/* Ninefall — the look.

   A dark stage the hero stands on, with everything else floating over it: an uppercase eyebrow, a
   serif name, rarity told by a pill, and a glass panel for whatever the screen lets you choose. The
   direction is the Mythic Model Lab tester: vignette and grain over a lit ground, gold on deep blue,
   micro-labels in wide uppercase, one characterful serif against a plain interface sans.

   Three rules hold it together:
     · one shape - a rounded rectangle at one of four radii; nothing is a circle or a pill
     · one control height - every button is --control tall, whatever it says
     · one spacing and tracking scale - the space between letters and parts comes from the tokens
       below and nowhere else, which is what makes it read as made rather than assembled.

   Nothing scrolls: every screen is sized to the display (see fit() in the sprite module). */

@font-face{
  font-family:"Playfair Display";
  src:url("/fonts/playfair-display.woff2") format("woff2-variations");
  font-weight:400 900;font-style:normal;font-display:swap;
}

:root{
  --bg:#070912;
  --ink:#f8f4ea;
  --muted:#9a9cab;
  --line:#ffffff1c;
  --line-soft:#ffffff0e;
  --panel:linear-gradient(180deg,#111625df,#090c15df);
  --panel-line:#ffffff18;
  --gold:#d9bd75;
  --gold-hi:#f0d58d;
  --grey:#9aa0ae;
  --green:#7cc08d;
  --blue:#91b4ff;
  --violet:#9277ff;
  --rarity:var(--grey);

  --serif:"Playfair Display",Georgia,"Times New Roman",serif;
  --sans:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  /* type: three roles, and the tracking each one wants */
  --t-display:clamp(32px,8.5vw,58px);
  --t-body:12.5px;
  --t-label:10px;
  --t-micro:9.5px;
  --track-display:-.015em;
  --track-label:.16em;
  --track-micro:.22em;
  --track-caption:.1em;
  --lead-display:.95;
  --lead-body:1.62;
  --lead-label:1.25;

  /* space: one scale, for every gap and every padding */
  --s1:6px; --s2:10px; --s3:14px; --s4:18px; --s5:24px;
  /* shape: rounded rectangles only */
  --r-panel:18px;
  --r-tile:14px;
  --r-control:12px;
  --r-pill:9px;
  --control:34px;        /* every button on a page, whatever it says */
  --dock-control:40px;   /* the dock is not a page control and keeps its own */

  --ease:cubic-bezier(.22,1,.36,1);
  --ease-inout:ease-in-out;
  --move:300ms;
  --travel:44px;
  color-scheme:dark;
}

*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;overflow:hidden;
  background:var(--bg);color:var(--ink);
  font-family:var(--sans);font-size:var(--t-body);line-height:var(--lead-body);
  -webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;
  user-select:none;-webkit-user-select:none;
  touch-action:manipulation;overscroll-behavior:none;
  text-rendering:optimizeLegibility;
}
[hidden]{display:none!important}
button{font:inherit;color:inherit;cursor:pointer}
img{display:block;max-width:100%}

/* ---------- the stage: the world behind everything ---------- */
.stage{position:fixed;inset:0;z-index:0;overflow:hidden;background:var(--bg)}
.sky{position:absolute;inset:0;width:100%;height:100%;display:block;opacity:0;transition:opacity .5s var(--ease)}
.stage[data-ready="true"] .sky{opacity:1}
.vignette{position:absolute;inset:0;pointer-events:none;background:radial-gradient(circle at 50% 42%,transparent 38%,#03040a55 74%,#010207e6 112%)}
.grain{position:absolute;inset:0;pointer-events:none;opacity:.05;background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E")}

/* ---------- the screen ---------- */
#view{
  position:relative;z-index:1;
  height:100dvh;width:100%;max-width:1180px;margin:0 auto;
  padding:max(var(--s4),env(safe-area-inset-top)) max(var(--s4),env(safe-area-inset-left)) calc(env(safe-area-inset-bottom) + 78px);
  display:flex;flex-direction:column;gap:var(--s3);
}
#view[data-slack] .grid,#view[data-slack] .frame,#view[data-slack] .body,#view[data-slack] .state{margin-block:auto}
/* One view gives way to the next: the incoming screen arrives a short way off its place and eases in.
   Transforms only, so the glass over the stage never flattens mid-move. */
[data-view]{visibility:hidden;animation:var(--move) var(--ease-inout) both paused}
[data-view][data-run="true"]{visibility:visible;animation-play-state:running}
[data-view="push"]{animation-name:view-push}
[data-view="pop"]{animation-name:view-pop}
[data-view="cover"]{animation-name:view-cover}
[data-view="dismiss"]{animation-name:view-dismiss}
@keyframes view-push{from{transform:translateX(var(--travel))}to{transform:none}}
@keyframes view-pop{from{transform:translateX(calc(-1 * var(--travel)))}to{transform:none}}
@keyframes view-cover{from{transform:translateY(var(--travel)) scale(.982)}to{transform:none}}
@keyframes view-dismiss{from{transform:translateY(calc(-1 * var(--travel))) scale(.982)}to{transform:none}}
@media (prefers-reduced-motion:reduce){[data-view]{animation:none!important;visibility:visible}}

/* ---------- the head: what this is, whose it is, how rare ---------- */
.head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s3);flex:0 0 auto}
.brand{min-width:0;flex:1 1 auto;text-align:left}
.tools{flex:0 0 auto;display:flex;gap:var(--s1)}
.eyebrow{margin:0;font-size:var(--t-micro);letter-spacing:var(--track-micro);text-transform:uppercase;color:#b9b2a2;line-height:var(--lead-label)}
.title{
  margin:var(--s1) 0 0;font-family:var(--serif);font-weight:500;
  font-size:var(--t-display);line-height:var(--lead-display);letter-spacing:var(--track-display);
  text-wrap:balance;overflow-wrap:anywhere;
}
.pills{display:flex;flex-wrap:wrap;justify-content:flex-start;gap:var(--s1);margin-top:var(--s2)}
.pill{
  min-height:26px;padding:0 var(--s2);display:inline-flex;align-items:center;
  border:1px solid var(--line);border-radius:var(--r-pill);
  background:#090c14aa;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  font-size:var(--t-micro);letter-spacing:var(--track-label);text-transform:uppercase;color:#d6d2c9;white-space:nowrap;line-height:1;
}
.pill[data-rarity]{border-color:color-mix(in srgb,var(--rarity) 42%,transparent);color:var(--rarity);box-shadow:inset 0 0 18px color-mix(in srgb,var(--rarity) 9%,transparent)}
.pill[data-rarity="0"]{--rarity:var(--grey)}
.pill[data-rarity="1"]{--rarity:var(--green)}
.pill[data-rarity="2"]{--rarity:var(--blue)}
.pill[data-rarity="3"]{--rarity:var(--violet)}
.pill[data-rarity="4"]{--rarity:var(--gold)}

/* ---------- controls: one height, one shape ---------- */
.icon,.util,.btn,.seg button{
  min-height:var(--control);
  border-radius:var(--r-control);
  font-size:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;line-height:1.2;
  transition:color .2s ease,border-color .2s ease,background-color .2s ease,transform .16s var(--ease);
}
.icon,.util{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s1);
  border:1px solid var(--line);background:#ffffff06;
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);color:#c9cbd4;
}
.icon{width:var(--control);flex:0 0 auto}
.util{padding:0 var(--s3)}
.icon:active,.util:active,.btn:active,.seg button:active,.dock button:active{transform:scale(.96)}
.icon:hover,.util:hover{color:var(--ink)}
.icon svg,.util svg,.btn svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.icon:focus-visible,.util:focus-visible,.seg button:focus-visible,.dock button:focus-visible,.btn:focus-visible,.tile:focus-visible,.frame:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.btn{
  padding:0 var(--s4);display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);
  border:1px solid color-mix(in srgb,var(--gold) 34%,transparent);
  background:linear-gradient(180deg,#d9bd7524,#d9bd750a);color:#f6e6bf;
  backdrop-filter:blur(16px) saturate(130%);-webkit-backdrop-filter:blur(16px) saturate(130%);
}
.btn[data-tone="quiet"]{border-color:var(--line);background:#ffffff06;color:#c9cbd4}

/* ---------- the glass panel, and the segmented rows it holds ---------- */
.panel{
  flex:0 0 auto;padding:var(--s2);
  border:1px solid var(--panel-line);border-radius:var(--r-panel);
  background:var(--panel);backdrop-filter:blur(22px) saturate(130%);-webkit-backdrop-filter:blur(22px) saturate(130%);
  box-shadow:0 18px 70px #0007;
  display:grid;gap:var(--s1);
}
.seg{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:var(--s1)}
.seg[data-cols="3"]{grid-auto-flow:row;grid-template-columns:repeat(3,1fr)}
.seg[data-cols="4"]{grid-auto-flow:row;grid-template-columns:repeat(4,1fr)}
.seg button{
  padding:0 var(--s1);min-width:0;
  border:1px solid var(--line);background:#ffffff0b;color:#a8abb5;
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  font-size:var(--t-micro);
}
.seg button[aria-pressed="true"],.seg button[aria-current]{
  color:#fff4d9;border-color:color-mix(in srgb,var(--gold) 38%,transparent);
  background:linear-gradient(180deg,#d9bd7520,#d9bd750a);box-shadow:inset 0 0 18px #d9bd7512;
}
.seg button:disabled,.btn:disabled{opacity:.34;transform:none;cursor:default}
.pair{display:grid;grid-template-columns:1fr 1fr;gap:var(--s1)}

/* ---------- where a hero stands ----------
   The shot is the hero's frame: the sprite is scaled so its frame lands here. Anything that reaches
   past it - a wide weapon, one that hangs below the feet - keeps its full size and hangs outside,
   over whatever is around it, rather than being cropped or shrunk to fit. */
.frame,.tile{overflow:visible}
/* the sprite is art, not a target: a weapon hanging over a button never swallows the tap */
.shot{position:relative;width:100%;height:var(--shot-h,0px);pointer-events:none}
.shot canvas{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:calc(100% * var(--spill,1));max-width:none;height:auto;
  image-rendering:pixelated;
}
.frame{position:relative;flex:0 0 auto;margin:0}
.frame .shot canvas{filter:drop-shadow(0 22px 34px #0006)}

/* ---------- grids of heroes ---------- */
.grid{flex:0 0 auto;display:grid;gap:var(--s3)}
.grid[data-cols="2"]{grid-template-columns:repeat(2,1fr)}
.grid[data-cols="3"]{grid-template-columns:repeat(3,1fr)}
.tile{
  position:relative;margin:0;padding:var(--s2) var(--s1) var(--s1);display:grid;gap:var(--s1);
  border:1px solid var(--line-soft);border-radius:var(--r-tile);
  background:linear-gradient(180deg,#ffffff12,#ffffff06);
  backdrop-filter:blur(16px) saturate(125%);-webkit-backdrop-filter:blur(16px) saturate(125%);
  box-shadow:0 10px 30px #0004;
  transition:border-color .2s ease,background-color .2s ease,box-shadow .2s ease,transform .14s var(--ease);
}
.tile:active{transform:scale(.965);border-color:#ffffff3d}
@keyframes seat-take{0%{transform:scale(1)}38%{transform:scale(1.07)}100%{transform:scale(1)}}
.seat[data-took]{animation:seat-take .36s var(--ease)}
.tile[data-rarity]{border-color:color-mix(in srgb,var(--rarity) 24%,transparent)}
.tile[data-rarity="0"]{--rarity:var(--grey)}
.tile[data-rarity="1"]{--rarity:var(--green)}
.tile[data-rarity="2"]{--rarity:var(--blue)}
.tile[data-rarity="3"]{--rarity:var(--violet)}
.tile[data-rarity="4"]{--rarity:var(--gold);box-shadow:inset 0 -30px 40px -30px var(--gold)}
.tile figcaption{font-size:var(--t-micro);letter-spacing:var(--track-caption);text-transform:uppercase;color:#c3c5cd;text-align:center;line-height:var(--lead-label);overflow-wrap:anywhere}

/* ---------- numbers ---------- */
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s3)}
.stat{display:grid;gap:var(--s1);min-width:0}
.stat span{font-size:var(--t-micro);letter-spacing:var(--track-micro);text-transform:uppercase;color:var(--muted);line-height:1}
.stat strong{font-size:21px;font-weight:600;line-height:1;letter-spacing:-.01em;font-variant-numeric:tabular-nums}
.stat small{font-size:var(--t-micro);letter-spacing:var(--track-caption);color:var(--muted);font-variant-numeric:tabular-nums;line-height:1.2}
.bar{height:3px;border-radius:2px;background:#ffffff14;overflow:hidden}
.bar i{display:block;height:100%;background:linear-gradient(90deg,color-mix(in srgb,var(--gold) 60%,transparent),var(--gold));transform-origin:left center;transform:scaleX(var(--fill,0));transition:transform .9s var(--ease)}
.facts{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2)}
.fact{display:grid;gap:4px;min-width:0}
.fact span{font-size:var(--t-micro);letter-spacing:var(--track-micro);text-transform:uppercase;color:var(--muted);line-height:1}
.fact b{font-weight:500;font-size:var(--t-body);line-height:var(--lead-label);overflow-wrap:anywhere}

/* ---------- states, hints, toast ---------- */
.state{
  padding:var(--s5);display:grid;gap:var(--s2);justify-items:start;
  border:1px solid var(--line);border-radius:var(--r-panel);background:var(--panel);
  backdrop-filter:blur(22px);-webkit-backdrop-filter:blur(22px);
}
.state p{margin:0}
.state h2{margin:0;font-family:var(--serif);font-weight:500;font-size:22px;line-height:1.15;letter-spacing:-.01em}
.state small{color:var(--muted);font-size:var(--t-body);line-height:var(--lead-body);max-width:46ch}
.state .btn{margin-top:var(--s1)}
.hint{flex:0 0 auto;margin:0;text-align:center;font-size:var(--t-micro);letter-spacing:var(--track-micro);text-transform:uppercase;color:#7f8390}
.toast{
  position:fixed;z-index:40;left:50%;transform:translateX(-50%);
  bottom:calc(env(safe-area-inset-bottom) + 86px);
  max-width:min(92vw,420px);padding:var(--s2) var(--s3);
  display:flex;align-items:center;gap:var(--s3);
  border:1px solid var(--panel-line);border-radius:var(--r-control);background:var(--panel);
  backdrop-filter:blur(22px);-webkit-backdrop-filter:blur(22px);box-shadow:0 14px 50px #0008;
  font-size:var(--t-body);color:#dcdde3;
}

/* ---------- the dock ---------- */
.dock{
  position:fixed;z-index:20;left:50%;transform:translateX(-50%);
  bottom:calc(env(safe-area-inset-bottom) + 12px);
  padding:var(--s1);display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:var(--s1);
  width:min(420px,calc(100vw - 28px));
  border:1px solid var(--panel-line);border-radius:var(--r-panel);background:var(--panel);
  backdrop-filter:blur(22px) saturate(130%);-webkit-backdrop-filter:blur(22px) saturate(130%);
  box-shadow:0 16px 50px #0008;
}
.dock button{
  min-height:var(--dock-control);border-radius:var(--r-control);border:0;background:transparent;color:#9497a3;
  font-size:var(--t-micro);letter-spacing:var(--track-label);text-transform:uppercase;line-height:1.2;
  transition:color .2s ease,background-color .2s ease,transform .16s var(--ease);
  display:flex;align-items:center;justify-content:center;gap:var(--s1);
  font-size:var(--t-micro);
}
.dock button svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.dock button[aria-current="page"]{color:#fff4d9;background:linear-gradient(180deg,#d9bd751f,#d9bd7508)}

@media (min-width:760px){
  #view{gap:var(--s4);padding-inline:34px}
  .grid{gap:var(--s4)}
  .panel{padding:var(--s3);gap:var(--s2)}
}

/* ---------- the band: nine seats, and the lines drawn across them ----------
   The grid takes the pointer itself (touch-action:none) so drawing a line is never read as a scroll.
   The strokes sit in an overlay above the seats and below nothing: they are not interactive. */
.band{position:relative;flex:0 0 auto;display:grid}
.band .grid{touch-action:none;-webkit-user-select:none;user-select:none}
.band .lines{position:absolute;inset:0;pointer-events:none;overflow:visible}
.band .lines line{stroke-linecap:round;fill:none}
.band .lines .drawn{stroke:var(--gold);stroke-width:3;opacity:.85}
.band .lines .drawn.n1{stroke:var(--blue)}
.band .lines .drawn.n2{stroke:var(--green)}
.band .lines .drawing{stroke:#ffffff8c;stroke-width:2;stroke-dasharray:2 6}

.seat{cursor:pointer}
.seat[data-in]{border-color:color-mix(in srgb,var(--gold) 55%,transparent)}
.seat[data-in="2"]{box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--gold) 30%,transparent)}
.seat[data-in="3"]{box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--gold) 42%,transparent)}
.seat[data-first]{border-color:#ffffff6b}
.seat .seatskill{display:block;text-align:center;font-size:var(--t-micro);letter-spacing:var(--track-caption);
  color:var(--muted);line-height:var(--lead-label);overflow-wrap:anywhere}
.seat figcaption{display:flex;align-items:center;justify-content:center;gap:5px}

/* a sign is a square of its own colour - the five never mix, so the shape stays the same */
.sign{width:8px;height:8px;border-radius:3px;flex:none;background:var(--sign,var(--grey))}
.sign[data-sign="lightning"]{--sign:#e0c84a}
.sign[data-sign="water"]{--sign:#6f9ce8}
.sign[data-sign="fire"]{--sign:#e08a52}
.sign[data-sign="earth"]{--sign:#7fbb7a}
.sign[data-sign="wind"]{--sign:#74c2cc}

/* the three lines you have drawn, named */
.lineup-chosen{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2)}
.chosen{display:grid;gap:2px;padding:var(--s2) var(--s1);border:1px solid var(--line-soft);
  border-radius:var(--r-control);text-align:center;min-width:0;background:#ffffff07}
.chosen[data-on]{border-color:color-mix(in srgb,var(--gold) 45%,transparent)}
.chosen span{font-size:var(--t-micro);letter-spacing:var(--track-micro);text-transform:uppercase;color:var(--muted);line-height:1}
.chosen b{font-size:var(--t-label);font-weight:600;line-height:1.2;overflow-wrap:anywhere}

/* A short screen cannot hold nine seats, their names, their skills and a panel. The skill line is the
   first thing to go - it is a reminder, not a decision - and the chosen lines stack tighter. */
@media (max-height:700px){
  /* the archive is a thing to look at, so it is the first thing a short screen gives up */
  [data-part="archive"]{display:none}
  [data-part="dev"] .hint{display:none}
  [data-part="signin"] .hint{display:none}
  .tally{padding:var(--s1)}
  .tell strong{font-size:15px}
  .tell small{display:none}
  .deeds{gap:1px;padding:4px}
  .deed{min-height:28px}
  .tally{gap:0}
  .state{padding:var(--s3);gap:var(--s1)}
  .state h2{font-size:19px}
  .state small{display:none}
}
@media (max-height:640px){
  .seat .seatskill{display:none}
  .band .grid{gap:var(--s2)}
  .chosen{padding:var(--s1) 4px}
  .lineup-chosen{gap:var(--s1)}
}

/* ---------- bare: the model gets the room ----------
   On a screen whose subject is one figure, the head stays where it is and everything you can press is
   reduced to one slim strip, so the figure has the rest. The art is then fitted to the HEIGHT it was
   given rather than the width - the no-crop rule solved the other way round - and whatever reaches past
   the frame sideways hangs outside it as it always did. */
#view[data-bare="true"]{gap:var(--s2)}
#view[data-bare="true"] > .body{flex:1 1 auto;min-height:0;display:grid;place-items:center}
#view[data-bare="true"] .frame{margin:0;height:100%;width:100%;display:grid;place-items:center}
#view[data-bare="true"] .shot{height:calc(100% / var(--spill-y,1))}
#view[data-bare="true"] .shot canvas{width:auto;height:calc(100% * var(--spill-y,1))}
#view[data-bare="true"] .frame{cursor:pointer}
.float{display:grid;gap:var(--s1)}
.float .hint{margin:0}
.float .panel{padding:var(--s1);gap:var(--s1)}

/* the smallest a control can be and still be worth aiming at */
.mini{display:grid;grid-template-columns:auto 1fr;gap:var(--s1);align-items:center}

/* an icon that is currently true wears the gold */
.icon[data-on]{color:var(--gold);border-color:color-mix(in srgb,var(--gold) 45%,transparent);background:#d9bd7514}

/* A narrow screen tightens the smallest type rather than taking another row: a row costs the model
   more height than the letters cost legibility. */
@media (max-width:370px){
  .seg button{font-size:8.5px;letter-spacing:.03em;padding:0 3px}
}

/* ---------- the field ----------
   Two sides, the far one above the near one, each fighter a sprite with its life under it. The rows
   share the room the rest of the screen leaves, and the fallen stay where they fell, dimmed. */
/* Two columns facing each other: the band on the left, what it is facing on the right. Each side is a
   stack, so a fighter's whole height is its own and the two lines look across the gap between them. */
.battle{flex:1 1 auto;min-height:0;display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
.side{display:grid;grid-auto-flow:row;grid-auto-rows:1fr;gap:var(--s2);justify-items:center;align-items:stretch;min-height:0}
.fighter{position:relative;margin:0;padding:0;width:100%;min-width:0;height:100%;
  display:grid;grid-template-rows:minmax(0,1fr) auto;gap:4px;
  transition:transform .22s var(--ease),opacity .4s ease}
/* the art is fitted to the row's HEIGHT, and whatever spills sideways passes behind its neighbours */
.battle .shot{height:100%;min-height:0;z-index:1}
.battle .shot canvas{width:auto;height:calc(100% * var(--spill-y,1));max-width:none}
.vitals{position:relative;z-index:2}
.fighter[data-acting]{transform:translateY(-6px) scale(1.04)}
.fighter[data-down]{opacity:.26;filter:grayscale(1)}
.vitals{display:grid;gap:2px;min-width:0;justify-items:center}

/* one pip per mark, in the mark's own colour */
.marks{display:flex;flex-wrap:wrap;justify-content:center;gap:3px;min-height:9px}
.mark{width:9px;height:9px;border-radius:3px;background:color-mix(in srgb,var(--tint) 78%,transparent);
  display:grid;place-items:center;font-size:7px;font-style:normal;font-weight:700;color:#0b0d16;line-height:1}
.mark[data-hard]{box-shadow:0 0 0 1px var(--tint),0 0 8px var(--tint)}
.fighter[data-frozen] .shot canvas{filter:saturate(.45) brightness(1.15) drop-shadow(0 0 6px #74c2cc)}
.battle .side{align-items:stretch}
.hp{height:2px;border-radius:2px;background:#ffffff14;overflow:hidden}
.battle .hp{width:62%;justify-self:center;margin:0 auto}
.hp i{display:block;height:100%;border-radius:2px;background:linear-gradient(90deg,#b2553f,var(--gold));
  transform-origin:left center;transform:scaleX(var(--fill,1));transition:transform .38s var(--ease)}
.fighter figcaption{display:flex;align-items:center;justify-content:center;gap:4px;
  font-size:var(--t-micro);letter-spacing:var(--track-caption);text-transform:uppercase;color:#c3c5cd;
  line-height:var(--lead-label);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* a number that leaves the fighter it landed on */
@keyframes rise{from{transform:translate(-50%,0);opacity:0}
  18%{opacity:1}to{transform:translate(-50%,-46px);opacity:0}}
.num{position:absolute;left:50%;top:22%;z-index:4;pointer-events:none;
  font-size:15px;font-weight:600;font-variant-numeric:tabular-nums;letter-spacing:-.01em;
  text-shadow:0 2px 6px #000a;animation:rise 1.05s var(--ease) forwards;color:#f3ede0}
.num[data-tone="edge"]{color:var(--gold);font-size:18px}
.num[data-tone="weak"]{color:#9aa0ae;font-size:13px}
.num[data-tone="mend"]{color:var(--green)}
.num[data-tone="buff"]{color:var(--blue);font-size:11px;letter-spacing:var(--track-caption)}

#view[data-over] .hint{color:var(--gold)}

/* ---------- what a player has ---------- */
.tally{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s1);
  padding:var(--s2);border:1px solid var(--panel-line);border-radius:var(--r-panel);
  background:var(--panel);backdrop-filter:blur(22px);-webkit-backdrop-filter:blur(22px)}
.tell{display:grid;gap:2px;justify-items:center;text-align:center;min-width:0}
.tell span{font-size:var(--t-micro);letter-spacing:var(--track-micro);text-transform:uppercase;color:var(--muted);line-height:1}
.tell strong{font-size:17px;font-weight:600;line-height:1.1;font-variant-numeric:tabular-nums;color:var(--gold)}
.tell small{font-size:var(--t-micro);letter-spacing:var(--track-caption);color:var(--muted);line-height:1.2}

/* the daily three */
.deeds{display:grid;gap:var(--s1);padding:var(--s2);border:1px solid var(--panel-line);
  border-radius:var(--r-panel);background:var(--panel);backdrop-filter:blur(22px);-webkit-backdrop-filter:blur(22px)}
.deed{display:grid;grid-template-columns:1fr auto;gap:var(--s2);align-items:center;min-height:var(--control)}
.deed-say{display:grid;gap:2px;min-width:0}
.deed-say b{font-size:var(--t-label);font-weight:600;letter-spacing:var(--track-caption);
  text-transform:uppercase;line-height:1.2;overflow-wrap:anywhere}
.deed-say small{font-size:var(--t-micro);letter-spacing:var(--track-caption);color:var(--muted);font-variant-numeric:tabular-nums}
.deed .hp{width:76px}
.deed[data-done] .deed-say b{color:var(--gold)}
.deed[data-paid]{opacity:.5}

/* the ground: nine fields to an area */
.nodes{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2);flex:0 0 auto}
.node{display:grid;gap:2px;place-items:center;min-height:56px;padding:var(--s2) var(--s1);
  border:1px solid var(--line);border-radius:var(--r-tile);background:#ffffff08;color:#c9cbd4;
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  transition:border-color .2s ease,background-color .2s ease,transform .14s var(--ease)}
.node:active{transform:scale(.965)}
.node span{font-family:var(--serif);font-size:19px;line-height:1;font-variant-numeric:tabular-nums}
.node small{font-size:var(--t-micro);letter-spacing:var(--track-caption);text-transform:uppercase;color:var(--muted)}
.node[data-done]{border-color:color-mix(in srgb,var(--green) 40%,transparent);color:var(--green)}
.node[data-here]{border-color:color-mix(in srgb,var(--gold) 55%,transparent);color:var(--gold);
  background:linear-gradient(180deg,#d9bd7520,#d9bd7508)}
.node:disabled{opacity:.3;transform:none}
.node:focus-visible{outline:2px solid var(--gold);outline-offset:2px}

/* an empty seat in the frame: the same box as a filled one, so nothing reflows when it is taken */
.seat[data-empty]{border-style:dashed;border-color:#ffffff1c;background:
  repeating-linear-gradient(135deg,#ffffff05 0 6px,transparent 6px 12px)}
.seat[data-empty] figcaption{color:var(--muted)}

/* the ground takes the room the rest leaves rather than a fixed nine rows of its own */
#view .nodes{flex:1 1 auto;min-height:0;grid-auto-rows:1fr}
.campaign-body{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:var(--s2)}

/* ---------- a fall ----------
   Each shape comes down out of the dark a moment after the one before it, and settles when it is
   touched. Transform and filter only: the tiles themselves are glass. */
@keyframes descend{from{transform:translateY(-46vh);opacity:0}60%{opacity:1}to{transform:none;opacity:1}}
@keyframes settle{0%{transform:scale(1.1)}60%{transform:scale(.97)}to{transform:none}}
.fell[data-fell]{animation:descend .82s var(--ease) both;animation-delay:calc(var(--i,0) * 170ms)}
.fell[data-settled]{animation:settle .5s var(--ease)}
.fell[data-veil]{cursor:pointer}
.fell[data-veil] .shot canvas{filter:drop-shadow(0 0 14px color-mix(in srgb,var(--rarity) 55%,transparent))}
.fell[data-veil] .seatskill{color:var(--rarity);letter-spacing:.4em}
@media (prefers-reduced-motion:reduce){.fell[data-fell],.fell[data-settled]{animation:none}}

/* ---------- what a hero carries ---------- */
.slots{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s1)}
.slot{display:grid;gap:3px;justify-items:center;text-align:center;min-width:0;padding:var(--s2) var(--s1);
  border:1px solid var(--line-soft);border-radius:var(--r-tile);background:#ffffff05}
.slot[data-rarity]{border-color:color-mix(in srgb,var(--rarity) 42%,transparent)}
.slot[data-rarity="0"]{--rarity:var(--grey)} .slot[data-rarity="1"]{--rarity:var(--green)}
.slot[data-rarity="2"]{--rarity:var(--blue)} .slot[data-rarity="3"]{--rarity:var(--violet)}
.slot[data-rarity="4"]{--rarity:var(--gold)}
.slot span{font-size:var(--t-micro);letter-spacing:var(--track-micro);text-transform:uppercase;color:var(--muted);line-height:1}
.slot b{font-size:var(--t-label);font-weight:600;line-height:1.2;overflow-wrap:anywhere}
.slot b.dim{color:var(--muted);font-weight:400}
.slot small{font-size:var(--t-micro);letter-spacing:var(--track-caption);color:var(--muted);line-height:1.2}
.slot .btn{margin-top:4px;padding:0 var(--s2);width:100%}

.relics{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s1)}
.relic{display:grid;gap:2px;justify-items:start;text-align:left;padding:var(--s2);min-height:var(--control);
  border:1px solid var(--line);border-radius:var(--r-control);background:#ffffff07;color:var(--ink);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  transition:border-color .2s ease,transform .14s var(--ease)}
.relic:active{transform:scale(.97)}
.relic:disabled{opacity:.4}
.relic[data-rarity]{border-color:color-mix(in srgb,var(--rarity) 38%,transparent)}
.relic[data-rarity="0"]{--rarity:var(--grey)} .relic[data-rarity="1"]{--rarity:var(--green)}
.relic[data-rarity="2"]{--rarity:var(--blue)} .relic[data-rarity="3"]{--rarity:var(--violet)}
.relic[data-rarity="4"]{--rarity:var(--gold)}
.relic b{font-size:var(--t-label);font-weight:600;letter-spacing:var(--track-caption);text-transform:uppercase;line-height:1.2}
.relic small{font-size:var(--t-micro);letter-spacing:var(--track-caption);color:var(--muted)}
.relic:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
