/* 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;
  /* Glass, and it has to actually be glass. This was #111625df - 87% opaque - which is a painted
     panel with a blur behind it that nobody can see. The stage, its stars and the hero's own light
     are supposed to come through; the blur is what makes it readable, not the fill. */
  --panel:linear-gradient(180deg,#151b2d4d,#0a0e1a59);
  --panel-line:#ffffff24;
  --glass:blur(26px) saturate(135%);
  --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. One scale, every screen - the interface is
     not the thing you came to look at, so it stays out of the hero's way and the serif never becomes
     a billboard. A desk is not a reason to make the chrome bigger; it is a reason to leave more dark
     around it, which is what --column below does. */
  --t-display:clamp(23px,6.2vw,30px);
  --t-body:11.5px;
  --t-label:9.5px;
  --t-micro:9px;
  --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 */
  /* The game is one column wide, on every screen. A desk gets more room around it, never a wider
     interface - so the dock and the page are the same width and nothing has to be sized twice. */
  --column:420px;

  --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:calc(var(--column) + 2 * var(--s4));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:#090c1452;backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass);
  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:var(--glass);-webkit-backdrop-filter:var(--glass);
  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:var(--glass);-webkit-backdrop-filter:var(--glass);
}
.state p{margin:0}
.state h2{margin:0;font-family:var(--serif);font-weight:500;font-size:18px;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:var(--glass);-webkit-backdrop-filter:var(--glass);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(var(--column),calc(100vw - 28px));
  border:1px solid var(--panel-line);border-radius:var(--r-panel);background:var(--panel);
  backdrop-filter:var(--glass);-webkit-backdrop-filter:var(--glass);
  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)}


/* ---------- 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. */
/* A title sized only by width grows on a wide-but-short screen until it pushes the page off the
   bottom. Height gets a say: the display face is the largest thing on any screen, so it is the first
   thing that should notice the screen is short. */

/* ---------- 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)}
/* A row that is nothing but buttons does not get a box round it - that is a frame containing only
   other frames. The store and the archive are both one segmented row, so they stand in the stack at
   the same height as every other button and the panel is kept for things that hold actual content. */
.float .panel[data-part="stores"],.float .panel[data-part="archive"]{
  padding:0;border:0;background:none;box-shadow:none;backdrop-filter:none;-webkit-backdrop-filter:none}

/* 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:var(--glass);-webkit-backdrop-filter:var(--glass)}
.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}
.shard{width:1.05em;height:1.05em;display:inline-block;vertical-align:-.17em;margin-right:.34em;flex:0 0 auto}
.tell strong{font-size:15px;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:var(--glass);-webkit-backdrop-filter:var(--glass)}
.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. */
/* The ceremony. A Spritefall is the one moment the game asks you to WAIT, so none of it snaps: each
   shape falls out of the dark out of focus, slows, touches down and throws a ring of its own tier
   colour. Then it holds, silent, until it is tapped - and the grain settles rather than swapping. */
@keyframes descend{
  from{transform:translateY(-62vh) scale(.90);opacity:0;filter:blur(3px)}
  50%{opacity:1}
  74%{transform:translateY(7px) scale(1.03);filter:blur(0)}
  88%{transform:translateY(-2px) scale(.995)}
  to{transform:none;opacity:1;filter:blur(0)}
}
/* what the landing throws off, in the colour of how intact the seed was */
@keyframes land{
  from{box-shadow:0 0 0 0 color-mix(in srgb,var(--rarity) 70%,transparent)}
  to{box-shadow:0 0 40px 14px transparent}
}
/* the grain gathering: a flare, then the shape resolves out of it */
@keyframes gather{0%{filter:brightness(1) saturate(1)}38%{filter:brightness(2.9) saturate(1.5)}to{filter:brightness(1) saturate(1)}}
@keyframes settle{0%{transform:scale(1.09)}58%{transform:scale(.975)}to{transform:none}}
.fell[data-fell]{
  animation:descend 1.05s var(--ease) both, land .8s var(--ease) both;
  animation-delay:calc(var(--i,0) * 240ms), calc(var(--i,0) * 240ms + .74s);
}
.fell[data-settling] .shot canvas{animation:gather .46s var(--ease)}
.fell[data-settled]{animation:settle .52s 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],.fell[data-settling] .shot canvas{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}

/* today's ground and the week's Anchor sit above the nine, because they are not part of the nine */
.special{display:grid;gap:var(--s2);flex:0 0 auto}
.node.wide{grid-auto-flow:row;min-height:46px;padding:var(--s2) var(--s3);justify-items:start;text-align:left;gap:3px}
.node.wide span{font-family:var(--sans);font-size:var(--t-label);font-weight:600;letter-spacing:var(--track-caption);text-transform:uppercase}
.node.wide .hp{width:100%;margin-top:3px}


/* ---------- the wider screen ----------
   Last, for the same reason the short-screen blocks are: a media query carries no extra
   specificity, so this has to sit after the base rules it raises. It stays ABOVE the
   short-screen blocks, which are allowed to take the title back down on a wide-but-short one. */
/* A bigger screen gets more ROOM AROUND the game, never a bigger game. The page is the same column
   the dock is, centred, so every size and gap measured on a phone holds on a desk without being
   worked out a second time - which is also why there is no longer a min-width:760px block here
   raising the type, the gaps and the padding. One column, one set of numbers. */


/* ---------- short screens ----------
   These sit at the END of the sheet on purpose. A media query adds no specificity, so a block
   written earlier loses to an identical selector defined later in the file - which is exactly what
   had happened: six rules here (.tally, .tell strong, .tell small, .deeds, .deed) were dead the
   whole time, beaten by their own base rules further down. Keep these last. */
/* A title sized only by width grows on a WIDE-but-short screen until it pushes the page off the
   bottom - a laptop, not a phone. Scoped to match: a phone is short by nature and already has its own
   smaller scale, and this rule was quietly undoing it. */
/* (There was a rule here that shrank the title on a wide-but-short screen, back when the display face
   ran to 58px and pushed the page off the bottom. The scale tops out at 30px now, so the same rule had
   turned into the opposite of itself - it was INFLATING the title to 44px on exactly those screens.
   Deleted rather than adjusted: a smaller face never needed rescuing from its own size.) */
@media (max-height:860px){
  /* The archive is a thing to look at, so a short screen may keep it folded away. The store is NOT -
     provisions are bought, and a laptop is about 800px tall, so hiding it here meant a player on a
     MacBook could not buy a poultice at all. Content you act on does not get to be the thing that
     gives way; the display face above is what makes the room. */
  [data-part="archive"]{display:none}
}
@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}
  /* The deeds close up rather than lose a row. They were crushed flat when the type was bigger; the
     smaller phone scale paid that back, so this is now a gentle tightening with about 30px still in
     hand rather than a squeeze with 6 (scratchpad/relax.mjs). */
  .deeds{gap:3px;padding:var(--s1)}
  .deed{min-height:30px}
  .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)}
}
