/* ============================================================
   Ugly Co-op Deckbuilder — derived from
   /home/fre/GitHub/CursedGame/Ugly Co-op Deckbuilder Game/
     Ugly Deckbuilder Style Board.dc.html
   ============================================================
   Background  : CASINO FELT (radial dark green + 45° stripe overlay)
   Table chrome: PALETTE A — Basement Vegas
                 #0c3a22 felt · #1d7a45 felt-lit · #ffd21e gold
                 #ff2e88 magenta (danger) · #00e5ff cyan (mana) · #000 chrome
   Boss layer  : PALETTE B — Cursed Rainbow
                 #20002e void · #6a0dad grape · #aaff00 lime (primary CTA)
                 #ff6a00 orange (mana) · #ff00c8 magenta (curse) · #e8e8e8 text
   Type        : PAIRING 1
                 Luckiest Guy — card names, buttons, boss shouting
                 Verdana       — rules, GM narration, numbers
                 VT323         — logs, timestamps, fake system text
   ============================================================ */

/* Self-hosted, not linked: the container has no outbound internet, so a
   fonts.googleapis.com <link> silently falls back to cursive/monospace —
   which is exactly what the display type was rendering as. See
   public/fonts/README.md. */
@font-face {
  font-family: 'Luckiest Guy';
  src: url('/fonts/luckiest-guy.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'VT323';
  src: url('/fonts/vt323.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Palette A — table */
  --felt-bg: radial-gradient(ellipse at 50% 40%, #26a05c 0%, #12592f 55%, #08331c 100%),
             repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.07) 0 3px, transparent 3px 6px);
  --felt-bg-blend: multiply;
  --felt-deep: #0c3a22;
  --felt-mid: #1d7a45;
  --gold: #ffd21e;
  --magenta: #ff2e88;
  --cyan: #00e5ff;
  --chrome: #000;
  /* Palette B — boss layer */
  --boss-bg: #20002e;
  --boss-grape: #6a0dad;
  --boss-lime: #aaff00;
  --boss-orange: #ff6a00;
  --boss-curse: #ff00c8;
  --boss-text: #e3c6f5;
  /* Type */
  --font-display: 'Luckiest Guy', cursive;
  --font-body: Verdana, Geneva, sans-serif;
  --font-mono: 'VT323', monospace;
}

* { box-sizing: border-box; }

/* ============================================================
   GLOBAL TEXT-SELECTION SUPPRESSION
   Drag-to-select on cards is annoying — kill it everywhere except
   in the modal where players may want to copy flavor text.
   ============================================================ */
.card-frame, .hand-fan, .hand-fan-card, .hand-battlefield, .party-rail,
.party-avatar, .tab-bar, .tab, .hp-panel, .mana-pips, .lands-rail,
.turn-banner, .boss-strip, button, .land-chip, .status-chip, .play-grid {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;  /* suppress iOS long-press callout */
}
.card-frame.selectable, .modal-card, .modal-card * { user-select: text; -webkit-user-select: text; }

html, body {
  margin: 0; padding: 0; min-height: 100%;
  background: var(--felt-bg);
  background-blend-mode: var(--felt-bg-blend);
  box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.8);
  color: var(--boss-text);
  font-family: var(--font-body);
  overflow-x: hidden;
}

/* ============================================================
   Views + boss strip
   ============================================================ */
.view { display: none; padding: 16px; min-height: 60vh; }
.view.active { display: block; }

.boss-strip {
  /* PAINT SPLATTER over palette-B void — the template's boss background. */
  background: var(--boss-bg);
  background-image:
    radial-gradient(circle at 15% 30%, rgba(170, 255, 0, 0.35) 26px, transparent 27px),
    radial-gradient(circle at 85% 70%, rgba(255, 0, 200, 0.35) 34px, transparent 35px);
  border-bottom: 4px solid var(--boss-lime);
  padding: 8px;
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 9px;
  align-items: center;
  color: var(--boss-text);
}
.boss-portrait {
  width: 62px; height: 62px; flex: 0 0 auto;
  background: #0a0a0a; border: 4px outset var(--boss-curse);
  display: flex; align-items: center; justify-content: center; font-size: 34px;
}
.boss-info { min-width: 0; }
.boss-line { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.boss-hp-text { font-family: var(--font-body); font-weight: bold; font-size: 14px; color: #fff; }
.boss-next {
  margin-top: 4px; font-family: var(--font-mono); font-size: 15px; color: #fff;
  background: #000; border: 2px inset var(--boss-grape); padding: 2px 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.boss-next span { color: var(--boss-orange); }
.boss-name {
  font-family: var(--font-display);
  font-size: 17px;
  color: var(--boss-lime);
  text-shadow: 2px 2px 0 var(--chrome);
}
.boss-phase {
  font-family: var(--font-mono);
  font-size: 18px;
  color: var(--boss-text);
}

/* ============================================================
   BOSS HP — striped bar (palette B)
   The template says: badge = players, striped bar = boss,
   pip row = creatures (≤5 HP). Boss always gets the striped bar.
   ============================================================ */
.boss-hp, .boss-hp-bar {
  width: 100%;
  height: 15px;
  background: #3a0018;
  border: 2px solid var(--chrome);
  padding: 2px;
  position: relative;
  overflow: hidden;
}
.boss-hp-fill, .boss-hp-bar > div {
  height: 100%;
  background: repeating-linear-gradient(90deg, var(--magenta) 0 6px, #ff5aa0 6px 12px);
  transition: width 0.3s ease;
}
.boss-hp span, .boss-hp-bar span {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-weight: bold;
  font-size: 14px;
  color: #fff;
  text-shadow: 1px 1px 0 var(--chrome);
}

/* Boss screen gets the BIG boss hp */
.boss-hp-bar { height: 36px; margin: 16px 0; }
.boss-hp-bar span { font-family: var(--font-mono); font-size: 22px; }

/* ============================================================
   PLAYER HP — badge style (template: ❤️ + Verdana bold number,
   magenta outset border). Replaces the old hp-panel block.
   ============================================================ */
.hp-panel {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: #1a0010;
  border: 3px outset var(--magenta);
  padding: 4px 9px;
  align-self: start;
}
.hp-heart { font-size: 20px; }
.hp-big {
  font-family: var(--font-body);
  font-weight: bold;
  font-size: 19px;
  color: #fff;
  line-height: 1;
}
.hp-label {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--gold);
  letter-spacing: 0.3px;
}

/* ============================================================
   TURN INDICATOR — gold bevel + pulse ring on active player.
   Boss turn = whole screen gets 6px magenta inset border.
   ============================================================ */
.phase-banner {
  font-family: var(--font-display);
  font-size: 20px;
  color: #0c3a22;
  background: var(--gold);
  border: 4px outset #fff;
  padding: 6px 12px;
  text-align: center;
  letter-spacing: 0.3px;
}
.phase-banner.is-my-turn {
  animation: pulseTurn 1.6s ease-out infinite;
}

/* When the boss turn starts, app.js toggles a class on body */
body.boss-turn::before {
  content: '';
  position: fixed;
  inset: 0;
  border: 6px inset var(--boss-curse);
  pointer-events: none;
  z-index: 1000;
}

/* Active player indicator on the avatar/HP badge */
.hp-panel.is-active {
  border-color: var(--gold);
  border-style: outset;
  animation: pulseTurn 1.6s ease-out infinite;
}

/* ============================================================
   MANA — cyan orb + pip row.
   The template says: pick orb + pip row, drop the rest.
   ============================================================ */
.mana-orb {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #9ff6ff, #00a8c0);
  border: 3px solid var(--chrome);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 18px;
  color: #00304a;
  flex: 0 0 auto;
}
.mana-pips { display: inline-flex; gap: 3px; align-items: center; }
.mana-pip {
  width: 14px;
  height: 22px;
  background: var(--cyan);
  border: 2px solid var(--chrome);
  display: inline-block;
}
.mana-pip.spent { background: #123; }

/* ============================================================
   STATUS EFFECT CHIPS — 22px black-bordered emoji + stack count.
   ============================================================ */
.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  background: #000;
  border: 2px solid var(--chrome);
  padding: 2px 5px;
  font-family: var(--font-mono);
  font-size: 14px;
  color: #fff;
}
.status-chip .emoji { font-size: 22px; }

/* ============================================================
   CARDS — V1 CASINO BEVEL (already defined; kept here for clarity)
   ============================================================ */
.card-frame { display: inline-block; }
.card-bevel {
  background: linear-gradient(var(--felt-mid), var(--felt-deep));
  border: 6px outset var(--gold);
  box-shadow: 8px 8px 0 var(--chrome);
  cursor: pointer;
  transition: transform 120ms cubic-bezier(.34, 1.56, .64, 1);
  font-family: var(--font-body);
  color: #c0c0c0;
}
.card-frame.interactive .card-bevel:hover { filter: brightness(1.08); }
.card-frame.interactive .card-bevel:active { transform: scale(1.06) rotate(0deg); }

.card-header {
  display: flex; justify-content: space-between; align-items: center;
  padding: 5px 7px;
  background: var(--gold);
  border-bottom: 3px solid var(--chrome);
}
.card-name {
  font-family: var(--font-display);
  font-size: 13px;
  color: var(--felt-deep);
  letter-spacing: 0.5px;
  line-height: 1;
  text-shadow: none;
}
.card-md .card-name { font-size: 15px; }
.card-lg .card-name { font-size: 20px; }

.card-cost {
  width: 24px; height: 24px;
  background: var(--cyan);
  border: 2px solid var(--chrome);
  border-radius: 50%;
  font-family: var(--font-display);
  font-size: 13px;
  color: #000;
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
}
.card-md .card-cost { width: 26px; height: 26px; font-size: 15px; }
.card-lg .card-cost { width: 34px; height: 34px; font-size: 20px; }

.card-art {
  background: repeating-linear-gradient(45deg, #0f4a2b 0 10px, #12592f 10px 20px);
  display: flex; align-items: center; justify-content: center;
  border-bottom: 3px solid var(--chrome);
  text-shadow: 3px 3px 0 rgba(0, 0, 0, 0.5);
  line-height: 1;
}

.card-stats {
  display: flex; justify-content: space-between;
  padding: 6px 8px;
  background: #0a0a0a;
}
.card-atk, .card-hp {
  font-family: var(--font-body);
  font-weight: bold;
  font-size: 15px;
}
.card-md .card-atk, .card-md .card-hp { font-size: 19px; }
.card-lg .card-atk, .card-lg .card-hp { font-size: 24px; }
.card-atk { color: var(--magenta); }
.card-hp { color: #00e676; }

.card-flavor {
  padding: 6px 8px 9px;
  background: #0a0a0a;
  border-top: 2px dotted var(--gold);
  font-family: var(--font-body);
  font-style: italic;
  font-size: 11px;
  line-height: 1.35;
  color: #c0c0c0;
}
.card-md .card-flavor { font-size: 12px; }
.card-lg .card-flavor { font-size: 14px; padding: 8px 10px 12px; }

/* ============================================================
   MODAL — palette B backdrop (paint splatter bg + clip-art stars)
   ============================================================ */
.modal-backdrop {
  position: fixed; inset: 0;
  background: radial-gradient(circle at 20% 30%, rgba(170, 255, 0, 0.18) 18px, transparent 19px),
              radial-gradient(circle at 70% 60%, rgba(255, 0, 200, 0.18) 26px, transparent 27px),
              radial-gradient(circle at 45% 85%, rgba(255, 106, 0, 0.18) 14px, transparent 15px),
              rgba(0, 0, 0, 0.85);
  display: flex; align-items: center; justify-content: center;
  z-index: 100;
}
.modal-card {
  background: var(--boss-bg);
  border: 6px ridge var(--gold);
  padding: 20px;
  max-width: 90vw;
  text-align: center;
  color: var(--boss-text);
}

/* ============================================================
   BUTTONS — lime primary CTA (palette B), magenta secondary
   ============================================================ */
/* Gold, not lime: lime is palette B, which the style board reserves for the
   boss layer. Table-side actions are palette A, whose primary CTA is gold.
   START outranks JOIN by size, not by hue. */
.ugly-btn, .btn-play, .btn-close {
  background: var(--gold);
  color: var(--felt-deep);
  min-height: 44px;
  border: 3px solid var(--chrome);
  padding: 8px 16px;
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: 0.3px;
  box-shadow: 4px 4px 0 var(--chrome);
  cursor: pointer;
}
.ugly-btn.primary, .btn-play { background: var(--gold); color: var(--felt-deep); }
.ugly-btn.secondary, .btn-close { background: var(--magenta); color: #fff; }
.ugly-btn:active, .btn-play:active, .btn-close:active {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 var(--chrome);
}

/* ============================================================
   TOAST — black bg, dashed gold border, VT323
   ============================================================ */
.toast {
  background: #000;
  border: 3px dashed var(--gold);
  padding: 12px 16px;
  margin: 8px;
  max-width: 320px;
  font-family: var(--font-mono);
  font-size: 18px;
  color: var(--gold);
  animation: toastIn 0.4s ease-out;
}
.toast-error { border-color: var(--magenta); color: var(--magenta); }
@keyframes toastIn { from { transform: translateY(-20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

/* ============================================================
   RECONNECT
   ============================================================ */
#reconnect-strip {
  position: fixed; bottom: 0; left: 0; right: 0;
  background: var(--magenta); color: #fff;
  padding: 8px; text-align: center;
  font-family: var(--font-display);
  font-size: 16px;
  display: none;
  z-index: 200;
}
#reconnect-strip.active { display: block; }

/* ============================================================
   HAND SCREEN
   ============================================================ */
.hand-root { display: grid; grid-template-rows: auto 1fr auto auto; gap: 12px; padding: 16px; min-height: 80vh; }
.battlefield {
  background: rgba(0, 0, 0, 0.4);
  border: 3px dashed var(--gold);
  padding: 16px;
  min-height: 200px;
  display: flex; gap: 12px; flex-wrap: wrap;
  align-items: center; justify-content: center;
}
.placeholder { color: var(--gold); font-family: var(--font-mono); font-size: 20px; }

.lands-column { display: flex; gap: 4px; flex-wrap: wrap; }
.land-chip {
  font-size: 32px;
  padding: 4px;
  background: var(--felt-deep);
  border: 2px solid var(--gold);
  border-radius: 4px;
}

/* ============================================================
   LOBBY
   ============================================================ */
/* The lobby is a three-step sequence — pick a campaign, get the party in,
   start — so the style board's numbered section headers are load-bearing here
   rather than decorative. Everything was previously in raw inline flow, which
   is why the buttons sat on shared line boxes and collided with the headings. */
.lobby { display: flex; flex-direction: column; gap: 18px; }

/* ---- Marquee: the style board's own header lockup, section 0 ---- */
.marquee {
  border: 6px ridge var(--gold);
  background: linear-gradient(90deg, #ff00c8, #ff8a00, #ffe600, #00e676, #00b0ff, #b400ff, #ff00c8);
  background-size: 400px 100%;
  animation: rainbowSlide 6s linear infinite;
  padding: 6px;
  box-shadow: 0 10px 0 var(--chrome), 0 0 0 3px var(--chrome) inset;
}
.marquee-inner {
  background: #0a0a0a; padding: 14px 12px;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
  position: relative;
}
.marquee-logo {
  font-family: var(--font-display); font-size: 34px; line-height: 0.95;
  color: var(--gold); text-shadow: 4px 4px 0 var(--boss-curse);
}
.marquee-logo span { color: var(--cyan); }
.marquee-tag {
  font-family: var(--font-display); font-size: 14px; color: #00e676;
  text-shadow: 2px 2px 0 var(--chrome); transform: rotate(-3deg);
  border: 3px dashed var(--boss-curse); padding: 5px 10px; background: #1a0022;
}
.marquee-meta {
  font-family: var(--font-mono); font-size: 16px; color: #c0c0c0; line-height: 1.3;
}
.marquee-blink { animation: blinkTacky 1s steps(1) infinite; color: #ff3b3b; }
.marquee-star {
  position: absolute; right: 10px; top: 10px; font-size: 34px;
  animation: bounceStar 1.4s ease-in-out infinite;
}
@keyframes rainbowSlide { 0% { background-position: 0 0; } 100% { background-position: 400px 0; } }

/* ---- Steps ---- */
.step { display: flex; flex-direction: column; gap: 10px; }
.step-head {
  display: flex; align-items: center; gap: 10px; margin: 0;
  font-family: var(--font-display); font-size: 19px; color: #fff;
  text-shadow: 3px 3px 0 var(--boss-grape);
}
.step-no {
  flex: 0 0 auto; width: 28px; height: 28px;
  background: var(--gold); color: var(--felt-deep); border: 3px solid var(--chrome);
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; text-shadow: none;
}

/* ---- Campaign spec sheet, in place of a bare dropdown ---- */
.campaign-spec {
  background: #0a0a0a; border: 3px solid var(--gold); padding: 10px;
  display: flex; flex-direction: column; gap: 8px;
}
.campaign-spec.is-unplayable { border-color: #7a5a00; opacity: 0.72; }
.spec-empty {
  background: #0a0a0a; border: 3px dashed #6a8c78; padding: 14px;
  font-family: var(--font-mono); font-size: 17px; color: #8fbfa4;
}
.spec-name { font-family: var(--font-display); font-size: 17px; color: var(--gold); }
.spec-symbols { display: flex; flex-wrap: wrap; gap: 5px; }
.sym-chip {
  font-family: var(--font-mono); font-size: 14px; color: var(--boss-orange);
  border: 2px solid var(--boss-orange); padding: 0 5px; white-space: nowrap;
}
.spec-counts {
  display: flex; flex-wrap: wrap; gap: 10px;
  font-family: var(--font-mono); font-size: 16px; color: #c0c0c0;
}
.spec-blocked { font-family: var(--font-mono); font-size: 16px; color: var(--magenta); }

/* ---- Party slots: the play screen's sprites, plus the seats still open ---- */
.party-slots { display: flex; gap: 14px; padding: 4px 0 2px; }
.party-slot-empty {
  width: 50px; height: 50px; border-radius: 50%;
  border: 4px dashed #4d7a60; color: #4d7a60;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 22px;
}

/* ---- Inputs ---- */
.join-row { display: flex; gap: 8px; align-items: stretch; flex-wrap: wrap; }
.join-row .ugly-input { flex: 1 1 120px; min-width: 0; }
.join-row .emoji-input { flex: 0 0 64px; text-align: center; }
.join-row .ugly-btn { flex: 0 0 auto; }
.ugly-input {
  background: #000;
  color: var(--gold);
  border: 3px solid var(--gold);
  padding: 8px;
  font-family: var(--font-mono);
  font-size: 18px;
  min-height: 44px;
}

/* GENERATE is slow and system-flavoured, so it wears palette C's Win98 chrome
   — which also demotes it below the two ways to actually start playing. */
.sys-btn {
  background: #c0c0c0; color: #000; border: 3px outset #fff;
  font-family: Tahoma, Verdana, sans-serif; font-size: 14px;
  padding: 9px 12px; min-height: 44px; cursor: pointer; text-align: left;
}
.sys-btn:active { border-style: inset; }
.generate-progress { font-family: var(--font-mono); font-size: 16px; color: var(--cyan); }

/* ---- The two ways to start. Gold is palette A's primary CTA. ---- */
.cta-row { display: flex; gap: 10px; }
.cta {
  flex: 1; min-height: 56px; cursor: pointer;
  font-family: var(--font-display); font-size: 20px;
  border: 4px outset #fff; box-shadow: 5px 5px 0 var(--chrome);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.cta small { font-family: var(--font-mono); font-size: 14px; font-weight: normal; }
.cta-primary { background: var(--gold); color: var(--felt-deep); }
.cta-secondary { background: var(--felt-deep); color: var(--gold); border-color: var(--gold); }
.cta:active:not([disabled]) { transform: translate(2px, 2px); box-shadow: 3px 3px 0 var(--chrome); }
.cta[disabled] {
  background: #222; color: #7d7d7d; border: 3px inset #555;
  box-shadow: none; cursor: not-allowed;
}
.cta-hint { font-family: var(--font-mono); font-size: 16px; color: #8fbfa4; }
.error { color: var(--magenta); font-weight: bold; margin: 4px 0; font-family: var(--font-body); }

@media (prefers-reduced-motion: reduce) {
  .marquee { animation: none; }
  .marquee-blink, .marquee-star { animation: none; }
}

/* ============================================================
   BOSS VIEW — palette B
   ============================================================ */
.boss-view { padding: 16px; background: transparent; }
.boss-view h3 {
  font-family: var(--font-display);
  color: var(--boss-lime);
  font-size: 18px;
  letter-spacing: 0.3px;
  margin: 14px 0 6px;
  border-bottom: 2px dotted var(--boss-curse);
  padding-bottom: 3px;
}
.boss-portrait-big { font-size: 96px; text-align: center; margin: 16px 0; }
.boss-name-big {
  font-family: var(--font-display);
  color: var(--boss-lime);
  text-shadow: 3px 3px 0 var(--boss-curse);
  text-align: center;
  font-size: 28px;
  letter-spacing: 0.3px;
  margin: 8px 0;
}
.boss-abilities { display: flex; flex-direction: column; gap: 6px; }
.boss-ability {
  background: rgba(0, 0, 0, 0.5);
  padding: 6px 12px;
  margin: 4px 0;
  border-left: 4px solid var(--boss-curse);
  font-family: var(--font-body);
  color: var(--boss-text);
  font-size: 14px;
  line-height: 1.4;
}
.boss-pending {
  font-family: var(--font-mono);
  font-size: 24px;
  color: var(--gold);
}

/* ============================================================
   LOG STRIP — VT323 mono, dotted gold rules
   ============================================================ */
.log-strip {
  background: #000;
  padding: 8px;
  max-height: 280px;
  overflow-y: auto;
  border: 2px solid var(--gold);
  font-family: var(--font-mono);
  font-size: 14px;
}
.log-row { padding: 2px 0; border-bottom: 1px dotted var(--gold); }
.log-damage { color: var(--magenta); }
.log-heal { color: #00e676; }
.log-narration { color: var(--gold); }
.log-system { color: #888; font-style: italic; }

/* ============================================================
   TABLE OVERVIEW
   ============================================================ */
.table-view { padding: 16px; }
.table-row {
  display: grid; grid-template-columns: 100px 1fr; gap: 12px;
  margin: 12px 0; padding: 8px;
  background: rgba(0, 0, 0, 0.4);
  border: 2px solid var(--gold);
}
.table-label {
  font-family: var(--font-display);
  color: var(--gold);
  letter-spacing: 0.3px;
}
.table-cards { display: flex; gap: 6px; flex-wrap: wrap; }

/* ============================================================
   RARITY TINTS — gold for rare, magenta for curse (blinks)
   ============================================================ */
.rarity-curse { animation: blinkTacky 1s steps(1) infinite; }
.rarity-curse .card-bevel { border-color: var(--boss-curse); }
.rarity-rare .card-bevel { border-color: var(--gold); }
.rarity-uncommon .card-bevel { border-color: var(--cyan); }

/* ============================================================
   ANIMATIONS
   ============================================================ */
@keyframes pulseTurn {
  0%, 100% { box-shadow: 0 0 0 0 var(--gold); }
  70% { box-shadow: 0 0 0 12px rgba(255, 210, 30, 0); }
}
@keyframes blinkTacky { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0.15; } }
@keyframes bounceStar { 0%, 100% { transform: translateY(0) rotate(-8deg); } 50% { transform: translateY(-7px) rotate(8deg); } }
@keyframes toastIn { from { transform: translateY(-20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 600px) {
  .boss-name-big { font-size: 22px; }
}

/* ============================================================
   RESPONSIVE — auto-scale for Android (390×844) and PC.
   Uses clamp() / min() / vw so the same CSS works at any width.
   Mobile is the design target (template mockup is 390px wide).
   ============================================================ */

/* The #app container scales itself via container queries + clamp on padding.
   On wide screens we cap at ~720px so the layout still feels phone-like
   (the template is a phone, not a desktop dashboard). */
#app {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  min-height: 100vh;
  position: relative;
}

/* Boss strip + cards scale their font sizes with viewport width */
.boss-strip { padding: clamp(6px, 1.5vw, 10px) clamp(8px, 2vw, 16px); }
.boss-name { font-size: clamp(14px, 2vw, 17px); }
.boss-portrait { font-size: clamp(24px, 4vw, 32px); }
.boss-hp, .boss-hp-bar { height: clamp(18px, 3vw, 22px); }
.boss-hp-bar { height: clamp(28px, 4.5vw, 36px); }
.boss-hp span, .boss-hp-bar span { font-size: clamp(11px, 1.5vw, 14px); }
.boss-hp-bar span { font-size: clamp(16px, 2.5vw, 22px); }

/* HP badge, mana orb scale with vw */
.hp-panel { padding: clamp(3px, 0.8vw, 5px) clamp(6px, 1.5vw, 9px); gap: clamp(3px, 0.8vw, 5px); }
.hp-heart { font-size: clamp(15px, 2.5vw, 20px); }
.hp-big { font-size: clamp(14px, 2.5vw, 19px); }
.hp-label { font-size: clamp(11px, 2vw, 15px); }
.mana-orb { width: clamp(28px, 6vw, 38px); height: clamp(28px, 6vw, 38px); font-size: clamp(13px, 2.5vw, 18px); }
.mana-pip { width: clamp(10px, 2vw, 14px); height: clamp(16px, 3.5vw, 22px); }

/* Hand view: rails shrink + tighten on narrow screens */
@media (max-width: 720px) {
  .hand-body {
    padding: 10px 60px 320px 56px;  /* extra bottom for lifted deck (156px) + slider (50px) + margins */
  }
  .party-rail { right: 4px; top: 6px; gap: 6px; }
  .party-avatar { width: 42px; height: 42px; font-size: 14px; }
  .party-hp { font-size: 12px; }
  .own-hp-block { left: 4px; top: 6px; }
  .lands-rail { left: 4px; top: 100px; }
  .land-chip { width: 36px; height: 28px; font-size: 16px; }
  .hand-battlefield { min-height: 140px; padding: 8px; }
  .turn-label { font-size: 12px; padding: 4px 8px; }
  .end-turn-btn { font-size: 11px; padding: 6px 10px; min-width: 84px; }
  /* Narrow screens: tighter stride so 6–7 cards still fit horizontally
     without bleeding past the rails. Visual scale stays at 0.63× from
     the desktop default. */
  .hand-fan-deck { --fan-stride: 55px; height: 150px; }
  .inline-log { font-size: 12px; max-height: 90px; }
  .tab-bar { height: 36px; }
  .tab { font-size: 12px; }
  .tab-icon { flex-basis: 44px; font-size: 16px; }
}

@media (max-width: 420px) {
  /* Smallest phones — tighter still */
  .hand-body { padding: 8px 52px 300px 48px; }
  .party-avatar { width: 38px; height: 38px; font-size: 13px; }
  .hp-big { font-size: 13px; }
  .hand-fan-deck { --fan-stride: 42px; height: 140px; }
  .hand-fan { bottom: 140px; }
  .turn-banner { flex-wrap: wrap; gap: 4px; }
  .end-turn-btn { min-height: 40px; padding: 4px 8px; }
}

/* Wide screens (PC / tablet): rails move slightly inward; layout uses the
   full 720px container with comfortable spacing. */
@media (min-width: 900px) {
  #app {
    border-left: 1px solid rgba(0,0,0,0.3);
    border-right: 1px solid rgba(0,0,0,0.3);
  }
}

/* ============================================================
   HAND VIEW (template section 8)
   Tab bar + party rail + inline GM log + turn banner + END TURN.
   See Ugly Deckbuilder Style Board.dc.html lines 327-462.
   ============================================================ */

/* TAB BAR — 38px sticky, chrome bevel gray, gold-highlighted active tab */
.tab-bar {
  display: flex;
  background: #c0c0c0;
  border-bottom: 3px solid var(--chrome);
  height: 38px;
  position: sticky;
  top: 0;
  z-index: 10;
  margin: 0;
}
.tab {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 13px;
  color: #0c3a22;
  background: transparent;
  border: none;
  border-right: 3px solid var(--chrome);
  cursor: pointer;
  padding: 0;
  letter-spacing: 0.3px;
}
.tab:hover:not(.tab-active) { background: #a8a8a8; color: #000; }
.tab-active {
  background: var(--gold) !important;
  color: #0c3a22 !important;
}
.tab-icon {
  flex: 0 0 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  background: transparent;
  border: none;
  cursor: pointer;
}
.tab-icon.is-on { background: var(--gold); }

/* HAND BODY — padded container for absolutely-positioned rails */
.hand-body {
  position: relative;
  padding: 10px 70px 80px 60px;
  min-height: 60vh;
}

/* HAND PANELS — pre-rendered, swap visibility by class */
.hand-panel { display: none; }
.hand-panel.is-active { display: block; }

/* OWN HP BLOCK (top-left rail) */
.own-hp-block {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 4;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.mana-pips {
  display: inline-flex;
  gap: 3px;
  align-items: center;
  background: #0a0a0a;
  border: 3px outset var(--cyan);
  padding: 3px 6px;
}
.mana-count {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--cyan);
  margin-left: 4px;
}
.status-chips-row {
  display: flex;
  gap: 3px;
  flex-wrap: wrap;
}

/* LANDS RAIL (left, below own HP) */
.lands-rail {
  position: absolute;
  top: 112px;
  left: 8px;
  z-index: 4;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
}
.lands-label {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--gold);
  letter-spacing: 0.5px;
}
.land-chip {
  width: 44px;
  height: 34px;
  background: var(--felt-deep);
  border: 3px outset var(--gold);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;
}
.lands-empty {
  font-family: var(--font-mono);
  color: #555;
  font-size: 18px;
}

/* BATTLEFIELD (center) */
.hand-battlefield {
  background: rgba(0, 0, 0, 0.4);
  border: 3px dashed var(--gold);
  padding: 12px;
  min-height: 140px;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
}
/* Cards in play on the battlefield are scaled down so multiple creatures
   fit comfortably on screen. transform-origin center keeps them shrunk
   in place; aspect ratio is preserved by the scale. */
.hand-battlefield .card-frame {
  transform: scale(0.45);
  transform-origin: 50% 50%;
  margin: 0 -55px;       /* compensate for the scaled visual width so adjacent cards overlap nicely */
}
/* In the battlefield, the inner .card-bevel shadow is overkill at 0.45×
   (it becomes a faint smudge). Drop it; the card border is enough. */
.hand-battlefield .card-bevel {
  box-shadow: none;
}

/* PARTY RAIL (right) */
.party-rail {
  position: absolute;
  top: 10px;
  right: 8px;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.party-avatar {
  position: relative;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 4px outset #555;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 17px;
  color: #fff;
  text-shadow: 2px 2px 0 var(--chrome);
}
.party-avatar.is-active {
  border-color: var(--gold);
  border-style: outset;
  animation: pulseTurn 1.8s ease-out infinite;
}
.party-avatar.is-dying { filter: saturate(0.4); }
.party-avatar.is-npc { filter: grayscale(0.5); }
.party-initials {
  font-family: var(--font-display);
  font-size: 17px;
  line-height: 1;
}
.party-hp {
  position: absolute;
  left: -6px;
  top: -8px;
  font-family: var(--font-mono);
  font-size: 14px;
  background: var(--chrome);
  border: 2px solid var(--magenta);
  color: #fff;
  padding: 0 3px;
  line-height: 1.1;
  text-shadow: none;
}
.party-hp.low { color: #ff5a5a; border-color: #cc0000; }

/* INLINE GM LOG — toggled by 📜 */
.inline-log {
  position: relative;
  margin-top: 12px;
  background: var(--chrome);
  border: 3px inset var(--gold);
  padding: 6px 8px;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.45;
  color: #e8e8e8;
  max-height: 120px;
  overflow-y: auto;
}
.inline-log.is-hidden { display: none; }
.gm-prefix {
  font-family: var(--font-mono);
  font-size: 16px;
  color: var(--gold);
  margin-right: 6px;
}
.gm-log-row { padding: 1px 0; border-bottom: 1px dotted #333; }

/* TURN BANNER + END TURN BUTTON (template lines 412-415) */
.turn-banner {
  position: relative;
  margin-top: 12px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  z-index: 6;
}
.turn-label {
  font-family: var(--font-display);
  font-size: 15px;
  color: #0c3a22;
  background: var(--gold);
  border: 4px outset #fff;
  padding: 6px 12px;
  box-shadow: 4px 4px 0 var(--chrome);
  transform: rotate(-2deg);
  letter-spacing: 0.3px;
}
.turn-banner.is-my-turn .turn-label {
  animation: pulseTurn 1.6s ease-out infinite;
}
.end-turn-btn {
  font-family: var(--font-display);
  font-size: 13px;
  color: #fff;
  background: #cc0000;
  border: 4px outset #ff8a8a;
  padding: 8px 14px;
  min-height: 44px;
  min-width: 100px;
  cursor: pointer;
  box-shadow: 4px 4px 0 var(--chrome);
  letter-spacing: 0.3px;
}
.end-turn-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.end-turn-btn:active:not(:disabled) {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 var(--chrome);
}

/* HAND STACK — fixed bottom (template section 8 lines 418-419, restyled
   for narrow screens: horizontal poker-hand fan with overlap). Each
   .hand-fan-card is absolutely positioned at left: 50% (centered
   horizontally on the focused card), then translated horizontally by
   --fan-stride × offset. Back cards drop a bit so they peek behind the
   focused one without fully hiding it. Slider + counter let the player
   pick which card is on top. */
.hand-fan {
  /* Deck only — floats higher on screen so cards sit above the
     slider rather than fighting it for vertical space. */
  position: fixed;
  bottom: 150px;     /* above where the slider sits */
  left: 0;
  right: 0;
  padding: 6px 12px 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  /* No background/border — the deck sits in space, the slider is the
     fixed "control bar" at the very bottom. */
  z-index: 8;
}
.hand-fan-deck {
  /* Cards are 210px wide in the card layout (preserves template
     proportions), but rendered at 0.63× via .card-frame scale so the
     visual width is ~132px. Stride of 75px gives ~57px visible overlap
     per card. */
  position: relative;
  --fan-stride: 75px;
  width: 100%;
  height: 156px;     /* visual card height (~132) + 8px shadow + breathing room */
  overflow: visible;
}
.hand-fan-card {
  position: absolute;
  left: 50%;
  top: 4px;          /* tight to top of deck */
  margin-left: -105px;   /* card layout width (210) / 2 — keeps layout centered
                            even though the visual is only ~132px wide */
  transition: transform 220ms cubic-bezier(.2,.9,.3,1.2),
              z-index 0s linear 220ms;
  touch-action: none;
  will-change: transform;
}
/* Render the card at 0.63× of its layout size. transform-origin is the
   card's center, so it shrinks in place. This preserves the template's
   210×~190 aspect ratio while making the card visually smaller. */
.hand-fan-card .card-frame {
  transform: scale(0.63);
  transform-origin: 50% 50%;
}
/* Restore the template's chunky card-bevel shadow inside the hand-fan. */
.hand-fan-card .card-bevel {
  box-shadow: 8px 8px 0 var(--chrome);
}
.hand-fan-card.is-focused { z-index: 100; }

/* Slider — pinned to bottom: 0 as its own fixed element, ALWAYS
   accessible at the very bottom of the screen. The deck (above) can't
   move it. */
.hand-fan-slider {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  width: 100%;
  max-width: 100%;
  margin: 0;
  padding: 14px 12px 18px;
  background: linear-gradient(#0a0a0a00, #0a0a0acc 40%, #0a0a0a);
  border-top: 3px solid var(--gold);
  accent-color: var(--gold);
  cursor: pointer;
  z-index: 9;
  /* Force a touch-friendly hit area on mobile native slider thumbs. */
  touch-action: manipulation;
}
.hand-fan-slider::-webkit-slider-thumb {
  background: var(--gold);
  border: 2px solid var(--chrome);
  width: 24px;
  height: 24px;
}
.hand-fan-slider::-moz-range-thumb {
  background: var(--gold);
  border: 2px solid var(--chrome);
  width: 24px;
  height: 24px;
}

/* "3 / 7" counter — lives inside the deck (top-right corner) so it never
   overlaps the slider. pointer-events: none makes it purely decorative;
   any touch that lands on its pixels falls through to whatever is behind
   it (the deck or, if the deck is short, the slider). */
.hand-fan-counter {
  position: absolute;
  top: -4px;
  right: 4px;
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--gold);
  text-shadow: 1px 1px 0 var(--chrome);
  z-index: 110;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}
.hand-fan .placeholder {
  margin: 60px 0 0;
  color: var(--magenta);
  font-family: var(--font-mono);
  font-size: 14px;
}

/* ============================================================
   DRAG-AND-DROP visual states
   ============================================================ */

/* Source card while dragging — fades out so the ghost clone stands out. */
.card-frame.is-dragging {
  opacity: 0.35;
  cursor: grabbing !important;
}
.card-frame { cursor: grab; }

/* Floating ghost that follows the pointer on touch devices. Desktop HTML5
   DnD shows its own native ghost; this clone is for pointer-event fallback. */
.drag-ghost {
  position: fixed;
  pointer-events: none;
  z-index: 1000;
  transform: translate(-50%, -50%) scale(1.05) rotate(-3deg);
  filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.55));
  transition: transform 60ms ease-out;
  will-change: transform, left, top;
}

/* Battlefield zone glows when a card is dragged over it. */
.hand-battlefield.drag-over {
  border-color: var(--boss-lime);
  background: rgba(170, 255, 0, 0.12);
  animation: pulseDrop 0.6s ease-in-out infinite alternate;
}
@keyframes pulseDrop {
  from { box-shadow: inset 0 0 0 0 var(--boss-lime); }
  to   { box-shadow: inset 0 0 24px 6px rgba(170, 255, 0, 0.5); }
}

/* ============================================================
   PLAY SCREEN — style board section 8, "YOUR TURN" (390×844)
   The template stacks: boss strip / HUD rails / creatures /
   GM log / turn banner / hand fan. Its body uses absolute
   positioning; these are grid rows instead, because absolute
   children are what put the HP panel on top of the battlefield.
   ============================================================ */
.play-grid {
  display: grid;
  grid-template-rows: auto 1fr auto auto auto;
  gap: 8px;
  min-height: calc(100vh - 140px);
}
/* Grid and flex children default to min-width:auto, so one long unbreakable
   token (a card id in the GM log, say) can push a row wider than the phone and
   drag the whole layout with it. Every row is pinned to the track instead. */
.play-grid > * { min-width: 0; max-width: 100%; }

/* ---- HUD: own vitals left, party sprites right (template rails) ---- */
/* Vitals sit on one line rather than stacked — the second row cost the board
   ~40px of height on a 844px screen, which is a creature row. */
.play-hud { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.hud-self { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }
.hud-party { margin-left: auto; display: flex; gap: 12px; padding: 4px 8px 0 0; }

.hp-badge {
  display: inline-flex; align-items: center; gap: 5px;
  background: #0a0a0a; border: 3px outset var(--magenta); padding: 3px 8px;
  font-family: var(--font-body); font-size: 17px; color: #fff;
}
.hp-badge b { font-weight: bold; }
.hp-badge i { font-style: normal; color: #b98; font-size: 13px; }

.mana-badge {
  display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap;
  background: #0a0a0a; border: 3px outset var(--cyan); padding: 3px 8px;
}
.mana-badge .mana-pip {
  width: 10px; height: 16px; background: var(--cyan);
  border: 2px solid var(--chrome); display: inline-block;
}
.mana-badge .mana-pip.is-spent { background: #123; }
.mana-count { font-family: var(--font-mono); font-size: 16px; color: var(--cyan); }
.mana-sym {
  font-family: var(--font-mono); font-size: 13px; color: var(--boss-orange);
  border: 1px solid var(--boss-orange); padding: 0 3px;
}

.status-chips { display: flex; gap: 3px; }
.status-chips .status-chip {
  font-size: 16px; background: #0a0a0a;
  border: 2px solid var(--boss-lime); padding: 1px 3px;
}

/* Party sprites: 50px, initials + emoji overlay + HP tag, gold bevel active. */
.party-sprite {
  position: relative; width: 50px; height: 50px; border-radius: 50%;
  border: 4px outset #555; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 17px; color: #fff;
  flex: 0 0 auto; filter: saturate(0.7);
}
.party-sprite.is-active {
  border-color: var(--gold); filter: none;
  animation: pulseTurn 1.8s ease-out infinite;
}
.party-sprite.is-dying { filter: grayscale(0.5); }
.party-sprite.is-dead { filter: grayscale(1) brightness(0.6); }
.sprite-emoji { position: absolute; right: -5px; bottom: -5px; font-size: 17px; }
.sprite-hp {
  position: absolute; left: -6px; top: -8px;
  font-family: var(--font-mono); font-size: 14px;
  background: #000; border: 2px solid var(--slot, var(--magenta));
  color: #fff; padding: 0 3px; line-height: 1.2;
}

/* ---- BOARD: a camera viewport. touch-action:none so the browser
        does not steal pan/pinch before boardView.js sees them. ---- */
.play-board {
  position: relative; overflow: hidden; min-height: 210px;
  border: 3px inset rgba(0, 0, 0, 0.5);
  touch-action: none; cursor: grab;
}
.play-board:active { cursor: grabbing; }
/* Two territories, boss above and yours below, divided by a hard rule. The
   boss side carries palette B so whose creatures are whose is a colour
   decision, not a position-memory one. */
.board-canvas {
  display: flex; flex-direction: column; gap: 8px; padding: 8px;
  width: 100%;   /* fits the viewport at scale 1; the camera moves it from there */
  transform-origin: 0 0; will-change: transform;
}
.boss-field {
  background: rgba(32, 0, 46, 0.55);
  border: 2px solid var(--boss-grape);
  padding: 5px 6px 7px;
}
.field-label {
  font-family: var(--font-mono); font-size: 14px; color: var(--boss-lime);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 4px;
}
.field-row { display: flex; flex-wrap: wrap; gap: 6px; min-height: 30px; align-items: flex-start; }
.field-rule {
  height: 0; border-top: 3px dashed rgba(255, 210, 30, 0.5);
}
.my-side { display: flex; align-items: flex-start; gap: 10px; }

/* Opposing creatures wear the boss palette. */
.perm-tile.is-opposing {
  background: linear-gradient(var(--boss-grape), #2a0140);
  border-color: var(--boss-lime);
  box-shadow: 4px 4px 0 var(--chrome);
}
.perm-tile.is-opposing .perm-art { background: #1a0022; }
.perm-tile.is-opposing .perm-name { color: var(--boss-lime); }

/* position is reset explicitly: the outgoing hand.js screen pins a .lands-rail
   at `position: absolute; top: 112px`, and this rule reuses the class name. It
   is the same trap .party-hp fell into — without the reset the rail leaves the
   flow and lands on top of the boss's board. */
.lands-rail { position: static; display: flex; flex-direction: column; gap: 6px; flex: 0 0 auto; }
.rail-label { font-family: var(--font-mono); font-size: 14px; color: var(--gold); }
.rail-empty { font-family: var(--font-mono); font-size: 16px; color: #6a8c78; }
.land-tile {
  width: 44px; height: 34px; background: var(--felt-deep);
  border: 3px outset var(--gold);
  display: flex; align-items: center; justify-content: center; font-size: 19px;
}
.land-tile.is-tapped { transform: rotate(90deg); filter: brightness(0.6); }

.creature-field {
  flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px;
  justify-content: center; align-content: flex-start;
}
.field-empty { font-family: var(--font-mono); font-size: 17px; color: #6a8c78; padding: 20px 0; }

/* Creature mini-card — 78px, the template's board treatment. */
.perm-tile {
  position: relative; width: 78px; height: 106px; flex: 0 0 auto; overflow: hidden;
  background: linear-gradient(var(--felt-mid), var(--felt-deep));
  border: 4px outset var(--gold); box-shadow: 4px 4px 0 var(--chrome);
}
.perm-art {
  height: 48px; font-size: 28px;
  background: repeating-linear-gradient(45deg, #0f4a2b 0 8px, #12592f 8px 16px);
  border-bottom: 2px solid var(--chrome);
  display: flex; align-items: center; justify-content: center;
  text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.5);
}
.perm-name {
  font-family: var(--font-display); font-size: 8.5px; letter-spacing: -0.2px;
  color: var(--gold); text-align: center; padding: 3px 2px; min-height: 15px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.perm-stats {
  display: flex; justify-content: space-between; padding: 2px 4px 3px;
  font-family: var(--font-body); font-weight: bold; font-size: 11px;
}
.perm-atk { color: var(--magenta); }
.perm-hp { color: #00e676; }
/* Curses arrive from the boss's palette — "pasted in from a worse website". */
.perm-tile.is-cursed { background: linear-gradient(var(--boss-grape), #2a0140); border-color: var(--boss-curse); }
.perm-tile.is-cursed .perm-art { background: #1a0022; }
.perm-tile.is-cursed .perm-name { color: var(--boss-curse); text-decoration: line-through; }

/* A rotation does not change the layout box, so a tapped 78x106 tile lays
   across 106px and shoved its neighbour — and the row below it — out of the
   way. The margin reserves the footprint the rotation actually occupies. */
.perm-tile.is-tapped { transform: rotate(90deg); margin: 0 14px; }
.perm-tile.is-sick { opacity: 0.7; }
.perm-tile.is-selectable { cursor: pointer; outline: 3px dashed #00e676; outline-offset: 2px; }
.perm-tile.is-selected { outline: 4px solid var(--gold); outline-offset: 3px; transform: translateY(-6px) rotate(-3deg); }
.perm-tile.is-selected.is-tapped { transform: rotate(90deg) translateY(-6px); margin: 0 14px; }
.perm-badge { position: absolute; top: -8px; right: -8px; font-size: 16px; }
.perm-damage {
  position: absolute; bottom: -8px; right: -8px; background: #cc0000; color: #fff;
  font-family: var(--font-mono); font-size: 14px; padding: 0 4px; border: 2px solid var(--chrome);
}

/* Camera chrome — bevel tiles, same idiom as the lands rail. */
.board-zoom { position: absolute; right: 6px; bottom: 6px; display: flex; gap: 4px; }
.zoom-btn {
  min-width: 34px; height: 30px; background: var(--felt-deep); color: var(--gold);
  border: 3px outset var(--gold); font-family: var(--font-mono); font-size: 17px;
  line-height: 1; cursor: pointer; padding: 0 5px;
}
.zoom-btn:active { border-style: inset; }
.zones {
  position: absolute; left: 6px; bottom: 6px;
  font-family: var(--font-mono); font-size: 15px; color: #8fbfa4;
  background: rgba(0, 0, 0, 0.45); padding: 1px 5px; pointer-events: none;
}

/* ---- GM log: black box, gold inset, VT323 prefix ---- */
.gm-log {
  background: #000; border: 3px inset var(--gold); padding: 6px 8px;
  font-family: var(--font-body); font-size: 12.5px; line-height: 1.45; color: #e8e8e8;
  max-height: 58px; overflow-y: auto;
  overflow-wrap: anywhere;
}
.gm-prefix { font-family: var(--font-mono); font-size: 16px; color: var(--gold); margin-right: 5px; }

/* ---- Turn banner: gold bevel + red END TURN, per the template ---- */
.phase-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.phase-name {
  font-family: var(--font-display); font-size: 15px; color: var(--felt-deep);
  background: var(--gold); border: 4px outset #fff; padding: 6px 12px;
  box-shadow: 4px 4px 0 var(--chrome); transform: rotate(-2deg);
}
.phase-primary {
  font-family: var(--font-display); font-size: 13px; color: #fff;
  background: #cc0000; border: 4px outset #ff8a8a; padding: 8px 14px;
  min-height: 44px; box-shadow: 4px 4px 0 var(--chrome); cursor: pointer;
}
.phase-primary[disabled] {
  background: #222; color: #c0c0c0; border: 3px inset #555;
  box-shadow: none; cursor: default;
}

/* ---- Hand: 92px tilted cards over the template's fade + gold rule ---- */
.play-hand {
  background: linear-gradient(#0a0a0a00, #0a0a0acc 40%, #0a0a0a);
  border-top: 3px solid var(--gold); padding: 10px 0 4px;
}
.hand-strip {
  display: flex; gap: 8px; padding: 6px 10px 10px;
  overflow-x: auto; overflow-y: hidden; align-items: flex-end;
}
.hand-strip::-webkit-scrollbar { height: 6px; }
.hand-card {
  width: 92px; flex: 0 0 auto;
  background: linear-gradient(var(--felt-mid), var(--felt-deep));
  border: 4px outset var(--gold); box-shadow: 5px 5px 0 var(--chrome);
  transform: rotate(var(--tilt, 0deg)); transform-origin: 50% 120%;
  transition: transform 120ms cubic-bezier(.34, 1.56, .64, 1);
  cursor: pointer;
  /* Horizontal pans scroll the hand; vertical ones are ours. Without this the
     browser claims the gesture and fires pointercancel on the first move, so
     "drag up to play" died on touch while still working with a mouse. */
  touch-action: pan-x;
}
.hand-card:hover { transform: rotate(0deg) scale(1.06); }
/* The ghost is a clone, so it carries .hand-card — whose transform would
   otherwise win on source order and leave the ghost offset from the finger. */
.hand-card.drag-ghost {
  transform: translate(-50%, -50%) rotate(-4deg) scale(1.05);
  transition: none;
}
.hand-art {
  height: 54px; font-size: 30px;
  background: repeating-linear-gradient(45deg, #0f4a2b 0 8px, #12592f 8px 16px);
  border-bottom: 2px solid var(--chrome);
  display: flex; align-items: center; justify-content: center;
}
.hand-name {
  font-family: var(--font-display); font-size: 10px; color: var(--gold);
  text-align: center; padding: 3px 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hand-stats {
  display: flex; justify-content: space-between; padding: 2px 4px 4px;
  font-family: var(--font-body); font-weight: bold; font-size: 11px;
}
.hand-atk { color: var(--magenta); }
.hand-cost { color: var(--cyan); }
.hand-card.is-unaffordable { filter: grayscale(0.8) brightness(0.55); }
.hand-card.is-dragging { opacity: 0.35; }
.hand-hint {
  text-align: center; font-family: var(--font-mono); font-size: 15px; color: #8fbfa4;
}
.play-board.drag-over { outline: 4px dashed #00e676; outline-offset: -4px; }

@media (prefers-reduced-motion: reduce) {
  .party-sprite.is-active { animation: none; }
  .hand-card { transition: none; }
}

/* ---- Full game log, opened by tapping the GM line ---------------------- */
/* The GM line only shows the latest beat; the boss acts between your turns,
   so the log is where you see what it actually did. */
.gm-log { cursor: pointer; display: flex; align-items: baseline; gap: 6px; }
.gm-more { margin-left: auto; color: #ffd21e; font-family: VT323, monospace; flex: 0 0 auto; }
.gm-log:active { filter: brightness(1.2); }

.log-panel {
  width: min(94vw, 460px); max-height: 78vh; display: flex; flex-direction: column;
  background: #0a0a0a; border: 5px outset #ffd21e; box-shadow: 8px 8px 0 #000;
}
.log-panel-head {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  background: #ffd21e; border-bottom: 3px solid #000; flex: 0 0 auto;
}
.log-panel-title { font-family: 'Luckiest Guy', cursive; font-size: 16px; color: #0c3a22; }
.log-panel-head .btn-close { margin-left: auto; min-width: 44px; min-height: 36px; }
.log-panel-body { overflow-y: auto; padding: 6px 8px; -webkit-overflow-scrolling: touch; }

.log-row {
  display: grid; grid-template-columns: auto auto 1fr; gap: 6px; align-items: baseline;
  padding: 5px 2px; border-bottom: 1px dotted #333;
  font-family: Verdana, Geneva, sans-serif; font-size: 12.5px; line-height: 1.4; color: #e8e8e8;
}
.log-turn { font-family: VT323, monospace; font-size: 14px; color: #8fbfa4; }
.log-who { font-weight: bold; color: #00e5ff; }
/* The boss gets the loud palette so its turns are scannable at a glance —
   spotting what it did is the whole reason this panel exists. */
.log-boss .log-who { color: #ff2e88; }
.log-narration .log-gm { font-family: VT323, monospace; font-size: 14px; color: #ffd21e; }
.log-narration .log-text { font-style: italic; color: #c9a8de; }
.log-empty { padding: 14px; text-align: center; font-family: VT323, monospace; color: #8fbfa4; }
