/* ══ PUNCH_CARDS ══════════════════════════════════════════════════════════════
   Manila punch cards on a dark green felt table. The chassis IS a card and every
   point of damage is a hole punched through it; the hands are photographed boxing
   gloves and focus mitts. Everything that moves is feedback, never rules — see
   juice.js. Motion degrades to nothing under prefers-reduced-motion.            */

:root {
  --u: 4.6vmin;                 /* one lane */
  --felt: #122a21;
  --paper: #e6d7b3; --paper2: #dccaa0; --pale: #efe4c8;
  --ink: #241d13; --dim: #7d6a43; --edge: #a4926e;
  --hole: #0d1b14; --brass: #c9a24a; --gold: #e8c877;
  --R: #9c2f26; --L: #204a86; --moss: #8dae9c; --moss-d: #5d7c6c;
  --ease-out: cubic-bezier(.16,1,.3,1);
  --ease-back: cubic-bezier(.34,1.56,.64,1);   /* overshoot: follow-through */
}

html, body { height: 100%; }
/* The page ground is a value rather than a declaration, because a punched hole wears
   it too. Both are `fixed`, so the gradient and texture inside a hole line up exactly
   with the page behind the card — the hole really does show through. */
:root { --page-bg:
  repeating-linear-gradient(-45deg, rgba(0,0,0,.07) 0 1px, transparent 1px 6px),
  radial-gradient(ellipse at 50% 0%, #265143, var(--felt) 58%, #0a1a14); }
body {
  background: var(--page-bg);
  background-attachment: fixed;
  color: #dfe9dd;
  font-family: 'Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  padding: 14px 12px 40px;          /* the house frame, docs/design.md → Shape and space */
}
/* The ground is the hatch in --page-bg, not an overlay: an overlay would sit above
   the cards too and take the clean off the paper. */
#root { font-size: calc(var(--u) * .30); user-select: none;
  display: flex; flex-direction: column; min-height: calc(100vh - 54px); }

/* Everything freezes for a beat on contact. One class, no per-element bookkeeping. */
body.hitstop *, body.hitstop *::before, body.hitstop *::after {
  animation-play-state: paused !important;
  transition: none !important;
}

/* ── the table ─────────────────────────────────────────────────────────────── */
.menu, .game { position: relative; width: 100%; max-width: 1560px; margin-inline: auto;
  /* A column that grows, so the paper below the card reaches the foot of the page
     however short the card itself is. */
  flex: 1 1 auto; display: flex; flex-direction: column;
  transform: var(--shake, none); }
/* The board is the page: the transcript is the last thing on it and the paper runs
   off the bottom edge, the way continuous form does when it is still in the printer. */
.game { display: flex; flex-direction: column; gap: calc(var(--u) * .34);
  min-height: calc(100vh - 54px); }

.masthead { display: flex; align-items: flex-end; gap: 1.4em;
  border-bottom: 1px solid rgba(232,200,120,.22); padding-bottom: .5em; }
.brand { font-size: 1.35em; font-weight: 700; letter-spacing: .2em; color: #f2e9d5; }
.brand em { font-style: normal; color: var(--gold); }
.who { flex: 1; display: flex; justify-content: center; gap: 1.6em; align-items: baseline;
  font-size: .74em; letter-spacing: .18em; color: var(--moss); }
.who b { color: #f2e9d5; font-weight: 700; font-size: 1.2em; }
.who i { font-style: normal; color: var(--moss-d); }
.clock { text-align: right; font-size: .68em; letter-spacing: .16em; color: var(--moss); line-height: 1.8; }
.clock b { color: var(--gold); font-weight: 600; }
.menu-upper { display: flex; gap: 1.4em; font-size: .64em; letter-spacing: .2em; color: var(--moss-d); }

/* ── the arena ─────────────────────────────────────────────────────────────── */
.arena { display: flex; align-items: flex-start; justify-content: center; gap: calc(var(--u) * .5); }
.bay { flex: 1 1 0; display: flex; }
.bay.left  { justify-content: flex-end;   padding-right: calc(var(--u) * 2.1); }
.bay.right { justify-content: flex-start; padding-left:  calc(var(--u) * 2.1); }
.lanescale { flex: none; width: calc(var(--u) * 1.6); padding-top: calc(var(--u) * .95);
  position: relative; z-index: 0; }
/* Hands reach across the scale, so the bays paint above it. */
.bay { position: relative; z-index: 1; }
.lanescale span { display: block; height: var(--u); line-height: var(--u); text-align: center;
  font-size: .72em; color: var(--moss-d); position: relative; }
.lanescale span::before, .lanescale span::after { content: ""; position: absolute; top: 50%;
  width: calc(var(--u) * 2.0); border-top: 1px dashed rgba(232,200,120,.16); }
.lanescale span::before { right: 100%; } .lanescale span::after { left: 100%; }

.stacks { flex: none; display: flex; flex-direction: column; gap: calc(var(--u) * .5);
  padding-top: calc(var(--u) * .8); }
.stack { position: relative; width: calc(var(--u) * 1.9); height: calc(var(--u) * 1.25); }
.stack em { position: absolute; left: 0; right: 0; top: -1.25em; text-align: center; font-style: normal;
  font-size: .56em; letter-spacing: .2em; color: var(--moss-d); }
.stack i { position: absolute; left: 0; right: 0; height: calc(var(--u) * 1.05);
  background: linear-gradient(158deg, var(--paper), var(--paper2)); border: 1px solid var(--edge);
  clip-path: polygon(8px 0, 100% 0, 100% 100%, 0 100%, 0 8px); }
.stack i:nth-child(2){ top: 6px } .stack i:nth-child(3){ top: 4px }
.stack i:nth-child(4){ top: 2px } .stack i:nth-child(5){ top: 0 }
.stack b { position: absolute; left: 0; right: 0; top: .5em; text-align: center; z-index: 9;
  font-size: 1.3em; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }

/* ── the chassis: a punch card, damage punched through it ──────────────────── */
.chassis { position: relative; width: calc(var(--u) * 3); }
.plate { position: relative; color: var(--ink); border: 1px solid var(--edge);
  background: linear-gradient(157deg, var(--paper), var(--paper2));
  box-shadow: 0 calc(var(--u)*.22) calc(var(--u)*.5) rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.5);
  clip-path: polygon(11px 0, 100% 0, 100% 100%, 0 100%, 0 11px); }
.side-right .plate, .bay.right .plate { clip-path: polygon(0 0, calc(100% - 11px) 0, 100% 11px, 100% 100%, 0 100%); }
.plate.jolt { animation: jolt .34s var(--ease-out); }
@keyframes jolt { 0% { transform: translateX(0) } 18% { transform: translateX(calc(var(--u)*.11)) scaleY(.965) }
  55% { transform: translateX(calc(var(--u)*-.05)) scaleY(1.02) } 100% { transform: none } }
.hdr { display: flex; justify-content: space-between; padding: .5em .7em; font-size: .56em;
  letter-spacing: .18em; color: #95866a; border-bottom: 1px solid rgba(120,100,60,.34); }
.zone { display: flex; border-bottom: 1px solid rgba(120,100,60,.3); position: relative; }
.zone:last-child { border-bottom: none; }
.zone.z2 { height: calc(var(--u) * 2); } .zone.z3 { height: calc(var(--u) * 3); }
.bay.right .zone { flex-direction: row-reverse; }
.znside { width: 44%; flex: none; padding: 0 .5em; display: flex; flex-direction: column; justify-content: center; }
.zn { font-size: .52em; letter-spacing: .16em; color: #95866a; }
.hp { font-size: 1.25em; font-weight: 600; line-height: 1.1; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.hp s { text-decoration: none; font-size: .48em; color: #95866a; font-weight: 400; }
.lost { font-size: .5em; color: var(--R); font-weight: 600; letter-spacing: .04em; min-height: 1em; }
.field { flex: 1; min-width: 0; display: grid; gap: 2px; padding: 0 .4em;
  grid-template-columns: repeat(var(--cols), 1fr); align-content: center; justify-content: center; }
.field i { aspect-ratio: 1; min-width: 0; border-radius: 1px; background: rgba(134,110,64,.55);
  box-shadow: inset 0 0 0 .5px rgba(120,100,60,.42); transition: background .18s ease, box-shadow .18s ease; }
.field i.p { background: var(--page-bg); background-attachment: fixed;
  box-shadow: inset 0 2px 3px rgba(0,0,0,.55), 0 1px 0 rgba(255,255,255,.32); }
.field i.fresh { animation: punched .5s var(--ease-out); }
@keyframes punched { 0% { transform: scale(2.4); box-shadow: 0 0 0 3px var(--R), 0 0 14px rgba(156,47,38,.9) }
  60% { box-shadow: 0 0 0 2px var(--R), 0 0 8px rgba(156,47,38,.6) }
  100% { transform: scale(1); box-shadow: inset 0 2px 3px rgba(0,0,0,.95) } }
.zone.struck { animation: struck .4s ease-out; }
@keyframes struck { 0%,100% { background: transparent } 22% { background: rgba(156,47,38,.24) } }
.zone.mended { animation: mended .5s ease-out; }
@keyframes mended { 0%,100% { background: transparent } 30% { background: rgba(120,180,130,.22) } }

/* ── the hands ─────────────────────────────────────────────────────────────── */
.hands { position: absolute; top: calc(var(--u) * .95); bottom: 0; width: 0; }
.bay.left .hands { left: 100%; } .bay.right .hands { right: 100%; }
.hand { position: absolute; top: calc(var(--u) * (var(--lane, 3) - 1));
  height: calc(var(--u) * var(--span, 1)); width: auto;
  filter: saturate(.86) brightness(.96) contrast(1.02) sepia(.06) drop-shadow(0 4px 6px rgba(0,0,0,.5));
  transition: top .3s var(--ease-back), left .26s var(--ease-back), right .26s var(--ease-back),
              transform .26s var(--ease-back); will-change: top, transform; }
.bay.left .hand { left: calc(var(--u) * .12); } .bay.right .hand { right: calc(var(--u) * .12); }
.hand.mir { transform: scaleX(-1); }
.hand.guard { height: calc(var(--u) * 2); } .hand.fist { height: calc(var(--u) * 1.02); }
.bay.left .hand.charged { left: calc(var(--u) * -.12); } .bay.right .hand.charged { right: calc(var(--u) * -.12); }
.hand.charged { filter: saturate(1) brightness(1.06) drop-shadow(0 0 10px rgba(232,200,120,.85))
  drop-shadow(0 4px 6px rgba(0,0,0,.5)); }
.hand.cocked { animation: cocked .42s var(--ease-back); }
@keyframes cocked { 0% { transform: translateX(0) } 45% { transform: translateX(-14%) scale(1.08) } }
.hand.mir.cocked { animation-name: cockedR; }
@keyframes cockedR { 0% { transform: scaleX(-1) } 45% { transform: scaleX(-1) translateX(-14%) scale(1.08) } }
/* The gap between the two chassis is 6.8u: 2.1 bay padding + .5 arena gap + 1.6 lane
   scale + .5 + 2.1. A thrown fist is about 1.7u wide, so it travels 5.1u for its
   leading edge to land on the opponent's plate — and stops a guard's width short
   when the blow is blocked. Anything less and the punch swings at open air. */
.arena { --gap: 6.8; --fist: 1.7; }
.bay.left .hand.attacking { left: calc(var(--u) * (var(--gap) - var(--fist))); }
.bay.right .hand.attacking { right: calc(var(--u) * (var(--gap) - var(--fist))); }
.bay.left .hand.attacking.blocked { left: calc(var(--u) * (var(--gap) - var(--fist) - .8)); }
.bay.right .hand.attacking.blocked { right: calc(var(--u) * (var(--gap) - var(--fist) - .8)); }
.hand.thrown { animation: thrown .3s var(--ease-out); }
@keyframes thrown { 0% { transform: scaleX(1.16) scaleY(.9) } 100% { transform: none } }
.hand.mir.thrown { animation-name: thrownR; }
@keyframes thrownR { 0% { transform: scaleX(-1.16) scaleY(.9) } 100% { transform: scaleX(-1) } }

/* ── the clock (off by default) ────────────────────────────────────────────── */
.tick { position: absolute; left: 50%; bottom: calc(var(--u) * -1.4); transform: translateX(-50%);
  width: calc(var(--u) * 1.5); height: calc(var(--u) * 1.5); }
.tick .hand { position: absolute; inset: 0; }
.tick .count { display: none; }
.time-to-input { position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 1.4em; font-weight: 600; color: var(--moss); }
.time-to-input.active { color: var(--gold); }
.time-to-input.urgent { color: var(--R); animation: urgent .5s ease-in-out infinite; }
@keyframes urgent { 50% { transform: scale(1.2) } }
.state { display: none; }

/* ── the seats ─────────────────────────────────────────────────────────────── */
.seats { display: flex; gap: calc(var(--u) * .8); }
.seat { flex: 1 1 0; min-width: 0; }
.seat-h { display: flex; justify-content: space-between; gap: 1em; font-size: .58em;
  letter-spacing: .18em; color: var(--moss); border-bottom: 1px solid rgba(232,200,120,.18);
  padding-bottom: .4em; margin: .9em 0 .6em; }
.seat-h b { color: var(--gold); font-weight: 600; }
.actions, .cards { display: flex; justify-content: center; gap: calc(var(--u) * .16); }

/* One card, two sizes. Same proportions, same face, same punch pattern — a card
   in the reader is the card that was in the hopper, only nearer. */
.card { position: relative; flex: none; box-sizing: border-box; color: var(--ink);
  width: min(calc(var(--u) * var(--cw, 4.6)),
             calc((100% - var(--u) * .16 * (var(--n, 3) - 1)) / var(--n, 3)));
  aspect-ratio: 1.79;
  padding: .5em .6em 0; display: flex; gap: .5em; align-items: flex-start;
  background: linear-gradient(157deg, var(--paper), var(--paper2)); border: 1px solid var(--edge);
  clip-path: polygon(10px 0, 100% 0, 100% 100%, 0 100%, 0 10px);
  box-shadow: 0 calc(var(--u)*.1) calc(var(--u)*.2) rgba(0,0,0,.42);
  transition: transform .18s var(--ease-back), box-shadow .18s var(--ease-out), filter .18s ease;
  will-change: transform; }
.cards .card { --cw: 2.75; font-size: .72em; padding-top: .5em; }
.card .icon { flex: none; width: 1.9em; height: 1.9em; color: var(--ink); }
.card .icon svg { width: 100%; height: 100%; }
.card .icon.hit { color: var(--R); } .card .icon.mend { color: var(--L); }
.card .text { min-width: 0; padding-right: 1.9em; overflow: hidden; }
.card .nm { display: block; font-size: 1.02em; font-weight: 600; line-height: 1.1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card .nt { display: block; font-size: .56em; letter-spacing: .1em; color: var(--dim); margin-top: .25em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card .holes { position: absolute; left: .55em; right: .55em; bottom: .4em; opacity: .72;
  display: grid; grid-template-columns: repeat(32, 1fr); gap: 1px; }
.card .holes i { aspect-ratio: 1; border-radius: .5px; background: rgba(120,100,60,.3); }
.card .holes i.p { background: var(--page-bg); background-attachment: fixed;
  box-shadow: inset 0 1px 2px rgba(0,0,0,.5); }
.cards .card .holes { opacity: .55; }
.card:hover { transform: translateY(-5%) scale(1.02); box-shadow: 0 calc(var(--u)*.17) calc(var(--u)*.3) rgba(0,0,0,.5); }
.card.used { filter: saturate(.28) brightness(.84); }
.card.facedown > * { display: none; }
.card.selected { outline: 2px solid var(--gold); outline-offset: 2px; }
.card.highlight { z-index: 10; transform: translateY(-7%) scale(1.04);
  box-shadow: 0 calc(var(--u)*.2) calc(var(--u)*.34) rgba(0,0,0,.55), 0 0 0 2px var(--gold); }
.card.reading::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(255,246,214,.85), transparent);
  animation: sweep .42s ease-out; }
@keyframes sweep { from { transform: translateY(-100%) } to { transform: translateY(100%) } }
.hand-toggle { position: absolute; top: .45em; right: .5em; width: 1.75em; height: 1.75em;
  display: grid; place-items: center; border-radius: 50%; border: .13em solid;
  font-size: .84em; font-weight: 700; line-height: 1; transform: rotate(-13deg); opacity: .92; }
.hand-toggle.right { color: var(--R); border-color: var(--R); }
.hand-toggle.left { color: var(--L); border-color: var(--L); }
.hand-toggle.clickable:hover { transform: rotate(-13deg) scale(1.14); }

.button { margin: calc(var(--u) * .34) auto 0; width: fit-content; padding: .5em 1.6em;
  font-size: .9em; font-weight: 700; letter-spacing: .22em; background: var(--ink); color: var(--paper);
  box-shadow: 0 4px 0 rgba(36,29,19,.35); cursor: pointer;
  transition: transform .12s var(--ease-out), box-shadow .12s var(--ease-out); }
.button:hover { transform: translateY(-2px); box-shadow: 0 6px 0 rgba(36,29,19,.35); }
.button:active { transform: translateY(2px); box-shadow: 0 1px 0 rgba(36,29,19,.35); }
.button.pushed { background: transparent; border: 2px dashed rgba(232,200,120,.4);
  color: var(--moss-d); box-shadow: none; cursor: default; }

/* ── the transcript, printing on continuous form ───────────────────────────── */
.strip { position: relative; flex: 1 1 auto; margin: calc(var(--u) * .5) 0 -40px;
  background: #f5f8ef; color: #2b2b26; box-shadow: 0 -8px 24px rgba(0,0,0,.35); overflow: hidden; }
.strip .edge { position: absolute; top: 0; bottom: 0; width: 1.9em; background: #eef1e8; z-index: 2;
  display: flex; flex-direction: column; justify-content: space-around; align-items: center; }
.strip .edge.l { left: 0; border-right: 1px dashed rgba(0,0,0,.2); }
.strip .edge.r { right: 0; border-left: 1px dashed rgba(0,0,0,.2); }
/* Sprocket holes all the way down, however tall the paper ends up. */
.strip .edge { background-image: radial-gradient(circle at 50% .8em, #18332a .34em, transparent .35em);
  background-size: 100% 2.1em; background-repeat: repeat-y; }
.strip .sh { position: relative; z-index: 3; height: 2.4em; padding: 0 3em; display: flex;
  align-items: center; justify-content: space-between; font-size: .56em; letter-spacing: .2em;
  color: #6c7568; border-bottom: 1px solid rgba(0,0,0,.18); }
.strip .bars { position: absolute; left: 0; right: 0; top: 2.4em; bottom: 0; z-index: 0;
  background: repeating-linear-gradient(to bottom, #dbe7d3 0 3.2em, #f8fbf4 3.2em 6.4em); }
.strip .log { position: relative; z-index: 1; padding: 0 3em .4em; font-size: .64em; line-height: 1.6em;
  white-space: pre; }
.strip .log .hot { color: var(--R); font-weight: 700; }

/* ── the menu is a job setup card ──────────────────────────────────────────── */
.menu { max-width: 78rem; padding-top: calc(var(--u) * .4); }
.setup { position: relative; color: var(--ink); border: 1px solid var(--edge);
  background: linear-gradient(157deg, var(--paper), var(--paper2));
  clip-path: polygon(22px 0, 100% 0, 100% 100%, 0 100%, 0 22px);
  box-shadow: 0 calc(var(--u)*.4) calc(var(--u)*.8) rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.5); }
.setup-hd { display: flex; align-items: flex-end; justify-content: space-between; gap: 2em;
  padding: 1.5em 1.7em .8em; border-bottom: 2px solid var(--ink); }
.setup-hd h1 { font-size: 2.9em; font-weight: 700; letter-spacing: .13em; line-height: 1; color: var(--ink); }
.setup-hd h1 em { font-style: normal; color: var(--R); }
.setup-hd .form { text-align: right; font-size: .62em; letter-spacing: .2em; color: var(--dim); line-height: 1.9; }
.setup-hd .form b { color: var(--ink); font-weight: 600; }
.setup-cols { display: flex; }
.setup-l { width: 56%; padding: 1.1em 1.4em 1.2em 1.7em; border-right: 1px solid rgba(120,100,60,.34); }
.setup-r { flex: 1; padding: 1.1em 1.7em 1.2em 1.4em; }

.fieldrow { display: flex; align-items: center; gap: .9em; margin-bottom: .6em; }
.fieldrow .lb { font-size: .6em; letter-spacing: .18em; color: var(--dim); width: 9em; flex: none; }
.fieldrow .val { flex: 1; display: flex; align-items: center; justify-content: space-between; gap: .8em;
  background: var(--pale); border: 1px solid rgba(120,100,60,.42); padding: .35em .6em; }
.fieldrow .val u { text-decoration: none; font-size: .55em; letter-spacing: .16em; color: var(--dim); flex: none; }
/* A number field is as wide as the number. Stretching a two-digit hit-point value
   across the sheet made the unit that explains it land a foot away from it. */
.fieldrow .val:has(input[type="number"]) { justify-content: flex-start; }
.fieldrow .input[type="number"] { width: 4em; flex: none; text-align: right; }
.fieldrow .input { width: 100%; border: none; background: transparent; color: var(--ink);
  font: inherit; font-weight: 600; font-size: .9em; padding: 0; }
.fieldrow .input:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }

.secl { font-size: .6em; letter-spacing: .2em; color: var(--dim); margin: 1.1em 0 .5em;
  border-top: 1px solid rgba(120,100,60,.34); padding-top: .7em; }
.secl b { color: var(--ink); font-weight: 600; }
.job { display: flex; align-items: center; gap: .9em; padding: .32em .7em .32em 0; position: relative;
  cursor: pointer; transition: background .14s ease; }
.job .punch { display: flex; gap: .22em; flex: none; }
.job .punch i { width: .62em; height: .9em; border-radius: 1px; background: rgba(134,110,64,.55);
  box-shadow: inset 0 0 0 .5px rgba(120,100,60,.42); transition: background .16s var(--ease-out); }
.job.on .punch i { background: var(--page-bg); background-attachment: fixed;
  box-shadow: inset 0 2px 3px rgba(0,0,0,.55); }
.job .nm { flex: 1; font-size: .95em; letter-spacing: .02em; }
.job.on .nm { font-weight: 700; }
.job .nt { font-size: .58em; letter-spacing: .14em; color: var(--dim); }
.job.on { background: rgba(156,47,38,.24); }
.job.on::before { content: ""; position: absolute; left: -1.7em; top: 0; bottom: 0; width: .3em; background: var(--R); }
.job:hover:not(.on) { background: rgba(120,100,60,.3); }
.job:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }

.adv { display: flex; gap: 1.6em; }
.adv span { font-size: .78em; letter-spacing: .04em; cursor: pointer; border-bottom: 1px dotted rgba(120,100,60,.42); }
.adv span::before { content: "\25B8 "; color: var(--brass); }
.adv span:hover { color: var(--R); }

.manifest { display: grid; grid-template-columns: 1fr 1fr; gap: .12em 1.4em; }
.mrow { display: flex; align-items: center; gap: .5em; font-size: .66em; }
.mic { width: 1.25em; height: 1.25em; flex: none; color: var(--ink); opacity: .8; }
.mic svg { width: 100%; height: 100%; display: block; }
.mnm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mct { color: var(--dim); font-weight: 600; flex: none; }

.rlabel { font-size: .6em; letter-spacing: .2em; color: var(--dim); margin-bottom: .5em; }
.preview { border: 1px solid rgba(120,100,60,.42); background: var(--pale); padding: 1em .8em .6em;
  display: flex; align-items: flex-start; justify-content: center; gap: 1.6em; flex-wrap: wrap; }
.pc-chassis { width: 7em; border: 1px solid var(--edge);
  background: linear-gradient(157deg,var(--paper),var(--paper2));
  box-shadow: 0 3px 8px rgba(0,0,0,.35); }
.pz { box-sizing: border-box; height: calc(var(--lanes) * 1.5em); border-bottom: 1px solid rgba(120,100,60,.3);
  padding: .25em .4em; display: flex; flex-direction: column; justify-content: center; }
.pz:last-child { border-bottom: none; }
.pz span { font-size: .48em; letter-spacing: .14em; color: #95866a; }
.pz b { font-size: .8em; font-weight: 600; }
.pc-lanes { width: 2.4em; padding-top: 1px; }
/* The row box stays in the panel's em so it matches `.pz`; only the digit shrinks.
   Sizing the box in the span's own smaller em compressed seven lanes into four. */
.pc-lanes span { display: block; height: 1.5em; line-height: 1.5em; text-align: center;
  color: var(--dim); position: relative; }
.pc-lanes span i { font-style: normal; font-size: .62em; }
.pc-lanes span::before, .pc-lanes span::after { content: ""; position: absolute; top: 50%; width: 1.1em;
  border-top: 1px dashed rgba(120,100,60,.42); }
.pc-lanes span::before { right: 100%; } .pc-lanes span::after { left: 100%; }
.pc-cap { width: 100%; text-align: center; font-size: .52em; letter-spacing: .14em; color: var(--dim); margin-top: .4em; }
.stat { display: flex; justify-content: space-between; font-size: .6em; letter-spacing: .16em;
  color: var(--dim); margin-top: .8em; border-top: 1px solid rgba(120,100,60,.34); padding-top: .6em; }
.stat b { color: var(--ink); font-weight: 600; }
.how { list-style: none; counter-reset: h; }
.how li { counter-increment: h; font-size: .68em; line-height: 1.5; margin-bottom: .5em;
  padding-left: 1.8em; position: relative; }
.how li::before { content: counter(h); position: absolute; left: 0; top: .1em; width: 1.2em; height: 1.2em;
  background: var(--ink); color: var(--paper); font-size: .8em; display: grid; place-items: center; }

.setup-ft { display: flex; align-items: center; justify-content: space-between; gap: 2em;
  border-top: 2px solid var(--ink); padding: .9em 1.7em; }
.setup-ft .inv { flex: 1 1 auto; font-size: .58em; letter-spacing: .16em; color: var(--dim); min-width: 0; }
.setup-ft .inv b { display: block; margin-top: .3em; }
/* A link nobody can read is not an invitation: full width, and big enough to check. */
.invite-link { font-size: 1.6em; font-weight: 400; letter-spacing: .02em;
  text-overflow: ellipsis; cursor: pointer; }
.invite-link.success { color: var(--L); }
.setup-ft .inv .input { width: 100%; max-width: none; border: none; background: transparent;
  color: var(--L); font: inherit; font-size: 1.5em; font-weight: 600; letter-spacing: 0; padding: 0; }
.feed { display: flex; align-items: center; gap: .8em; flex: none; background: var(--ink); color: var(--paper);
  padding: .7em 1.4em; font-size: .78em; font-weight: 700; letter-spacing: .22em; cursor: pointer;
  box-shadow: 0 4px 0 rgba(36,29,19,.35); transition: transform .12s var(--ease-out), box-shadow .12s var(--ease-out); }
.feed:hover { transform: translateY(-2px); box-shadow: 0 6px 0 rgba(36,29,19,.35); }
.feed:active { transform: translateY(2px); box-shadow: 0 1px 0 rgba(36,29,19,.35); }
.feed .dots { display: flex; gap: .18em; }
.feed .dots i { width: .3em; height: .62em; background: var(--gold); border-radius: 1px; }
.menu-strip { position: relative; flex: 1 1 auto; margin: calc(var(--u) * .6) 0 -40px; min-height: 7em; }
/* The paper is as wide as the board it belongs to. It only runs to the screen edges
   once the board itself does — below 1560 + the page's own 12px gutters. */
@media (max-width: 1584px) {
  .strip, .menu-strip { margin-inline: -12px; }
}

/* The connection card: the same sheet as the job setup, with the codes printed on it. */
.setup.wait { display: flex; flex-direction: column; }
.wait-cols { display: flex; gap: 2.6em; padding: 1.6em 2.2em 1.2em; }
.wait-cols.one { justify-content: center; }
.wait-half { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center;
  gap: .7em; text-align: center; }
.wait-half.wide { max-width: 46em; }
.wait-half .secl { align-self: stretch; }
.wait-half .qr-code { align-self: center; width: max-content; padding: .7em; background: var(--paper);
  border: 1px solid rgba(120,100,60,.45); box-shadow: 0 2px 0 rgba(36,29,19,.16); line-height: 0; }
/* qrcodejs draws to a canvas and then shows an <img> of it; only the image is wanted. */
.wait-half .qr-code canvas { display: none; }
.wait-half .qr-code img { display: block; width: 15em; height: 15em; image-rendering: pixelated; }
/* Until the broker answers there is no code to print. An empty bordered square reads
   as broken, so the box says what it is waiting for and holds the same space. */
.wait-half .qr-code:empty { width: 15em; height: 15em; border-style: dashed;
  display: flex; align-items: center; justify-content: center; line-height: 1.5;
  padding: 1.5em; text-align: center; }
.wait-half .qr-code:empty::after { content: "the code prints once the network answers";
  font-size: .62em; letter-spacing: .12em; color: var(--dim); }
/* The label wraps the field, so it is the label that has to span the column. */
.wait-half .line { display: block; width: 100%; }
.wait-half .input { width: 100%; }
/* Gold is the felt's colour; on card stock the link is ink. */
/* Beats `.menu .line .input`, which paints fields gold for the felt, not for card stock. */
.menu .wait-half .input.invite-link { color: var(--ink); font-size: .78em; text-align: center; }
.menu .wait-half .input.invite-link.success { color: var(--L); }
.wait-half .connected { font-size: 1.4em; font-weight: 700; letter-spacing: .18em; color: var(--L);
  padding: 3em 0; }
.setup-ft .waitmsg { font-size: 1.5em; letter-spacing: .1em; }
.feed.back { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px rgba(36,29,19,.5); }
.feed.back:hover { background: rgba(36,29,19,.08); box-shadow: inset 0 0 0 1px rgba(36,29,19,.5); transform: none; }
.feed.back .dots i { background: var(--ink); }

/* The two settings sheets: rows of fields, and the deck as a printed inventory. */
.handrows { display: flex; flex-direction: column; }
.handrow { display: flex; align-items: center; gap: .8em; padding: .3em 0; }
.handrow + .handrow { border-top: 1px dotted rgba(120,100,60,.34); }
.handrow .sq { font-size: .6em; letter-spacing: .12em; color: var(--dim); width: 1.2em; flex: none; }
.handrow select { flex: 1; min-width: 0; }
.deckrows { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 1.6em; }
.deckrow { display: flex; align-items: center; gap: .6em; padding: .28em 0; }
.deckrow + .deckrow { border-top: 1px dotted rgba(120,100,60,.34); }
.deckrow .pic, .handrow .pic { width: 1.15em; height: 1.15em; flex: none; color: var(--ink); }
.deckrow .pic svg, .handrow .pic svg { width: 100%; height: 100%; display: block; }
.deckrow .nm { flex: 1; min-width: 0; font-size: .82em; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.deckrow .input, .handrow .input { background: rgba(255,255,255,.34); color: var(--ink);
  border: none; border-bottom: 1px solid rgba(120,100,60,.42); font: inherit; padding: .2em .5em; }
.deckrow .input { width: 3.2em; text-align: right; flex: none; }
.setup .fieldrow .input { color: var(--ink); }

/* The settings sub-menus still use the plain printed list. */
.qr-code { width: 60%; margin: .6em auto; } .qr-code > * { width: 100%; height: auto; }
.menu-half { display: inline-block; width: 50%; text-align: center; vertical-align: top; }
.menu .line { display: block; line-height: 2; font-size: .95em; }
h1.line { font-size: 2.6em; font-weight: 700; letter-spacing: .14em; text-align: center; color: #f2e9d5; }
.clickable { cursor: pointer; }
.clickable.with-hover:hover { color: var(--gold); }
.indented { padding-left: 1.6em; }
.menu .line .input { border: none; background: rgba(255,255,255,.05); color: var(--gold); font: inherit;
  font-weight: 600; padding: .2em .4em; }

/* ── overlays and effects ──────────────────────────────────────────────────── */
.message-overlay {
  position: absolute; left: 0; right: 0; top: 22%; text-align: center; z-index: 40;
  font-size: 4.5em; font-weight: 700; letter-spacing: .1em; color: var(--gold);
  text-shadow: 0 0 30px rgba(232,200,120,.5), 0 6px 0 rgba(0,0,0,.35); pointer-events: none;
}
.message-overlay.shout { animation: shout .45s var(--ease-back); }
@keyframes shout { 0% { transform: scale(2.2); opacity: 0 } 55% { transform: scale(.94); opacity: 1 } 100% { transform: scale(1) } }

.fx { position: absolute; inset: 0; pointer-events: none; z-index: 50; overflow: visible; }
.chad { position: absolute; width: 6px; height: 4px; border-radius: 1px; background: var(--hole);
        box-shadow: 0 1px 0 rgba(255,255,255,.28);
        animation: chad var(--dur, 700ms) cubic-bezier(.2,.6,.4,1) forwards; }
@keyframes chad {
  0% { transform: translate(0,0) rotate(0); opacity: 1 }
  100% { transform: translate(var(--dx), calc(var(--dy) + 90px)) rotate(var(--rot)); opacity: 0 }
}
.floater { position: absolute; transform: translate(-50%, 0); font-size: 1.6em; font-weight: 700;
           letter-spacing: -.02em; animation: floater 1.05s var(--ease-out) forwards; }
.floater.hurt { color: #ff8f7f; text-shadow: 0 2px 0 rgba(0,0,0,.4), 0 0 18px rgba(156,47,38,.7); }
.floater.heal { color: #a8e6b4; text-shadow: 0 2px 0 rgba(0,0,0,.4), 0 0 18px rgba(80,180,110,.6); }
@keyframes floater {
  0% { transform: translate(-50%, 8px) scale(.7); opacity: 0 }
  22% { transform: translate(-50%, -6px) scale(1.18); opacity: 1 }
  100% { transform: translate(-50%, -52px) scale(1); opacity: 0 }
}

/* ── the phone: the punch card, printed small ──────────────────────────────── */
:root:has(.mobile) body, body:has(.mobile) { padding: 0; overflow: hidden; }
body:has(.mobile) #root { min-height: 0; }
.mobile { --u: 9vmin; position: fixed; inset: 0; display: flex;
  background: linear-gradient(160deg, var(--paper), var(--paper2));
  color: var(--ink); -webkit-tap-highlight-color: transparent; overflow: hidden; }
.mobile::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(90deg, rgba(120,100,60,.055) 0 1px, transparent 1px 8px); }
.colticks { width: 1.15em; flex: none; padding: 3.4em 0 .6em; display: flex; flex-direction: column;
  justify-content: space-evenly; align-items: center; border-right: 1px solid rgba(120,100,60,.34); }
.colticks span { font-size: .42em; color: var(--dim); }
.mobile .pad { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.mobile .tbar { display: flex; justify-content: space-between; align-items: baseline; flex: none;
  padding: 1.1em .9em .5em; border-bottom: 2px solid var(--ink); }
.mobile .tbar .t { font-size: .95em; font-weight: 700; letter-spacing: .13em; }
.mobile .tbar .t em { font-style: normal; color: var(--R); }
.mobile .tbar .side { font-size: .56em; letter-spacing: .16em; color: var(--dim); }
.mobile .tbar .side b { color: var(--L); font-weight: 700; }
.mobile .formline { display: flex; justify-content: space-between; flex: none;
  padding: .45em .9em 0; font-size: .5em; letter-spacing: .2em; color: var(--dim); }

.mobile .seat { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.mobile .sect { padding: .7em .9em 0; flex: none; }
/* The sheet is one fixed height, so the rows share it out instead of huddling at the
   top: never under the 44px a thumb needs, taller when the hand is small, and the
   hopper takes the slack (and scrolls, on the day someone holds twenty cards). */
.mobile .sect.prog, .mobile .sect.hop { display: flex; flex-direction: column; min-height: 0; }
.mobile .sect.hop { flex: 1 1 auto; padding-bottom: .7em; }
.mobile .sect.hop .cards { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.mobile .prow { flex: 1 1 auto; min-height: 44px; }
.mobile .spacer { flex: none; }
/* On the phone a hand is a column of rows, not a row of cards. */
.mobile .actions, .mobile .cards { display: flex; flex-direction: column; gap: 0; }
.mobile .sect h3 { display: flex; justify-content: space-between; font-size: .52em; font-weight: 400;
  letter-spacing: .2em; color: var(--dim); border-bottom: 1px solid rgba(120,100,60,.34);
  padding-bottom: .4em; margin-bottom: .45em; }
.mobile .sect h3 b { color: var(--R); font-weight: 700; }

.status { display: flex; flex-direction: column; gap: .35em; }
.srow { display: flex; align-items: center; gap: .6em; font-size: .72em; color: var(--dim); }
.srow i { width: .55em; height: .55em; border-radius: 50%; background: rgba(134,110,64,.55); flex: none; }
.srow.ok { color: var(--ink); } .srow.ok i { background: var(--L); }
.srow.live i { background: var(--brass); animation: urgent 1s ease-in-out infinite; }
.srow.bad { color: var(--R); } .srow.bad i { background: var(--R); }

.hpbar { display: flex; gap: .9em; padding: .6em .9em .7em; flex: none;
  border-bottom: 1px solid rgba(120,100,60,.34); }
.hpcol { flex: 1; min-width: 0; }
.hpcol .who { font-size: .5em; letter-spacing: .16em; font-weight: 700; margin-bottom: .35em; }
.hpcol .who.mine { color: var(--L); } .hpcol .who.theirs { color: var(--R); }
.hprow { display: flex; align-items: center; gap: .35em; margin-bottom: .18em; }
.hprow .n { font-size: .46em; color: var(--dim); width: 2.6em; flex: none; }
.hprow .f { flex: 1; display: flex; gap: 1.5px; }
.hprow .f i { flex: 1; height: .55em; border-radius: .5px; background: rgba(134,110,64,.55); }
.hprow .f i.p { background: var(--page-bg); background-attachment: fixed;
  box-shadow: inset 0 1px 2px rgba(0,0,0,.5); }
.hprow .v { font-size: .5em; font-weight: 600; width: 3.4em; text-align: right; flex: none; }

/* A row you punch, which is the same gesture the menu and the reader use. */
.prow { display: flex; align-items: center; gap: .55em; padding: .42em .3em; position: relative;
  cursor: pointer; transition: background .14s ease; }
.prow + .prow { border-top: 1px dotted rgba(120,100,60,.34); }
.prow .sq { font-size: .46em; letter-spacing: .12em; color: var(--dim); width: .9em; flex: none; }
.prow .pn { display: flex; gap: .18em; flex: none; }
.prow .pn i { width: .5em; height: .74em; border-radius: 1px; background: rgba(134,110,64,.55);
  box-shadow: inset 0 0 0 .5px rgba(120,100,60,.42); transition: background .16s var(--ease-out); }
.prow.on .pn i { background: var(--page-bg); background-attachment: fixed;
  box-shadow: inset 0 2px 3px rgba(0,0,0,.55); }
.prow .pic { width: 1.25em; height: 1.25em; flex: none; color: var(--ink); }
.prow .pic svg { width: 100%; height: 100%; display: block; }
.prow .pic.hit { color: var(--R); } .prow .pic.mend { color: var(--L); }
.prow .pnm { flex: 1; min-width: 0; font-size: .78em; font-weight: 600; line-height: 1.15;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prow .pnm u { display: block; text-decoration: none; font-size: .62em; font-weight: 400;
  letter-spacing: .1em; color: var(--dim); margin-top: .1em; }
.prow.on { background: rgba(156,47,38,.24); }
.prow.used { opacity: .42; }
.prow.empty .pnm { color: var(--dim); font-weight: 400; font-style: italic; }
.prow.reading::before { content: ""; position: absolute; left: -.9em; top: 0; bottom: 0;
  width: .28em; background: var(--gold); }
.prow .hand-toggle { position: static; flex: none; width: 1.5em; height: 1.5em; font-size: .62em; }

.spacer { flex: 1; }
.mobile .timer { display: flex; align-items: center; gap: .6em; padding: 0 .9em .5em; flex: none; }
.mobile .timer.off { visibility: hidden; }
.mobile .timer .lb { font-size: .46em; letter-spacing: .16em; color: var(--dim); }
.mobile .timer .bar { flex: 1; height: .5em; background: rgba(134,110,64,.55); position: relative; }
.mobile .timer .bar i { position: absolute; inset: 0 40% 0 0; background: var(--R); }
.mobile .timer .tick { position: static; width: auto; height: auto; transform: none; }
.mobile .timer .tick .hand, .mobile .timer .tick .count { display: none; }
.mobile .timer .time-to-input { position: static; font-size: .8em; font-weight: 700; color: var(--R); }
.mobile .button { margin: 0 .9em .9em; width: auto; padding: .95em 0; text-align: center;
  font-size: .82em; display: block; }

@media (max-width: 820px) {
  :root { --u: 7.6vmin; }
  .game { }
  .arena { flex-wrap: wrap; }
  .stacks { flex-direction: row; }
  .seats { flex-direction: column; }
}

/* ── phone (legacy) ─────────────────────────────────────────────────────────────────── */
.mobile { --u: 9.5vmin; position: absolute; inset: 0; padding: 3vmin;
          -webkit-tap-highlight-color: transparent; }
@media (max-width: 820px) {
  :root { --u: 7.6vmin; }
  .game { flex-direction: column; align-items: stretch; }
  .side { flex-direction: row; flex-wrap: wrap; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important;
                           transition-duration: .001ms !important; }
  .menu, .game { transform: none !important; }
}


/* ---------------------------------------------------------------------------
   On a phone the sheet is one column: two columns of a 132-column form at 390px
   is a form nobody can read. The arena keeps its geometry and scrolls instead of
   squashing -- the lanes are the game, and a squashed lane is a wrong lane. */
@media (max-width: 900px) {
  .setup-cols { flex-direction: column; }
  .setup-l, .setup-r { border-right: none; }
  .setup-r { border-left: none; border-top: 1px solid rgba(120,100,60,.42); }
  /* Right-aligned form text on a narrow card wraps into a ragged stack. */
  .setup-hd { flex-direction: column; align-items: flex-start; gap: .5em; }
  .setup-hd .form { text-align: left; }
  .deckrows { grid-template-columns: 1fr; }
  .wait-cols { flex-direction: column; align-items: center; gap: 1.6em; }
  .wait-half.wide { max-width: none; }
  .setup-ft { flex-direction: column; align-items: stretch; gap: .9em; }
  .setup-ft .feed { justify-content: center; }
  .fieldrow { flex-direction: column; align-items: stretch; gap: .2em; }
  .fieldrow .lb { font-size: .62em; }
  .menu .wait-half .input.invite-link { font-size: 1.05em; }

  /* The board: masthead stacks, the arena scrolls, the seats go one above the other. */
  .masthead { flex-wrap: wrap; gap: .4em 1em; }
  /* The arena is one wide thing that scrolls; wrapping it puts the robots on top
     of each other, which is not what facing each other looks like. */
  /* `safe center` keeps the arena centred until it overflows, then falls back to
     start -- plain centring makes the left half unreachable in a scroll container. */
  .arena { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; justify-content: safe center; }
  .arena > * { flex: none; }
  .seats { flex-direction: column; gap: 1.2em; }
  .seats > * { width: 100%; min-width: 0; }
  /* A hand is as wide as the hand is; it scrolls rather than pushing the page wide. */
  .seats .actions, .seats .cards { overflow-x: auto; overflow-y: hidden; padding-bottom: .35em; }
  .seats .actions > *, .seats .cards > * { flex: none; }
  .stacks { flex-direction: row; gap: .8em; }
}
