/* Mythraven — the hunt table.
   Source file. Copied verbatim into wiki/dist/play/ by build_play() in wiki/build.py. */

@import url('https://fonts.googleapis.com/css2?family=Cinzel+Decorative:wght@700;900&family=Cinzel:wght@400;600;700&family=Spectral:ital,wght@0,400;0,500;0,600;1,400&display=swap');

/* ---------------------------------------------------------------------------
   Tokens. The first block is the wiki's own palette, unchanged — this surface
   joins that world rather than starting a new one. The second block is what a
   table adds: the leather it is played on, the brass the counters are cut from,
   and three state roles.

   The state roles are a mapping, not decoration: gold is always you, blood is
   always the thing trying to kill you, raven is always the resource you spend.
   Every bar that uses them also prints its number, because a palette this dark
   cannot be the only carrier of "you are about to die".
--------------------------------------------------------------------------- */
:root {
  --bg: #0a0810;
  --card: #1a1424;
  --gold: #c9a24a;
  --gold-bright: #e8c876;
  --raven: #8a76c9;
  --text: #e6e0f0;
  --dim: #a99dc0;
  --border: #2e2540;
  --border-lit: #4a3a66;

  --leather: #17111f;
  --leather-lo: #0c0912;
  --brass-dark: #6b4f26;
  /* The lightest brass that still clears 4.5:1 as small text on the scroll's ground.
     --brass-dark is a border colour and fails badly the moment it carries a word. */
  --brass-text: #b08b3e;
  --brass-edge: rgba(255, 224, 160, 0.22);
  --blood: #a83a3a;
  --blood-dim: #5e2222;

  --rule: 1px solid var(--border);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  /* A mesma escala da wiki, oito degraus. Antes eram dezenove tamanhos soltos aqui,
     doze deles entre 0,63 e 0,95rem -- e uma faixa que o olho lê como "tudo do mesmo
     tamanho" enquanto desmancha a hierarquia que a tela precisa ter.

     A diferença para a wiki é deliberada e é uma só: lá a escala inteira cresce acima
     de 821px, porque prosa se lê de mais longe numa tela grande. Aqui não cresce. Esta
     é uma tela de jogo com contagem, barra e ficha em posição fixa; tipo que cresce com
     o breakpoint quebra a conta do layout em vez de melhorar a leitura.

     `--fs-nano` existe porque versal do Cinzel com 0,2em de entreletra ocupa muito mais
     espaço aparente do que o tamanho diz -- é o degrau das etiquetas gravadas, e é um
     papel de verdade, não um arredondamento. */
  --fs-nano: 0.7rem;       /* etiqueta gravada em versal: turno, HEALTH, ATTACK */
  --fs-micro: 0.8rem;      /* rótulo de ficha, legenda do contador, link do cabeçalho */
  --fs-small: 0.92rem;     /* linha do log, texto de apoio */
  --fs-body: 1.05rem;      /* texto corrido */
  --fs-large: 1.25rem;     /* nome do personagem, título do slot vazio */
  --fs-section: 1.55rem;   /* reservado: nenhum h2 nesta tela ainda */
  --fs-title: 2.2rem;
  --fs-hero: clamp(2.4rem, 9vw, 4.2rem);   /* a marca na tela de entrada */
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  color: var(--text);
  font-family: 'Spectral', Georgia, serif;
  font-size: var(--fs-body);
  line-height: 1.6;
  background-color: var(--leather-lo);
  /* The table itself: a real photographed surface (docs/art_samples/lore/hunt_table.png,
     with its generation prompt beside it), worn leather with a felt inlay and a tarnished
     brass rim. CSS gradients could only ever suggest this; grain, creases and the way the
     light dies in the leather are what makes it read as a place rather than a colour.
     `cover` crops it to the felt centre on a phone and lets the leather border show on a
     wide screen — the same surface, seen from further back.

     The plum layer above it is not decoration. The photograph runs warmer and redder than
     this world does, and correcting that in CSS keeps the art as material rather than as
     a colour decision. */
  background-image:
    radial-gradient(ellipse 70% 55% at 18% -5%, rgba(201, 162, 74, 0.10), transparent 70%),
    linear-gradient(158deg, rgba(23, 17, 31, 0.80) 0%, rgba(12, 9, 18, 0.90) 55%, rgba(8, 6, 12, 0.95) 100%),
    url('/assets/lore/hunt_table.webp');
  background-size: auto, auto, cover;
  background-position: center, center, center;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

/* The candle. One light source is the rule the whole design is built on, so it is the one
   thing on the page that is alive when nothing is happening: a slow warm swell over the
   upper-left corner, eighteen seconds a cycle, far too slow to notice directly and exactly
   what makes the surface read as lit rather than printed. It is also the page's only
   ambient motion — everything else moves because the player did something. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 55% 45% at 16% 4%, rgba(255, 214, 150, 0.11), transparent 72%);
  animation: candle 18s ease-in-out infinite;
}
@keyframes candle {
  0%, 100% { opacity: 0.55; transform: translate3d(0, 0, 0) scale(1); }
  38%      { opacity: 1;    transform: translate3d(0.6%, -0.4%, 0) scale(1.05); }
  64%      { opacity: 0.72; transform: translate3d(-0.4%, 0.5%, 0) scale(0.99); }
}

/* Worn grain in the leather. Two offset dot fields, so it never tiles visibly. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.55;
  background-image:
    repeating-radial-gradient(circle at 20% 30%, rgba(255, 255, 255, 0.014) 0, transparent 2px),
    repeating-radial-gradient(circle at 70% 80%, rgba(0, 0, 0, 0.22) 0, transparent 3px);
  background-size: 5px 5px, 9px 9px;
}

/* The parts of the browser nobody draws. They ship with defaults that belong
   to no design system, and on a surface this committed they are the leak. */
::selection { background: rgba(201, 162, 74, 0.32); color: var(--gold-bright); }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.35); }
::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, #40311c, #241a10);
  border: 1px solid var(--brass-dark);
  border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover { background: linear-gradient(180deg, #5b452a, #33260f); }
* { scrollbar-color: #40311c rgba(0, 0, 0, 0.35); scrollbar-width: thin; }

:focus-visible {
  outline: 2px solid var(--gold-bright);
  outline-offset: 3px;
  border-radius: 3px;
}

a { color: var(--raven); text-underline-offset: 3px; text-decoration-color: rgba(138, 118, 201, 0.5); }
a:hover { color: var(--gold-bright); text-decoration-color: var(--gold); }

h1, h2, h3, .plate-name, .counter, .stamp { font-family: 'Cinzel', Georgia, serif; }

/* ---------------------------------------------------------------------------
   Brass. One material, three sizes: the counters you push, the small chips on
   the sheet, and the plate under the monster's name. Everything brass shares
   this bevel so the table reads as one set of pieces.
--------------------------------------------------------------------------- */
.brass {
  position: relative;
  border: 2px solid var(--brass-dark);
  border-radius: 7px;
  background-image:
    linear-gradient(160deg, rgba(28, 20, 38, 0.86), rgba(14, 10, 20, 0.93)),
    var(--metal, none);
  background-size: cover, 260px 260px;
  background-position: center, 20% 30%;
  background-blend-mode: normal, luminosity;
  box-shadow:
    inset 0 1px 0 var(--brass-edge),
    inset 0 -3px 5px rgba(0, 0, 0, 0.6),
    0 3px 7px rgba(0, 0, 0, 0.45);
}

/* ---------------------------------------------------------------------------
   Shell
--------------------------------------------------------------------------- */
#app { position: relative; z-index: 1; min-height: 100dvh; display: flex; flex-direction: column; }

.view { display: none; flex: 1; flex-direction: column; }
.view[data-active] { display: flex; }

.head-link {
  font-family: 'Cinzel', Georgia, serif;
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--dim);
  text-decoration: none;
  padding: 0.4rem 0.6rem;
  border-radius: 5px;
}
.head-link:hover { color: var(--gold-bright); background: rgba(201, 162, 74, 0.08); }

/* ---------------------------------------------------------------------------
   Sign-in. Sober on purpose: no demo of a fight this build does not yet run.
--------------------------------------------------------------------------- */
#view-signin {
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 3rem 1.5rem 4rem;
  gap: 0;
}
.signin-mark {
  font-family: 'Cinzel Decorative', Cinzel, serif;
  font-size: var(--fs-hero);
  font-weight: 900;
  letter-spacing: 0.06em;
  margin: 0;
  color: var(--gold-bright);
  text-shadow: 0 0 60px rgba(201, 162, 74, 0.28), 0 2px 0 rgba(0, 0, 0, 0.8);
}
.signin-rule {
  width: min(340px, 70vw);
  height: 1px;
  margin: 1.6rem auto;
  border: 0;
  background: linear-gradient(90deg, transparent, var(--brass-dark) 20%, var(--gold) 50%, var(--brass-dark) 80%, transparent);
}
.signin-line {
  max-width: 34ch;
  margin: 0 auto 2.4rem;
  color: var(--dim);
  font-size: var(--fs-body);
  line-height: 1.7;
}
.signin-widget { min-height: 48px; display: flex; justify-content: center; }
.signin-alt { margin-top: 2rem; font-size: var(--fs-small); color: var(--dim); }

/* ---------------------------------------------------------------------------
   The felt. The hunt panel's own composition: the monster card wide on the
   left, the turn scroll at the right, the counters across the near edge. The
   character sheet that used to sit here is gone from this panel on purpose —
   it became the standing HUD above every panel, so the table stopped carrying
   a second, staler copy of the same numbers.
--------------------------------------------------------------------------- */
.felt {
  flex: 1;
  display: grid;
  gap: 1.25rem;
  padding: 1.25rem;
  width: min(1440px, 100%);
  margin: 0 auto;
  grid-template-columns: 1fr;
  align-content: start;
}

@media (min-width: 960px) {
  .felt {
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 1.75rem;
    padding: 1.75rem 1.75rem 0;
    align-items: start;
  }
  /* The log runs the full height of the card, so the right side reads as a rail
     being written down rather than a note stuck to the corner of the table. */
  .scroll { align-self: stretch; }
  .scroll-body { max-height: none; }
}

/* --- gauges, shared by the HUD, the sheet and the monster plate ----------- */
.gauge { margin-bottom: 0.95rem; }
.gauge-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.3rem;
  font-family: 'Cinzel', Georgia, serif;
  font-size: var(--fs-nano);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--dim);
}
.gauge-head b {
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
/* An inset channel cut into the sheet, not a floating pill. */
.gauge-track {
  position: relative;
  height: 11px;
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.55);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.75), inset 0 -1px 0 rgba(255, 255, 255, 0.04);
  overflow: hidden;
}
/* Scaled, not resized. A gauge that animates its width makes the browser lay the
   page out again on every frame of every turn; scaleX runs on the compositor and
   leaves the fill's vertical gradient untouched. */
.gauge-fill {
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left center;
  border-radius: 1px;
  transition: transform 0.55s var(--ease);
}
.gauge-hp .gauge-fill { background: linear-gradient(180deg, var(--gold-bright), #9c7a2e); }
.gauge-energy .gauge-fill { background: linear-gradient(180deg, #a695dd, #5c4b91); }
.gauge-foe .gauge-fill { background: linear-gradient(180deg, #c25050, var(--blood-dim)); }
.gauge-hp.is-low .gauge-fill { background: linear-gradient(180deg, #d05c5c, var(--blood-dim)); }

.ailments { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 1.05rem; }
.ailment {
  display: inline-flex;
  align-items: center;
  gap: 0.34rem;
  padding: 0.22rem 0.5rem;
  border: 1px solid var(--blood-dim);
  border-radius: 3px;
  background: rgba(168, 58, 58, 0.12);
  font-size: var(--fs-nano);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #e4b0b0;
}
.ailment svg { width: 12px; height: 12px; }
.ailment b { font-variant-numeric: tabular-nums; color: #fff; font-weight: 600; }

/* --- the board: the monster's card, laid on the felt ---------------------- */
.board { display: flex; flex-direction: column; gap: 1.1rem; min-width: 0; }

.foe-card {
  position: relative;
  width: 100%;
  max-width: 640px;
  margin-inline: auto;
  border: 1px solid var(--border-lit);
  border-radius: 5px;
  background: linear-gradient(170deg, #221a30, #0f0b17);
  box-shadow:
    0 26px 60px rgba(0, 0, 0, 0.62),
    0 3px 0 rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.05);
  overflow: hidden;
  /* Laid down by a hand, not printed by a press. */
  transform: rotate(-0.35deg);
}
.foe-art {
  position: relative;
  aspect-ratio: 4 / 3;
  /* On a wide desk the card would otherwise run the full width of the stage and the
     square plate inside it would swim in blur. Holding the card to a hand's width keeps
     the figure large and the fill thin. */
  max-height: min(58vh, 520px);
  overflow: hidden;
  background: #0b0810;
}
.foe-art-back {
  position: absolute;
  /* Past the edges, so the blur has stock to spread and never shows a seam. */
  inset: -12%;
  background: center/cover no-repeat;
  filter: blur(30px) saturate(0.6) brightness(0.4);
  transform: scale(1.06);
}
.foe-art-fig {
  position: absolute;
  inset: 0;
  margin: auto;
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  /* Cut out of the ground rather than pasted onto it. */
  filter: drop-shadow(0 12px 22px rgba(0, 0, 0, 0.72));
}
.foe-art::after {
  /* The card's own varnish, and the candle catching its top-left corner. */
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 60% 50% at 22% 8%, rgba(255, 226, 170, 0.14), transparent 65%),
    linear-gradient(180deg, transparent 45%, rgba(10, 8, 16, 0.86) 100%);
}
.foe-plate {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.85rem 1.1rem 1rem;
  border-top: 1px solid var(--brass-dark);
  background: linear-gradient(180deg, rgba(20, 15, 28, 0.96), rgba(10, 8, 16, 0.98));
}
.foe-plate-text { flex: 1; min-width: 0; }
.plate-name {
  margin: 0;
  font-size: var(--fs-large);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--gold-bright);
  /* Engraved: cut down into the plate, with a thin glint on the upper edge. */
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.95), 0 -1px 0 rgba(255, 224, 160, 0.16);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.foe-rank {
  margin: 0.15rem 0 0;
  font-size: var(--fs-nano);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dim);
}
/* The two bars that decide the fight, on one plate and the same width, so the comparison
   is made by the eye instead of by memory. */
.duel { display: flex; gap: 0.9rem; width: min(48%, 300px); flex-shrink: 0; }
.duel .gauge { flex: 1 1 0; min-width: 0; margin-bottom: 0; }

/* Brass corners. One shape, rotated four times. */
.corner {
  position: absolute;
  width: 26px;
  height: 26px;
  color: var(--gold);
  opacity: 0.75;
  pointer-events: none;
}
.corner-tl { top: 6px; left: 6px; }
.corner-tr { top: 6px; right: 6px; transform: rotate(90deg); }
.corner-br { bottom: 6px; right: 6px; transform: rotate(180deg); }
.corner-bl { bottom: 6px; left: 6px; transform: rotate(270deg); }

/* The damage stamp: struck onto the card, not floated over it. */
.strike {
  position: absolute;
  top: 14%;
  left: 50%;
  z-index: 3;
  padding: 0.1rem 0.55rem;
  font-family: 'Cinzel', Georgia, serif;
  /* Fora da escala de texto de propósito: o carimbo não é tipografia, é um efeito, e
     o tamanho dele é a força da pancada. Amarrado à viewport para ocupar a mesma
     fração da carta no celular e no monitor. */
  font-size: clamp(2.4rem, 7vw, 4rem);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  pointer-events: none;
  opacity: 0;
}
.strike.is-out { color: #ffe9b8; text-shadow: 0 0 26px rgba(201, 162, 74, 0.6), 0 3px 0 rgba(0, 0, 0, 0.75); }
.strike.is-in { color: #ffc9c9; text-shadow: 0 0 26px rgba(168, 58, 58, 0.65), 0 3px 0 rgba(0, 0, 0, 0.75); }
/* The number lands, holds, then RISES away. The first version drifted 22px and faded in
   under a second, which is a thing you only notice if you already knew it was there — the
   whole point of a damage number is that it is impossible to miss. */
.strike[data-play] { animation: stamp 1.25s var(--ease) forwards; }
@keyframes stamp {
  0%   { opacity: 0; transform: translate(-50%, 6px) rotate(-9deg) scale(1.9); filter: blur(8px); }
  16%  { opacity: 1; transform: translate(-50%, 0) rotate(-6deg) scale(1.06); filter: blur(0); }
  26%  { opacity: 1; transform: translate(-50%, 0) rotate(-6deg) scale(1); filter: blur(0); }
  60%  { opacity: 1; transform: translate(-50%, -30px) rotate(-6deg) scale(1); filter: blur(0); }
  100% { opacity: 0; transform: translate(-50%, -96px) rotate(-6deg) scale(0.92); filter: blur(1px); }
}

/* --- the elemental flash ---------------------------------------------------
   One layer over the plate and under the numbers. Every element is the same shape of event —
   a fast bloom, a held tint, a fade — and differs only in colour and in one detail of motion,
   because a fight where each element animates differently reads as six unrelated effects
   rather than one game. The server says which element (deps._element_of); this only paints. */
.foe-flash {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: screen;
}
.foe-flash[data-play] { animation: elemental 0.72s var(--ease) forwards; }
@keyframes elemental {
  0%   { opacity: 0; }
  14%  { opacity: 0.92; }
  38%  { opacity: 0.55; }
  100% { opacity: 0; }
}

/* Fire: a heat bloom from below, the way a flame actually arrives. */
.foe-flash[data-element="fire"] {
  background:
    radial-gradient(ellipse 70% 55% at 50% 78%, rgba(255, 150, 48, 0.85), transparent 68%),
    radial-gradient(ellipse 45% 35% at 50% 88%, rgba(255, 226, 150, 0.7), transparent 70%);
}
/* Frost: light from the top edge, and a cold cast over the whole plate. */
.foe-flash[data-element="frost"] {
  background:
    radial-gradient(ellipse 75% 50% at 50% 10%, rgba(150, 224, 255, 0.8), transparent 70%),
    linear-gradient(180deg, rgba(96, 168, 224, 0.45), transparent 75%);
}
/* Lightning: a hard vertical strike, not a glow. The stripe is what sells it. */
.foe-flash[data-element="lightning"] {
  background:
    linear-gradient(96deg, transparent 44%, rgba(226, 240, 255, 0.95) 49%, transparent 55%),
    radial-gradient(ellipse 60% 60% at 50% 40%, rgba(150, 190, 255, 0.55), transparent 72%);
}
/* Poison: pooling from the ground up, in the one green this palette allows itself. */
.foe-flash[data-element="poison"] {
  background:
    radial-gradient(ellipse 80% 45% at 50% 90%, rgba(126, 200, 84, 0.8), transparent 72%),
    radial-gradient(ellipse 40% 40% at 50% 62%, rgba(168, 224, 120, 0.42), transparent 70%);
}
/* Bleed: not a wash. Two arcs where a blade went through. */
.foe-flash[data-element="bleed"] {
  background:
    linear-gradient(122deg, transparent 40%, rgba(214, 62, 62, 0.9) 46%, transparent 51%),
    linear-gradient(58deg, transparent 46%, rgba(180, 40, 40, 0.7) 51%, transparent 56%);
}
/* Curse: dark, and the only element that arrives from the edges inward. */
.foe-flash[data-element="curse"] {
  mix-blend-mode: normal;
  background:
    radial-gradient(ellipse 95% 95% at 50% 50%, transparent 34%, rgba(74, 30, 104, 0.88) 82%),
    radial-gradient(ellipse 40% 40% at 50% 46%, rgba(168, 96, 224, 0.5), transparent 70%);
}
/* Holy: a single overhead shaft. */
.foe-flash[data-element="holy"] {
  background:
    linear-gradient(180deg, rgba(255, 240, 196, 0.85), transparent 62%),
    radial-gradient(ellipse 40% 70% at 50% 20%, rgba(255, 232, 168, 0.7), transparent 72%);
}
/* Arcane: the game's own gold and violet, turning around the middle. */
.foe-flash[data-element="arcane"] {
  background:
    radial-gradient(ellipse 55% 55% at 50% 48%, rgba(201, 162, 74, 0.8), transparent 66%),
    radial-gradient(ellipse 85% 85% at 50% 48%, rgba(150, 108, 214, 0.5), transparent 74%);
}
/* Shadow, and the plain swing. A weapon has no colour, so physical gets the faintest
   possible acknowledgement rather than nothing — silence would read as a missed frame. */
.foe-flash[data-element="shadow"] {
  mix-blend-mode: normal;
  background: radial-gradient(ellipse 80% 80% at 50% 50%, rgba(18, 10, 28, 0.9), transparent 76%);
}
.foe-flash[data-element="physical"] {
  background: radial-gradient(ellipse 55% 45% at 50% 45%, rgba(255, 244, 214, 0.42), transparent 68%);
}
.foe-flash[data-element="physical"][data-play] { animation-duration: 0.34s; }
.foe-card[data-hit] { animation: recoil 0.34s var(--ease); }
@keyframes recoil {
  0%   { transform: rotate(-0.35deg) translateX(0); }
  30%  { transform: rotate(0.9deg) translateX(7px); }
  100% { transform: rotate(-0.35deg) translateX(0); }
}

/* The empty slot, before a monster is dealt. */
.slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  min-height: clamp(220px, 38vh, 380px);
  padding: 2rem 1.5rem;
  text-align: center;
  border: 1px dashed var(--border-lit);
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.22);
  box-shadow: inset 0 24px 50px rgba(0, 0, 0, 0.4);
}
.slot h2 {
  margin: 0;
  font-size: var(--fs-large);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text);
}
.slot p { margin: 0; max-width: 40ch; color: var(--dim); }
.slot svg { width: 42px; height: 42px; color: var(--border-lit); }

/* The outcome banner, stamped across the card's foot. */
.verdict {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.1rem;
  padding: 0.95rem 1.15rem;
  border: 1px solid var(--brass-dark);
  border-radius: 4px;
  background: linear-gradient(160deg, rgba(60, 45, 22, 0.5), rgba(16, 12, 22, 0.85));
}
.verdict.is-loss { border-color: var(--blood-dim); background: linear-gradient(160deg, rgba(94, 34, 34, 0.4), rgba(16, 12, 22, 0.88)); }
.verdict h3 {
  margin: 0;
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-bright);
}
.verdict.is-loss h3 { color: #e9a8a8; }
.verdict ul { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; margin: 0; padding: 0; list-style: none; }
.verdict li { font-size: var(--fs-small); color: var(--text); font-variant-numeric: tabular-nums; }
.verdict li span { color: var(--dim); font-size: var(--fs-nano); letter-spacing: 0.1em; text-transform: uppercase; margin-right: 0.35rem; }

/* --- the scroll: what happened, in order --------------------------------- */
.scroll {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border: var(--rule);
  border-radius: 4px;
  background: linear-gradient(170deg, rgba(24, 18, 34, 0.9), rgba(12, 9, 18, 0.94));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03), 0 14px 34px rgba(0, 0, 0, 0.45);
}
.scroll-head {
  padding: 0.75rem 1rem;
  border-bottom: var(--rule);
  font-family: 'Cinzel', Georgia, serif;
  font-size: var(--fs-nano);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--dim);
  display: flex;
  justify-content: space-between;
}
.scroll-head b { color: var(--gold); font-weight: 600; font-variant-numeric: tabular-nums; }
.scroll-body {
  flex: 1;
  overflow-y: auto;
  padding: 0.5rem 0.35rem 0.75rem;
  max-height: min(52vh, 460px);
  scroll-behavior: smooth;
}
.scroll-empty { padding: 1.5rem 1rem; color: var(--dim); font-style: italic; font-size: var(--fs-small); }

.turn { padding: 0.7rem 0.65rem 0.75rem; border-top: 1px solid rgba(46, 37, 64, 0.7); }
.turn:first-child { border-top: 0; }
.turn-no {
  display: block;
  margin-bottom: 0.35rem;
  font-family: 'Cinzel', Georgia, serif;
  font-size: var(--fs-nano);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brass-text);
}
.line { display: flex; gap: 0.55rem; align-items: flex-start; padding: 0.13rem 0; font-size: var(--fs-small); line-height: 1.5; }
.line svg { width: 13px; height: 13px; margin-top: 0.32em; flex-shrink: 0; color: var(--dim); }
.line-text { min-width: 0; }
.line.is-harm svg { color: #c76a6a; }
.line.is-gain svg { color: var(--gold); }
.line.is-crit .line-text { color: var(--gold-bright); }
.line[data-fresh] { animation: ink 0.5s var(--ease) both; }
@keyframes ink {
  from { opacity: 0; transform: translateY(-4px); filter: blur(3px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}

/* --- the counters you push ------------------------------------------------ */
.counters {
  position: relative;
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  padding: 1.1rem 1.25rem calc(1.1rem + env(safe-area-inset-bottom));
  border-top: 1px solid rgba(107, 79, 38, 0.45);
  background: linear-gradient(180deg, rgba(10, 8, 16, 0.55), rgba(8, 6, 12, 0.95));
  backdrop-filter: blur(8px);
}
.counter {
  --metal: url('/assets/lore/metal_texture.webp');
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.18rem;
  min-width: 138px;
  padding: 0.7rem 1.15rem 0.72rem;
  overflow: hidden;
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #ddd0ee;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.9), 0 -1px 0 rgba(255, 224, 160, 0.12);
  cursor: pointer;
  transition: transform 0.14s var(--ease), color 0.14s, border-color 0.14s, box-shadow 0.14s;
}
/* A counter is a cast plate, not a rectangle. Three things say so: an engraved inner
   line a hair inside the rim, the candle catching the upper-left as a diagonal sheen,
   and the mark of the action struck above the word. The metal texture was already
   loading — it just sat under a 93%-opaque wash and never showed. */
.counter::before {
  content: "";
  position: absolute;
  inset: 3px;
  border: 1px solid rgba(201, 162, 74, 0.16);
  border-radius: 4px;
  pointer-events: none;
}
.counter::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(118deg, rgba(255, 232, 186, 0.13) 0 28%, transparent 58%);
  pointer-events: none;
}
.counter svg {
  width: 17px;
  height: 17px;
  color: var(--gold);
  opacity: 0.72;
  transition: opacity 0.14s, color 0.14s, transform 0.14s var(--ease);
}
.counter-label { display: block; }
.counter:hover:not(:disabled) svg { opacity: 1; color: var(--gold-bright); transform: translateY(-1px); }

.counter small {
  font-family: 'Spectral', Georgia, serif;
  font-size: var(--fs-nano);
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}
.counter:hover:not(:disabled) {
  color: var(--gold-bright);
  border-color: var(--gold);
  /* Pushed forward across the felt, toward the middle of the table. */
  transform: translateY(-3px);
  box-shadow:
    inset 0 1px 0 rgba(255, 224, 160, 0.3),
    inset 0 -3px 5px rgba(0, 0, 0, 0.6),
    0 8px 18px rgba(0, 0, 0, 0.55),
    0 0 20px rgba(201, 162, 74, 0.22);
}
.counter:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: inset 0 2px 7px rgba(0, 0, 0, 0.75), inset 0 -1px 0 rgba(255, 224, 160, 0.1);
}
.counter:disabled { cursor: not-allowed; opacity: 0.42; filter: saturate(0.4); }
/* The primary counter is the one a hand goes to without reading. It is warmer brass,
   sits a touch proud of the others, and its mark is fully lit rather than dimmed. */
.counter.is-primary {
  color: var(--gold-bright);
  border-color: #a07c3c;
  min-width: 172px;
  background-image:
    linear-gradient(160deg, rgba(62, 44, 26, 0.9), rgba(26, 17, 12, 0.94)),
    var(--metal, none);
  box-shadow:
    inset 0 1px 0 rgba(255, 226, 170, 0.34),
    inset 0 -3px 6px rgba(0, 0, 0, 0.62),
    0 4px 10px rgba(0, 0, 0, 0.5),
    0 0 16px rgba(201, 162, 74, 0.13);
}
.counter.is-primary svg { opacity: 1; }
.counter.is-primary::before { border-color: rgba(255, 224, 160, 0.28); }

/* Spent is a state, not a disabled control: the plate goes cold and the mark greys,
   so a skill on cooldown reads as "not yet" instead of "broken". */
.counter.is-spent { color: #8d84a0; border-color: #3a3048; }
.counter.is-spent svg { opacity: 0.32; color: #8d84a0; }

.counter.is-quiet { min-width: 108px; font-size: var(--fs-micro); }
.counter.is-spent small { color: #c78c8c; }
.counter[data-busy] { animation: shove 0.5s var(--ease); }
@keyframes shove {
  0%   { transform: translateY(0); }
  35%  { transform: translateY(-7px); }
  100% { transform: translateY(0); }
}

/* --- notices -------------------------------------------------------------- */
.notice {
  margin: 0 1.25rem 0;
  padding: 0.8rem 1.05rem;
  border: 1px solid var(--blood-dim);
  border-radius: 4px;
  background: rgba(168, 58, 58, 0.12);
  color: #f0cccc;
  font-size: var(--fs-small);
}
.notice[hidden] { display: none; }
.notice a { color: var(--gold-bright); }

.veil {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: grid;
  place-items: center;
  background: rgba(8, 6, 12, 0.72);
  backdrop-filter: blur(3px);
  font-family: 'Cinzel', Georgia, serif;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-size: var(--fs-micro);
  color: var(--dim);
}
.veil[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   Phone. Not the desktop stacked: the card leads, the scroll takes what is
   left, and the counters sit on the floor of the screen inside thumb reach.
--------------------------------------------------------------------------- */
@media (max-width: 959px) {
  .felt { padding: 0.9rem 0.9rem; gap: 0.9rem; }

  /* The counters MUST carry an order too. Without one they default to 0 and, with the
     board at 1 and the scroll at 2, the whole bank of buttons was rendered ABOVE the
     monster's card — which pushed the card and its health bar off the bottom of a phone
     screen. That is the "cannot see enemy hp, must scroll down first" a player reported
     on launch day, and it was never a sizing problem: it was source order. */
  .board { order: 1; }
  .scroll { order: 2; }
  .counters { order: 3; }

  /* Height, not ratio. A 5:4 card on a 375px screen is 300px of art, and with the plate
     under it the monster's health bar landed below the fold — a player had to scroll to
     see the number the whole fight is about. Capping the art in viewport units keeps the
     art, both bars and the counters inside one screen on every phone size. `dvh` because
     the mobile browser's address bar eats `vh` and puts the plate back under the fold. */
  .foe-art { aspect-ratio: auto; height: min(29dvh, 260px); max-height: none; }
  .foe-plate { flex-direction: column; align-items: stretch; gap: 0.55rem; padding: 0.7rem 0.85rem 0.8rem; }
  /* Still side by side, not stacked: stacking them is what put one at the top of the
     screen and the other at the bottom in the first place. */
  .duel { width: 100%; gap: 0.7rem; }
  .gauge-head { font-size: var(--fs-nano); margin-bottom: 0.22rem; }

  .scroll-body { max-height: 20vh; }
  .counters { gap: 0.45rem; padding: 0.6rem 0.6rem calc(0.6rem + env(safe-area-inset-bottom)); }
  /* Not one row of five. Five counters across 375px is 52px each — narrower than the
     word "Firebolt", so the label wraps to four lines and the plate grows to 136px tall
     to hold it. Three to a row gives each about 110px, which fits the longest skill name
     the game has on one line, and the two that spill make a second row inside thumb reach. */
  .counter {
    flex: 1 1 30%;
    min-width: 0;
    /* Shorter, not narrower. The plate was 0.72rem of padding above and below a stacked
       mark and label, which on a phone made a control taller than the health bar it was
       supposed to be read next to. The mark moves onto the label's line just below, so
       the height comes off without the word getting smaller. */
    padding: 0.42rem 0.5rem 0.45rem;
    flex-direction: row;
    gap: 0.4rem;
    font-size: var(--fs-micro);
    letter-spacing: 0.05em;
  }
  /* The note under a counter ("ready in 2", "3 free left") wraps to a second line on a
     narrow plate and puts the height straight back. It gets the whole width of the plate,
     under the mark and the word. */
  .counter { flex-wrap: wrap; align-content: center; }
  .counter small { flex: 1 0 100%; text-align: center; line-height: 1.1; }
  /* The mark shrinks so the longest skill name in the game still lands on one line beside
     it. A label that wraps is what made these plates tall, not the padding. */
  .counter svg { width: 12px; height: 12px; }
  .counter-label { line-height: 1.15; }
  /* --fs-nano é o degrau da etiqueta gravada, não o do botão. STRIKE a 11px num
     celular é o controle principal do jogo pedindo para ser lido com esforço. */
  .counter.is-primary, .counter.is-quiet { min-width: 0; }
  .counter.is-quiet { flex: 1 1 30%; }
  /* Five counters across 375px leaves each about 52px — too narrow to stack a mark
     above a word without breaking the word. The mark shrinks and moves onto the same
     line as the label, which is what a small plate can actually hold. */
  .counter svg { width: 14px; height: 14px; }
  .counter-label { overflow-wrap: anywhere; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  /* Two exceptions, and they are not decoration.
     The damage number is the only place the browser client ever states how hard the blow
     landed — the log says it too, but a player watching the card is watching the card. Killed
     by the blanket rule above, the whole thing became invisible to anyone who has animations
     switched off in Windows or macOS, which is a great many people and looks exactly like a
     broken feature. So it still appears; it just stops MOVING. It fades up, holds long enough
     to be read, and fades out.
     The elemental flash gets the same treatment for the same reason: which element hit is
     information about the fight, not flourish. */
  /* A fade, not a step. `steps(1, end)` holds the interval's start value for the whole
     interval, so the number sat at opacity 0 for its entire 1.5s and the fix looked exactly
     like the bug. A cross-fade is also what the guideline actually allows: what triggers
     vestibular trouble is MOTION, and there is none here — the number does not travel. */
  .strike[data-play] { animation: stamp-still 1.5s ease-out forwards !important; }
  @keyframes stamp-still {
    0%   { opacity: 0; transform: translate(-50%, 0) rotate(-6deg); }
    8%   { opacity: 1; transform: translate(-50%, 0) rotate(-6deg); }
    80%  { opacity: 1; transform: translate(-50%, 0) rotate(-6deg); }
    100% { opacity: 0; transform: translate(-50%, 0) rotate(-6deg); }
  }
  .foe-flash[data-play] { animation: flash-still 0.9s ease-out forwards !important; }
  @keyframes flash-still {
    0%   { opacity: 0; }
    10%  { opacity: 0.6; }
    72%  { opacity: 0.6; }
    100% { opacity: 0; }
  }
}
