/* Admin Adventures: NES color.
   One palette (the NES 2C02's own values, mirrored in palette.ts), one font ("Smplify 8", ours, drawn on an 8x8 grid),
   and one kind of window: deep blue fill, a 2px white border with notched corners, the way a 1985 RPG drew its menus.
   The world, the people and the monsters are in color. Some colors also say something: red is danger only (drift, alerts,
   DENY, errors, low coffee), green is healthy and done, gold is tokens and XP. Nothing is ever color alone: each has an icon or a word. */

@font-face { font-family: "Smplify 8"; src: url("/fonts/smplify-8.woff") format("woff"); font-weight: 400; font-style: normal; font-display: block; }
@font-face { font-family: "Smplify 8 Mono"; src: url("/fonts/smplify-8-mono.woff") format("woff"); font-weight: 400; font-style: normal; font-display: block; }

:root {
  /* The palette. */
  --nes-black: #000000; --nes-dark: #585858; --nes-gray: #7C7C7C; --nes-light: #BCBCBC; --nes-white: #F8F8F8;
  --nes-navy: #0000BC; --nes-blue: #0058F8; --nes-sky: #3CBCFC; --nes-ice: #A4E4FC;
  --nes-indigo: #4428BC; --nes-violet: #6844FC; --nes-lavender: #B8B8F8;
  --nes-plum: #940084; --nes-pink: #F878F8; --nes-blush: #F8A4C0;
  --nes-crimson: #A80020; --nes-red: #D82800; --nes-red-light: #F87858;
  --nes-umber: #503000; --nes-rust: #881400; --nes-brown: #AC7C00; --nes-orange: #E45C10; --nes-peach: #FCA044;
  --nes-gold: #F8B800; --nes-straw: #F8D878; --nes-cream: #FCE0A8;
  --nes-forest: #005800; --nes-pine: #007800; --nes-green: #00A844; --nes-green-light: #58D854; --nes-mint: #B8F8B8;
  --nes-deep-teal: #004058; --nes-teal: #008888; --nes-aqua: #00E8D8;
  /* What the palette is for. --bg is a window's fill (deep blue); --page is what the windows sit on (black). Every text color
     below passes WCAG AA (4.5:1) on both, and every edge that marks a control passes 3:1 (scripts/contrast-audit.mjs checks). */
  --page: var(--nes-black); --bg: var(--nes-navy); --fg: var(--nes-white); --dim: var(--nes-ice); --faint: var(--nes-light); --rule: var(--nes-sky);
  --drift: var(--nes-red-light); --drift-fill: var(--nes-red);
  --ok: var(--nes-green-light); --ok-fill: var(--nes-green);
  --gold: var(--nes-gold);
  --font: "Smplify 8", ui-monospace, Menlo, Consolas, monospace;
  --font-mono: "Smplify 8 Mono", ui-monospace, Menlo, Consolas, monospace;
  /* A window edge: a 2px white line on each side, and nothing at the corners, so every corner is notched. */
  --edge: 0 -2px 0 0 var(--nes-white), 0 2px 0 0 var(--nes-white), -2px 0 0 0 var(--nes-white), 2px 0 0 0 var(--nes-white);
  --edge-dim: 0 -2px 0 0 var(--nes-sky), 0 2px 0 0 var(--nes-sky), -2px 0 0 0 var(--nes-sky), 2px 0 0 0 var(--nes-sky);
  --edge-gold: 0 -2px 0 0 var(--nes-gold), 0 2px 0 0 var(--nes-gold), -2px 0 0 0 var(--nes-gold), 2px 0 0 0 var(--nes-gold);
  --edge-ok: 0 -2px 0 0 var(--nes-green-light), 0 2px 0 0 var(--nes-green-light), -2px 0 0 0 var(--nes-green-light), 2px 0 0 0 var(--nes-green-light);
  --edge-drift: 0 -2px 0 0 var(--nes-red-light), 0 2px 0 0 var(--nes-red-light), -2px 0 0 0 var(--nes-red-light), 2px 0 0 0 var(--nes-red-light);
  --win: var(--edge), 0 -4px 0 0 var(--nes-black), 0 4px 0 0 var(--nes-black), -4px 0 0 0 var(--nes-black), 4px 0 0 0 var(--nes-black);
  /* Set by theme.ts from the pixel art, so the icons in the interface are the icons in the game. */
  --ic-cup: none; --ic-cup-empty: none; --ic-cup-low: none; --ic-robot: none; --sky: none;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;background:var(--page);color:var(--fg);
  font-family:var(--font);font-size:16px;line-height:24px;font-weight:400;font-synthesis:none;
  -webkit-font-smoothing:none}
b,strong,h1,h2,h3,th{font-weight:400}
body{padding:env(safe-area-inset-top,0px) env(safe-area-inset-right,0px) env(safe-area-inset-bottom,0px) env(safe-area-inset-left,0px);
  overflow:hidden;touch-action:manipulation;-webkit-user-select:none;user-select:none}
button,input,textarea,select{font:inherit;color:inherit;letter-spacing:0}
button{cursor:pointer;border-radius:0}
:focus-visible{outline:2px solid var(--nes-white);outline-offset:2px}
.hidden{display:none!important}
a{color:var(--nes-white)}

/* ---------- the menu cursor: a small triangle that marks the focused choice ---------- */
.choice,.hudbtn,.big,.town,#moves button,.tabs button,.gbtns button{position:relative}
.choice::before,.hudbtn::before,.big::before,.town::before,#moves button::before,.tabs button::before,.gbtns button::before{
  /* Decorative: the second declaration gives the glyph empty alt text so it stays out of the button's accessible name (browsers without alt text keep the first). */
  content:"\25B6";content:"\25B6" / "";position:absolute;left:var(--cx,4px);top:var(--cy,2px);visibility:hidden;color:inherit}
#moves button::before,.tabs button::before{color:var(--nes-white)}
.choice:hover::before,.choice:focus-visible::before,.hudbtn:hover::before,.hudbtn:focus-visible::before,
.big:hover::before,.big:focus-visible::before,.town:hover::before,.town:focus-visible::before,
#moves button:hover:not(:disabled)::before,#moves button:focus-visible::before,
.tabs button:hover::before,.tabs button:focus-visible::before,.gbtns button:hover::before,.gbtns button:focus-visible::before{visibility:visible}
.choice{--cx:2px}.hudbtn{--cx:6px}.big{--cx:10px;--cy:8px}.town{--cx:8px;--cy:12px}#moves button{--cx:-20px}.tabs button{--cx:-18px}.gbtns button{--cx:4px;--cy:8px}

#app{height:100%;display:flex;flex-direction:column;max-width:1040px;margin:0 auto}

/* ---------- the status bar ---------- */
#hud{display:flex;flex-wrap:wrap;align-items:center;gap:0 16px;padding:8px 12px 8px 20px;background:var(--bg);box-shadow:0 2px 0 0 var(--nes-white)}
/* Row one: where you are, and the menu. Row two: how you are doing. */
#hud::after{content:"";order:2;flex-basis:100%;height:0}
#loc{order:0;margin-right:auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:60vw;color:var(--fg);font-size:24px;line-height:32px}
#hud .hudbtn{order:1}
#hud .stat{order:3}
.stat{display:flex;align-items:center;gap:8px;white-space:nowrap;color:var(--dim)}
#lvlTxt{color:var(--fg)}
/* Segmented meters. --segs squares; the fill snaps to whole squares (round() ignores older browsers, which then show the plain width). */
/* A meter sits in a black well (a 2px black frame around it), empty squares gray, so it reads on the blue window. */
.bar{--segs:10;--seg:8px;--gap:2px;position:relative;width:calc(var(--segs) * (var(--seg) + var(--gap)));height:var(--seg);flex:none;
  background:repeating-linear-gradient(90deg,var(--nes-gray) 0 var(--seg),var(--nes-black) var(--seg) calc(var(--seg) + var(--gap)));box-shadow:0 0 0 2px var(--nes-black)}
.bar i{display:block;height:100%;width:0;
  background:repeating-linear-gradient(90deg,var(--fill,var(--nes-green-light)) 0 var(--seg),transparent var(--seg) calc(var(--seg) + var(--gap)));
  transition:width .4s steps(8)}
.bar i[style*="--n"]{width:max(round(down,calc(var(--n) * 1%),calc(100% / var(--segs))),calc(sign(var(--n)) * 100% / var(--segs)))!important}
.bar.xp{--fill:var(--nes-gold)}
.bar.drift{--fill:var(--nes-red-light);--seg:12px;--gap:4px}
.bar.drift i{transition:none}
/* Coffee, as cups. */
.cups{--max:10;--n:10;--cw:18px;--ch:14px;display:inline-block;flex:none;width:calc(var(--max) * var(--cw));height:var(--ch);
  background:var(--ic-cup-empty) 0 0/var(--cw) var(--ch) repeat-x var(--nes-black);box-shadow:0 0 0 2px var(--nes-black);image-rendering:pixelated}
.cups i{display:block;height:100%;width:calc(var(--n) * var(--cw));background:var(--ic-cup) 0 0/var(--cw) var(--ch) repeat-x;image-rendering:pixelated}
/* Low coffee turns the cups red (meter.ts sets .low); the number beside them says the same in words. */
.cups.low i{background-image:var(--ic-cup-low)}
#coffeeStat{gap:8px}
#coffeeTxt{color:var(--dim)}
/* Menu labels. */
.hudbtn{background:none;border:0;padding:2px 6px 2px 22px;color:var(--fg);position:relative}
.hudbtn:hover,.hudbtn:focus-visible{background:var(--nes-white);color:var(--nes-navy)}
.hudbtn:active{transform:translateY(2px)}
#tokenbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:0 12px 0 20px;background:var(--bg)}
#tokenTxt{color:var(--gold);padding:2px 0}
#questbar{background:var(--bg);padding:2px 12px 8px 20px;color:var(--dim);box-shadow:0 2px 0 0 var(--nes-sky);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer}
#questbar span{color:var(--fg)}

/* ---------- the map ---------- */
#stage{flex:1;display:flex;align-items:center;justify-content:center;min-height:0;padding:16px 12px;position:relative}
#cv{image-rendering:pixelated;image-rendering:crisp-edges;display:block;background:var(--page);box-shadow:var(--win)}
#bubble{position:absolute;z-index:5;background:var(--bg);color:var(--fg);padding:6px 12px;line-height:24px;
  max-width:340px;width:max-content;pointer-events:none;box-shadow:var(--edge);transform:translate(-50%,calc(-100% - 22px))}
#bubble::after{content:"\25BC";content:"\25BC" / "";position:absolute;left:50%;bottom:-24px;margin-left:-4px;color:var(--nes-white);line-height:24px}
#bubble b{display:block;color:var(--dim)}
#toast{position:absolute;top:24px;left:50%;transform:translateX(-50%);background:var(--bg);padding:6px 16px;
  box-shadow:var(--edge);pointer-events:none;max-width:90%;text-align:center}

/* ---------- windows ---------- */
#dialog{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(20px + env(safe-area-inset-bottom,0px));
  width:min(92vw,760px);background:var(--bg);padding:20px 24px 16px;z-index:20;box-shadow:var(--win)}
#dname{position:absolute;top:-16px;left:20px;padding:0 10px;background:var(--bg);color:var(--fg);box-shadow:var(--edge);line-height:24px}
#dname:empty{display:none}
#dname.fm::before{content:"";display:inline-block;width:14px;height:10px;margin-right:8px;background:var(--ic-robot) center/14px 10px no-repeat;image-rendering:pixelated}
#dtext{min-height:72px;white-space:pre-line;max-height:52vh;overflow:auto;color:var(--fg)}
#dchoices{display:flex;flex-wrap:wrap;gap:0 28px;margin-top:12px;padding-left:16px}
/* A link under a line (the field note after a knowledge check): small, and it opens smplify.com in a new tab. */
#dlink{margin-top:8px;padding-left:16px;font-size:16px;line-height:24px}
#dlink a{color:var(--fg);padding:0 4px}
#dlink a:hover,#dlink a:focus-visible{background:var(--nes-white);color:var(--nes-navy);text-decoration:none}
#dmore{position:absolute;right:20px;bottom:10px;color:var(--fg);animation:blink 1s steps(2) infinite}
@keyframes blink{50%{opacity:0}}
@media (min-width:640px){#dialog{font-size:24px;line-height:36px}#dname{font-size:16px}#dtext{min-height:108px}}
.choice{position:relative;background:none;border:0;padding:2px 8px 2px 16px;color:var(--fg);text-align:left}
.choice:hover,.choice:focus-visible{background:var(--nes-white);color:var(--nes-navy)}
/* Outside the dialog, a choice is a small window of its own, so it reads as a button. */
.panel .choice,.speech .choice{padding:2px 12px 2px 24px;box-shadow:var(--edge);--cx:6px;margin:2px}

.overlay{position:fixed;inset:0;z-index:30;display:flex;align-items:center;justify-content:center;
  /* Every other pixel black, a 1px checkerboard: the world shows through, dimmed, without a single blended color. */
  background:conic-gradient(var(--nes-black) 25%,transparent 0 50%,var(--nes-black) 0 75%,transparent 0) 0 0/2px 2px;
  padding:calc(24px + env(safe-area-inset-top,0px)) 24px calc(24px + env(safe-area-inset-bottom,0px));overflow:auto}
.panel{background:var(--bg);width:min(100%,640px);padding:24px 28px;max-height:100%;overflow:auto;box-shadow:var(--win);margin:4px}
.panel h2{margin:0 0 8px;font-size:24px;line-height:32px;color:var(--fg)}
.panel h3{margin:16px 0 10px;padding-bottom:4px;font-size:16px;color:var(--fg);box-shadow:0 2px 0 0 var(--nes-sky)}
.panel p{margin:8px 0 16px;color:var(--dim)}
.panel{font-size:calc(16px * var(--text-scale,1))}
label{display:block;margin:12px 0 4px;color:var(--dim)}
input[type=text],input[type=email],input[type=tel],input[type=password],input[type=url],textarea,select{width:100%;background:var(--bg);border:0;padding:8px 12px;box-shadow:var(--edge-dim);-webkit-user-select:text;user-select:text}
input:focus,textarea:focus{box-shadow:var(--edge);outline:0}
::placeholder{color:var(--faint);opacity:1}
input[type=range]{accent-color:var(--nes-white);vertical-align:middle;width:min(100%,220px)}
input[type=checkbox],input[type=radio]{accent-color:var(--nes-white)}
.hint{color:var(--dim);margin-top:4px}
.row{display:flex;gap:16px;flex-wrap:wrap;margin-top:20px;padding-left:2px}
/* Buttons. Primary is a white slab with navy type; "alt" is a blue window with white type. */
.big{position:relative;background:var(--nes-white);color:var(--nes-navy);border:0;padding:8px 20px 8px 32px;box-shadow:var(--edge)}
.big.alt{background:var(--bg);color:var(--fg);box-shadow:var(--edge)}
.big:hover,.big:focus-visible{background:var(--nes-ice)}
.big.alt:hover,.big.alt:focus-visible{background:var(--nes-indigo)}
.big:active{transform:translateY(2px)}
.big:disabled,.choice:disabled{background:var(--nes-gray);color:var(--nes-black);box-shadow:var(--edge-dim);cursor:not-allowed}
.big:disabled::before,.choice:disabled::before{visibility:hidden!important}
.big:disabled{cursor:wait}
details{margin-top:12px}
summary{cursor:pointer;color:var(--fg)}
#setupMsg{margin-top:12px;white-space:pre-line;color:var(--dim)}
#setupMsg.err{color:var(--drift)}

/* ---------- the title screen ---------- */
#setup{background:var(--nes-black) var(--sky) 0 0/128px 128px;align-items:center}
#setup .panel{width:min(100%,600px)}
.title{font-size:40px;line-height:48px;margin:0 0 8px;color:var(--nes-white);text-shadow:4px 4px 0 var(--nes-black)}
.title-art{display:flex;align-items:flex-end;justify-content:center;gap:16px;margin:8px 0 20px;height:128px}
.title-art svg{image-rendering:pixelated;flex:none}
.title-art .hero,.title-art .fm{width:96px;height:96px}
.title-art .foe{width:128px;height:128px}
#setup .row{margin-top:24px}
#setup .setting{display:flex;gap:16px;flex-wrap:wrap;align-items:center;margin-top:16px;padding-left:2px}

/* ---------- travel ---------- */
#towns{display:grid;grid-template-columns:repeat(auto-fill,minmax(176px,1fr));gap:20px;margin:16px 0;padding:0 4px}
.town{position:relative;background:var(--bg);border:0;padding:12px 12px 12px 28px;text-align:left;box-shadow:var(--edge-dim);display:flex;flex-direction:column;gap:4px}
.town:hover,.town:focus-visible{box-shadow:var(--edge);background:var(--bg)}
.town.here{box-shadow:var(--edge)}
.town svg{width:40px;height:40px;image-rendering:pixelated}
.town .sub{color:var(--dim)}
.stars{color:var(--gold);letter-spacing:4px}
.stars .off{color:var(--faint)}
#worldMsg{white-space:pre-line;color:var(--dim)}


/* ---------- battle: a classic console RPG ---------- */
#battle{background:var(--page) var(--sky) 0 0/128px 128px;align-items:center}
#battle .panel{width:min(100%,920px);background:none;box-shadow:none;padding:0;margin:0;overflow:visible;
  display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);grid-template-areas:"arena arena" "msg cmd" "prompt cmd";gap:24px 28px;align-items:start}
.arena{grid-area:arena;position:relative;height:clamp(280px,44vh,380px);border-bottom:2px solid var(--nes-blue)}
#foeCv{position:absolute;left:calc(50% - 112px);bottom:8px;width:224px;height:224px;image-rendering:pixelated;animation:bob 1.2s steps(2) infinite}
#foeCv.hit{animation:shake .3s steps(3)}
@keyframes bob{50%{transform:translateY(-8px)}}
@keyframes shake{33%{transform:translateX(-12px)}66%{transform:translateX(12px)}}
.plate{position:absolute;background:var(--bg);padding:8px 16px 10px;box-shadow:var(--edge);min-width:210px;margin:2px}
.plate .bar,.plate .cups{margin-top:6px;display:block}
.plate small{display:block;color:var(--dim);font-size:16px}
#foePlate{right:6px;top:6px}
#heroPlate{left:6px;top:6px}
#heroPlate .lv{color:var(--gold)}
#foePlate #foeSub{color:var(--drift)}
#foeName{color:var(--fg)}
#intentTag{position:absolute;left:6px;bottom:12px;background:var(--nes-green);color:var(--nes-black);padding:0 12px;box-shadow:var(--edge-ok)}
#pendingTag{position:absolute;right:6px;bottom:12px;background:var(--nes-ice);color:var(--nes-black);padding:0 12px;max-width:60%}
#btext{grid-area:msg;min-height:132px;white-space:pre-line;background:var(--bg);padding:14px 20px;box-shadow:var(--edge);margin:2px;color:var(--fg)}
#moves{grid-area:cmd;display:flex;flex-direction:column;gap:0;background:var(--bg);padding:10px 12px 10px 28px;box-shadow:var(--edge);margin:2px}
#moves button{position:relative;background:none;border:0;padding:2px 8px 2px 4px;color:var(--fg);text-align:left;display:flex;justify-content:space-between;gap:12px;align-items:center}
#moves button:hover:not(:disabled),#moves button:focus-visible{background:var(--nes-white);color:var(--nes-navy)}
#moves button:disabled{color:var(--faint);cursor:not-allowed}
#moves button.fm span:first-child::before{content:"";display:inline-block;width:14px;height:10px;margin-right:8px;background:var(--ic-robot) center/14px 10px no-repeat;image-rendering:pixelated}
.tier{padding:0 6px;color:var(--nes-black);white-space:nowrap;flex:none;background:var(--nes-light)}
/* Tiers say their name in words; the fill only helps. Red is DENY's alone. */
.t-AUTO{background:var(--nes-green-light)} .t-NOTIFY{background:var(--nes-sky)} .t-APPROVE{background:var(--nes-white)} .t-TWO_PERSON{background:var(--nes-lavender);box-shadow:0 0 0 2px var(--nes-white);margin:0 2px}
.t-DENY{background:var(--nes-red);color:var(--nes-white)} .t-ASK{background:var(--nes-light);color:var(--nes-black)}
@media (max-width:760px){
  #battle{align-items:flex-start}
  #battle .panel{grid-template-columns:minmax(0,1fr);grid-template-areas:"arena" "msg" "prompt" "cmd";gap:20px}
  /* The battle stacks: foe, monster, you. Nothing overlaps at any width. */
  .arena{height:auto;display:flex;flex-direction:column;align-items:stretch;gap:12px;padding-bottom:12px}
  .arena .plate,.arena #foeCv,.arena #intentTag,.arena #pendingTag{position:static;margin:0}
  .arena #foePlate{order:1} .arena #foeCv{order:2;align-self:center} .arena #heroPlate{order:3}
  .arena #intentTag{order:4;align-self:flex-start} .arena #pendingTag{order:5;max-width:none}
  #foeCv{width:192px;height:192px}
  .plate{min-width:0;padding:6px 12px 8px}
  #btext{min-height:96px}
}
@media (prefers-reduced-motion:reduce){#foeCv{animation:none}#dmore{animation:none}}

/* ---------- touch controls: a plus-shaped pad and an A button ---------- */
#pad{display:none;justify-content:space-between;align-items:center;padding:8px 24px 14px}
@media (pointer:coarse){#pad{display:flex}}
.dpad{display:grid;grid-template-columns:repeat(3,52px);grid-template-rows:repeat(3,52px)}
.dpad button,.abtn{background:var(--bg);border:0;box-shadow:var(--edge);font-size:24px;line-height:24px;padding:0}
.dpad button:active,.abtn:active{background:var(--nes-white);color:var(--nes-navy)}
.abtn{width:68px;height:68px;margin:4px}
#menuFields{white-space:pre-wrap;background:var(--bg);padding:10px 12px;max-height:220px;overflow:auto;color:var(--dim);box-shadow:var(--edge-dim);margin:2px}

/* ---------- badges, the journal, the gate desk ---------- */
#badgePop{position:fixed;top:calc(20px + env(safe-area-inset-top,0px));left:50%;z-index:40;display:flex;align-items:center;gap:16px;
  background:var(--bg);padding:10px 20px 10px 16px;box-shadow:var(--edge-gold);
  transform:translate(-50%,-260%);visibility:hidden;transition:transform .35s steps(5);pointer-events:none;max-width:92vw}
#badgePop.show{transform:translate(-50%,0);visibility:visible}
#badgePop svg{width:40px;height:50px;flex:none;image-rendering:pixelated}
#badgePop small{display:block;color:var(--gold)}
@media (prefers-reduced-motion:reduce){#badgePop{transition:none}}
.tabs{display:flex;gap:4px 20px;margin:8px 0 16px;flex-wrap:wrap;padding-left:16px}
/* Six tabs now: a wider journal window keeps them on one row (they still wrap on a phone). */
#journal .panel{width:min(100%,760px)}
.tabs button{position:relative;background:none;border:0;padding:2px 8px 2px 4px;color:var(--dim)}
.tabs button:hover,.tabs button:focus-visible{background:var(--nes-white);color:var(--nes-navy)}
.tabs button[aria-selected=true]{color:var(--fg);box-shadow:0 2px 0 0 var(--nes-white)}
.tabs button[aria-selected=true]:hover,.tabs button[aria-selected=true]:focus-visible{color:var(--nes-navy)}
.rankcard{display:flex;gap:20px;align-items:center;background:var(--bg);padding:12px 16px;margin:8px 2px 16px;box-shadow:var(--edge-dim)}
.rankcard .lv{font-size:40px;line-height:40px;color:var(--gold);text-shadow:4px 4px 0 var(--nes-black)}
.rankcard .bar{--segs:20;--seg:6px;--gap:2px;margin:6px 0 4px}
.rankcard .grow{flex:1;min-width:0}
.rankcard small{color:var(--dim)}
.stats{display:grid;grid-template-columns:repeat(auto-fill,minmax(136px,1fr));gap:12px;margin:0 2px 8px}
.stats div{background:var(--bg);padding:8px 12px;box-shadow:var(--edge-dim)}
.stats b{display:block;font-size:24px;line-height:32px;color:var(--fg)}
.stats span{color:var(--dim)}
#badgeGrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(184px,1fr));gap:14px;margin:0 2px}
.badge{background:var(--bg);padding:10px 12px;display:flex;gap:12px;align-items:flex-start;box-shadow:var(--edge-dim)}
.badge svg{width:32px;height:40px;flex:none;image-rendering:pixelated}
.badge b{display:block;color:var(--fg)}
.badge span{display:block;color:var(--dim);line-height:20px}
.badge.locked b{color:var(--faint)}
.badge .bar{--segs:10;--seg:6px;--gap:2px;--fill:var(--nes-light);margin-top:8px}
.qlist{list-style:none;margin:0 2px;padding:0;display:flex;flex-direction:column;gap:12px}
.qlist li{background:var(--bg);padding:10px 14px;display:flex;gap:12px;box-shadow:var(--edge-dim)}
.qlist li .m{flex:none;width:16px;color:var(--faint)}
.qlist li.done .m{color:var(--ok)}
.qlist li.now{box-shadow:var(--edge)}
.qlist li.now .m{color:var(--fg)}
.qlist li.lock{color:var(--faint)}
.qlist li.lock small{color:var(--faint)}
.qlist small{display:block;color:var(--dim)}
.gatepanel{width:min(100%,680px)!important}
.gatehead{display:flex;justify-content:space-between;align-items:baseline;gap:12px;flex-wrap:wrap}
#gStatus{color:var(--dim);white-space:pre}
.ticket{position:relative;background:var(--bg);color:var(--fg);padding:14px 18px;margin:16px 2px;box-shadow:var(--edge)}
.ticket h3{margin:0 0 10px;font-size:16px;color:var(--fg);padding-right:150px}
.ticket dl{display:grid;grid-template-columns:auto 1fr;gap:4px 16px;margin:0}
.ticket dt{color:var(--dim)}
.ticket dd{margin:0}
.ticket .why{margin:10px 0 0;color:var(--dim)}
.who-tag{padding:0 6px;margin-left:8px;background:var(--nes-indigo);color:var(--nes-white)}
.who-tag.agent{background:var(--nes-aqua);color:var(--nes-black)}
/* The decision stamp: a plain block, no tilt. */
.stamp{position:absolute;right:14px;top:12px;padding:0 12px;background:var(--bg);box-shadow:var(--edge)}
.stamp.approve{color:var(--ok);box-shadow:var(--edge-ok)} .stamp.deny{color:var(--drift);box-shadow:var(--edge-drift)} .stamp.flag{color:var(--fg)} .stamp.expired{color:var(--dim);box-shadow:var(--edge-dim)}
.gtimer{height:8px;background:var(--nes-black);box-shadow:0 0 0 2px var(--nes-black);margin:16px 2px}
.gtimer i{display:block;height:100%;background:var(--nes-sky);width:100%}
.gbtns{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin:0 2px}
.gbtns button{position:relative;border:0;padding:8px 6px 8px 22px;color:var(--fg);background:var(--bg);box-shadow:var(--edge)}
.gbtns button:active{transform:translateY(2px)}
.g-approve{box-shadow:var(--edge-ok)!important} .g-approve:hover,.g-approve:focus-visible{background:var(--nes-green-light)!important;color:var(--nes-black)!important}
.g-deny{box-shadow:var(--edge-drift)!important} .g-deny:hover,.g-deny:focus-visible{background:var(--nes-red)!important;color:var(--nes-white)!important}
.g-flag:hover,.g-flag:focus-visible{background:var(--nes-white)!important;color:var(--nes-navy)!important}
.gbtns small{display:block;color:var(--dim);line-height:16px}
.gbtns button:hover small,.gbtns button:focus-visible small{color:inherit}
.verdict{font-size:24px;line-height:32px;margin:8px 2px 4px} .verdict.ok{color:var(--ok)} .verdict.bad{color:var(--drift)} .verdict.meh{color:var(--dim)}
.rulebox{background:var(--bg);padding:10px 14px;margin:12px 2px 4px;box-shadow:var(--edge-dim)}
.grade{font-size:64px;line-height:64px;color:var(--gold);text-shadow:4px 4px 0 var(--nes-black);margin:8px 0}
.brief{margin:8px 0;padding-left:24px}
.brief li{margin:8px 0}
.audit{background:var(--bg);padding:10px 12px;white-space:pre-wrap;max-height:50vh;overflow:auto;color:var(--dim);box-shadow:var(--edge-dim);margin:2px;font-family:var(--font-mono);-webkit-user-select:text;user-select:text}
.audit b{color:var(--fg)}
.booking-link{color:var(--nes-white);text-decoration:underline;display:inline-block;padding:12px}
.ok-text{color:var(--ok)} .gold-text{color:var(--gold)}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
.panel h3.first{margin-top:0}
.audit-row{margin-bottom:8px}
.fg-text{color:var(--fg)!important}
.hint.keys{margin-top:12px}

/* ---------- small screens and touch ---------- */
@media (max-width:560px){
  /* A tidy grid: the location on top, then Travel, Journal and Menu in one row, the vending label on its own row, then the meters. */
  #hud{display:grid;grid-template-columns:repeat(3,auto);justify-content:start;column-gap:12px;row-gap:0;padding:6px 10px 6px 14px}
  #hud::after{display:none}
  #loc{grid-column:1/-1;font-size:16px;line-height:24px;max-width:none}
  #hud .hudbtn{flex:none;text-align:left;padding:2px 4px 2px 20px;--cx:2px;white-space:nowrap}
  #vendingBtn{grid-column:1/-1;justify-self:start}
  #hud .stat:not(#lvlStat):not(#coffeeStat){grid-column:1/3}
  #coffeeStat{grid-column:1/-1}
  .stat{gap:6px}
  #hud .bar{--seg:5px;--gap:1px}
  #hud .cups{--cw:9px;--ch:7px}
  #tokenbar,#questbar{padding-left:14px}
  #stage{padding:10px 8px}
  #toast{top:8px;padding:2px 10px}
  .panel{padding:18px 16px}
  .overlay{padding:16px 12px}
}
@media (pointer:coarse){
  .choice,#moves button,.tabs button,.hudbtn,.gbtns button,.big,.town{min-height:44px}
  .choice,#moves button,.tabs button,.hudbtn{display:inline-flex;align-items:center}
  #moves button{display:flex}
  #dchoices{gap:0 20px}
}

/* Foreman exists on the phone, including story messages. */
#dialog.fm-phone { max-width:360px; width:calc(100% - 24px); left:50%; right:auto; transform:translateX(-50%); border:8px solid var(--nes-black); border-radius:0; padding:24px 16px; bottom:16px; }

.analytics-banner{position:relative;margin-top:16px;background:var(--bg);color:var(--fg);padding:8px 16px;display:flex;flex-wrap:wrap;align-items:center;gap:8px;border-top:2px solid var(--dim);font-size:12px}

#release-lab,#finale{z-index:110}
#analytics-choice{z-index:130}
#phone{z-index:120}
/* Original NES decorations. No flashes, jump scares or extra motion. */
:root[data-season=halloween]{--bg:var(--nes-black);--dim:var(--nes-lavender);--rule:var(--nes-lavender);--edge:0 -2px 0 0 var(--nes-lavender),0 2px 0 0 var(--nes-lavender),-2px 0 0 0 var(--nes-lavender),2px 0 0 0 var(--nes-lavender);--edge-dim:var(--edge)}
.season-banner{display:none}
[data-season=halloween] .season-banner{display:flex;align-items:center;justify-content:center;gap:16px;margin:0 auto 20px;padding:12px;border-top:2px solid var(--nes-peach);border-bottom:2px solid var(--nes-peach);max-width:720px;background:var(--nes-black);text-align:left}
.season-banner p{margin:0;color:var(--nes-lavender);font-size:14px;line-height:24px}
.season-banner .season-title{color:var(--nes-peach);font-size:24px;line-height:32px;letter-spacing:2px}
.season-icon{width:56px;height:56px;flex:none;image-rendering:pixelated}
.season-icon svg{width:100%;height:100%}
.season-picker{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px 16px;font-family:var(--font);font-size:14px;color:var(--dim);margin:20px 0 0}
.season-picker select{width:auto;min-height:44px;max-width:100%;padding:6px 10px;background:var(--bg);color:var(--fg);border:2px solid var(--nes-lavender);border-radius:0;box-shadow:none}
[data-season=halloween] #setup .title{color:var(--nes-white)}
[data-season=halloween] #setup .cinematic-title-art .intro-office,[data-season=halloween] #setup .cinematic-title-art canvas{max-height:220px}
[data-season=halloween] #setup .row{margin-top:8px;margin-bottom:20px}
[data-season=halloween] .intro-office{border-color:var(--nes-indigo)}
[data-season=halloween] .intro-cinematic{border-top-color:var(--nes-indigo)}
[data-season=halloween] .intro-title{color:var(--nes-peach)}
[data-season=halloween] .intro-character.speaking{background:var(--nes-indigo);border-color:var(--nes-peach)}
[data-season=halloween] #onboarding .intro-dialogue h2{background:var(--nes-peach)}
[data-season=halloween] .intro-dialogue{border-bottom-color:var(--nes-lavender)}
[data-season=halloween] .intro-scene-caption{background:var(--nes-lavender)}
[data-season=halloween] #hud{box-shadow:0 2px 0 0 var(--nes-peach)}
[data-season=halloween] #questbar{box-shadow:0 2px 0 0 var(--nes-lavender)}
[data-season=halloween] .foreman-portrait{position:relative;background:var(--nes-black);border-color:var(--nes-lavender)}
[data-season=halloween] .foreman-portrait::after{content:"";position:absolute;width:32px;height:16px;top:-7px;left:50%;transform:translateX(-50%);background:var(--season-hat) center/100% 100% no-repeat;image-rendering:pixelated;pointer-events:none}
[data-season=halloween] .vm-sign{position:relative}
[data-season=halloween] .vm-sign::after{content:"";position:absolute;width:32px;height:32px;right:4px;top:-28px;background:var(--season-pumpkin) center/100% 100% no-repeat;image-rendering:pixelated;pointer-events:none}
.season-vending-note{display:none}
[data-season=halloween] .season-vending-note{display:block;color:var(--nes-lavender);font-size:14px;line-height:24px;text-align:center}
@media(max-width:600px){.season-banner .season-title{font-size:18px;line-height:26px;letter-spacing:1px}.season-banner p{font-size:12px;line-height:20px}[data-season=halloween] .season-banner{gap:8px;padding:8px;margin-bottom:12px}.season-icon{width:40px;height:40px}.season-picker{font-size:12px;margin-top:12px}}
/* Foreman stays inside this small phone; the phone never tracks the player's map position. */
.foreman-dock{position:absolute;top:12px;right:12px;z-index:4;width:88px;min-height:100px;padding:10px 5px 6px;display:flex;flex-direction:column;align-items:center;gap:2px;background:var(--nes-black);color:var(--nes-white);border:4px solid var(--nes-light);box-shadow:0 0 0 2px var(--nes-black);line-height:16px;font-size:12px}
.foreman-speaker{width:18px;height:2px;background:var(--nes-gray);margin-bottom:4px}
.foreman-portrait{display:inline-flex;width:40px;height:40px;flex:none;align-items:center;justify-content:center;background:var(--nes-navy);border:2px solid var(--nes-sky);image-rendering:pixelated}
.foreman-portrait svg{width:32px;height:32px;image-rendering:pixelated}
.foreman-dock small{color:var(--nes-mint);font-size:12px;line-height:16px}
.foreman-dock[data-state=working] .foreman-portrait svg{animation:foreman-work 1s steps(2,end) infinite}
.foreman-dock[data-state=waiting] .foreman-portrait{border-color:var(--nes-gold)}
.foreman-dock[data-state=waiting] small{color:var(--nes-gold)}
.foreman-console .foreman-portrait{width:80px;height:80px}
.foreman-console .foreman-portrait svg{width:64px;height:64px}
.foreman-console .big{margin:8px 10px 4px 0}
.foreman-status-line{color:var(--nes-mint)}
.finale-receipt{padding:12px;box-shadow:var(--edge-dim);margin:12px 2px}
#demoRequestCode{font:inherit;user-select:all;overflow-wrap:anywhere;color:var(--gold)}
@keyframes foreman-work{50%{transform:translateY(-2px)}}
@media(max-width:760px){.foreman-dock{width:76px;min-height:90px;top:8px;right:8px;padding:6px 3px 4px}}
@media(prefers-reduced-motion:reduce){.foreman-dock[data-state=working] .foreman-portrait svg{animation:none}}

#foreman-status .foreman-console{width:min(100%,440px);border:10px solid var(--nes-light);background:var(--nes-black);box-shadow:0 0 0 4px var(--nes-black);}
/* Foreman's phone. A light-gray phone with a black screen, drawn as pixel art: the body, the screen and the bubbles are small
   pictures set by theme.ts (--ph-*) and cut into nine pieces with border-image, so the phone stretches to any width without a
   blurry pixel. --px is how many screen pixels one art pixel is (whole numbers only). Slack and Teams are words in a tag: no logos,
   no brand colors. Red is the Deny button's alone, the same as the gate desk's. */
#phone{position:fixed;inset:0;z-index:120;display:flex;align-items:flex-end;justify-content:center;pointer-events:none;
  padding:calc(12px + env(safe-area-inset-top,0px)) 12px calc(12px + env(safe-area-inset-bottom,0px))}
#phone .phone{pointer-events:auto}

.phone{--px:2px;--bpx:2px;position:relative;display:flex;flex-direction:column;min-height:0;width:100%;max-width:420px;max-height:100%;
  border:solid transparent;border-width:calc(8 * var(--px));border-image:var(--ph-body) 8 fill / calc(8 * var(--px)) stretch;
  image-rendering:pixelated;font-family:var(--font);font-size:calc(16px * var(--text-scale,1));line-height:24px;color:var(--nes-white);
  box-shadow:0 0 0 4px var(--nes-black)}
.phone-speaker,.phone-home{position:absolute;left:50%;image-rendering:pixelated;background-repeat:no-repeat;background-size:100% 100%}
.phone-speaker{top:calc(-5 * var(--px));width:24px;height:8px;margin-left:-12px;background-image:var(--ph-speaker)}
.phone-home{bottom:calc(-6 * var(--px));width:16px;height:16px;margin-left:-8px;background-image:var(--ph-home)}
.phone-screen{display:flex;flex-direction:column;flex:1;min-height:0;padding:2px 2px 6px;
  border:solid transparent;border-width:calc(3 * var(--px));border-image:var(--ph-screen) 3 fill / calc(3 * var(--px)) stretch}
/* One header row: the avatar, who is writing, and the channel as a word in a tag (the same plain tag for Slack and Teams). */
.phone-head{display:flex;align-items:center;gap:8px;padding:2px 6px 6px;box-shadow:0 2px 0 0 var(--nes-dark)}
.phone-chan{flex:none;margin-left:auto;padding:0 8px;background:var(--nes-light);color:var(--nes-black)}
.phone-avatar{flex:none;width:32px;height:32px;background:var(--nes-black);box-shadow:0 0 0 2px var(--nes-sky)}
.phone-avatar svg{display:block;width:100%;height:100%;image-rendering:pixelated}
.phone-who{display:flex;flex-direction:column;line-height:18px}
.phone-who b{color:var(--nes-white)}
.phone-who small{color:var(--dim);font-size:16px}

.phone-thread{flex:1;min-height:0;overflow:auto;padding:6px 4px 4px;display:flex;flex-direction:column;gap:6px}
.bub{--bpx:2px;--fill:var(--ph-bubble-fm);position:relative;max-width:100%;color:var(--nes-black);
  border:solid transparent;border-width:calc(4 * var(--bpx));border-image:var(--fill) 4 fill / calc(4 * var(--bpx)) stretch;image-rendering:pixelated}
.bub-you{--fill:var(--ph-bubble-you);align-self:flex-end;max-width:88%}
.bub-co{--fill:var(--ph-bubble-co)}
.bub p,.panel .bub p{margin:0 0 6px;color:var(--nes-black);line-height:20px}
.bub p:last-child,.panel .bub p:last-child{margin-bottom:0}
.bub-from{display:block;color:var(--nes-black);margin-bottom:2px}
/* The impact is the line you are agreeing to, so it gets a bar down its side. */
.bub .part-impact{padding-left:8px;box-shadow:inset 4px 0 0 0 var(--nes-navy)}

.phone-actions{display:flex;gap:12px;padding:6px 4px 0}
.phone-btn{position:relative;flex:1;min-height:48px;padding:8px 10px;border:0;background:var(--bg);color:var(--fg);box-shadow:var(--edge);font-family:var(--font);font-size:inherit;text-align:center}
.phone-btn:hover,.phone-btn:focus-visible{background:var(--nes-white);color:var(--nes-navy)}
.phone-btn:active{transform:translateY(2px)}
.phone-approve{box-shadow:var(--edge-ok)}
.phone-approve:hover,.phone-approve:focus-visible{background:var(--nes-green-light);color:var(--nes-black)}
/* Deny is the one red on the phone: danger and DENY are what red says. */
.phone-deny{box-shadow:var(--edge-drift)}
.phone-deny:hover,.phone-deny:focus-visible{background:var(--nes-red);color:var(--nes-white)}
.phone-ok{box-shadow:var(--edge-ok)}
.phone-ok:hover,.phone-ok:focus-visible{background:var(--nes-green-light);color:var(--nes-black)}
.phone-hint{margin:2px 6px 0;color:var(--dim);font-size:16px;line-height:20px;text-align:center}

/* The notice when a coworker answers: a small strip near the top with a phone beside it. */
/* It sits under the badge pop (which is at the very top), so a badge that fires with the reply never covers it. */
#phoneNote{position:fixed;z-index:36;top:calc(92px + env(safe-area-inset-top,0px));left:50%;transform:translateX(-50%);width:min(92vw,400px);
  pointer-events:none;background:var(--bg);color:var(--fg);padding:8px 14px 8px 52px;box-shadow:var(--edge)}
#phoneNote::before{content:"";position:absolute;left:14px;top:10px;width:27px;height:36px;background:var(--ic-phone) center/100% 100% no-repeat;image-rendering:pixelated}
#phoneNote b{display:block;color:var(--dim)}
#phoneNote span{display:block}
#phoneNote small{display:block;color:var(--dim);font-size:16px}

/* Sliding up, a short buzz, and sliding away. Reduced motion stops every animation (styles.css), so the phone just appears. */
.phone.enter{animation:phone-up .32s steps(8) both,phone-buzz .3s steps(4) .32s}
.phone.leave{animation:phone-down .25s steps(5) both}
@keyframes phone-up{from{transform:translateY(calc(100% + 40px))}to{transform:none}}
@keyframes phone-down{from{transform:none}to{transform:translateY(calc(100% + 40px))}}
@keyframes phone-buzz{25%{transform:translateX(-4px)}50%{transform:translateX(4px)}75%{transform:translateX(-2px)}}

/* A desktop phone is a phone-sized card low at the right of the screen, over the battle; a small screen gets it nearly full width as a sheet.
   Either way it never takes more than about two thirds of the height: a long message scrolls inside, and the buttons stay in view. */
@media (min-width:761px){
  #phone{justify-content:flex-end;padding-right:max(24px,calc(50vw - 480px))}
  .phone{--px:2px;width:340px;max-height:68%}
}
@media (max-width:760px){
  #phoneNote{top:calc(124px + env(safe-area-inset-top,0px))} /* the badge pop wraps to more lines on a narrow screen */
  #phone{padding-left:8px;padding-right:8px}
  .phone{max-width:none;max-height:68%}
}

/* The Journal's Messages tab: each exchange with Foreman is a card of the same bubbles. */
.msg-ic{display:inline-block;width:18px;height:24px;margin-right:10px;vertical-align:-6px;background:var(--ic-phone) center/100% 100% no-repeat;image-rendering:pixelated}
.msg-list{display:flex;flex-direction:column;gap:16px;margin:0 2px}
.msg-group{background:var(--bg);padding:12px 14px;box-shadow:var(--edge-dim);display:flex;flex-direction:column;gap:8px;font-size:calc(16px * var(--text-scale,1))}
.msg-group header{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 10px}
.msg-group header b{color:var(--fg)}
.msg-tag{padding:0 8px;background:var(--nes-light);color:var(--nes-black)}
.msg-tier{color:var(--dim)}
.panel .msg-meta{margin:0 0 4px;color:var(--dim)}
.msg-group .bub{align-self:flex-start;max-width:100%}
.msg-group .bub-you{align-self:flex-end}
#story-board{z-index:110}
.story-board{max-width:900px;width:100%;line-height:1.7}
.story-case{border-top:2px solid var(--nes-sky);margin:24px 0;padding:12px 0}
.story-case small{display:block;color:var(--nes-ice);margin-bottom:12px}
.story-case button{display:block;margin:8px 0}
.story-evidence{border:2px solid var(--nes-ice);padding:16px;margin:20px 0}
.story-phone{max-width:420px;margin:20px auto;border:8px solid var(--nes-light);box-shadow:0 0 0 4px var(--nes-black);background:var(--nes-black)}
.story-feedback{border-left:4px solid var(--nes-gold);padding:12px 16px;background:var(--nes-black)}
.story-decisions{display:flex;flex-direction:column;gap:16px;margin:16px 0}
.story-decisions button{text-align:left;white-space:normal;line-height:1.7;padding:12px}
.story-progress{padding:16px;border:2px solid var(--nes-ice);margin:16px 0;background:var(--nes-black)}
.story-progress h3{color:var(--nes-mint)}
.story-log{margin:16px 0;color:var(--dim)}
.story-log li{margin-bottom:12px}
.sarah-call{max-width:500px;border:8px solid var(--nes-light);background:var(--nes-black);line-height:1.7}
#sarah-call{z-index:125}
.sarah-call .intro-character{width:88px;height:88px;margin:12px auto}
.sarah-call .big{display:block;margin:12px 0;white-space:normal}

/* Routine encounters use a small conversation and a few choices; evidence remains available on demand. */
.story-kind{letter-spacing:2px;color:var(--nes-ice)}
.quick-encounter{max-width:680px;line-height:1.5}
.quick-character{display:flex;gap:20px;align-items:center;margin:20px 0;padding:16px 0;border-top:2px solid var(--nes-sky);border-bottom:2px solid var(--nes-sky)}
.quick-portrait{width:80px;height:80px;flex:none;image-rendering:pixelated}
.quick-portrait svg{width:100%;height:100%;image-rendering:pixelated}
.quick-encounter .quick-name{color:var(--nes-ice);margin:0 0 8px;font-size:12px}
.quick-encounter .quick-line{color:var(--nes-white);margin:0;font-size:18px;line-height:28px}
.quick-encounter .quick-clue{color:var(--nes-ice);font-size:16px;line-height:26px;padding:0 4px}
.quick-encounter .quick-gate{font-size:12px;line-height:20px;color:var(--nes-mint)}
.quick-encounter .story-decisions{gap:8px}
.quick-encounter .story-decisions button{min-height:48px;padding:10px 14px 10px 28px}
.quick-encounter .story-decisions .hint{font-size:12px;line-height:18px;margin:0 0 8px 4px}
.quick-encounter .story-evidence{font-size:12px;line-height:22px;padding:12px;margin:18px 0}
.quick-encounter .quick-simulation{font-size:10px;line-height:18px}
.quick-encounter .quick-victory{font-size:24px;color:var(--nes-mint);letter-spacing:3px;text-align:center;margin:20px 0}
.quick-encounter .quick-consequence{font-size:14px;color:var(--nes-peach);padding:8px 0}
.quick-beat{text-align:center;padding:20px 0}.quick-beat p{font-size:14px}
.quick-progress{height:8px;width:144px;max-width:100%;margin:0 auto 20px;border:2px solid var(--nes-sky);position:relative}
.quick-progress::after{content:'';display:block;width:24px;height:4px;background:var(--nes-ice);animation:quick-step 900ms steps(5,end) infinite}
@keyframes quick-step{from{transform:translateX(0)}to{transform:translateX(116px)}}
@media(max-width:600px){.quick-character{gap:12px;padding:12px 0;margin:14px 0}.quick-portrait{width:48px;height:48px}.quick-encounter .quick-line{font-size:16px;line-height:24px}.quick-encounter .quick-clue{font-size:14px;line-height:24px}}
@media(prefers-reduced-motion:reduce){.quick-progress::after{animation:none;width:100%}}

@media(max-width:600px){.quick-encounter h2{font-size:16px;line-height:24px}.quick-encounter .quick-character{margin:10px 0;padding:10px 0}.quick-encounter .quick-clue{font-size:16px;line-height:24px;margin:10px 0}.quick-encounter .story-decisions button{font-size:16px;line-height:24px;padding:8px 10px 8px 24px}.quick-encounter .story-decisions .hint{margin-bottom:0}.quick-encounter .quick-victory{font-size:24px}}

.quick-encounter .quick-reward{color:var(--nes-gold);font-size:16px;line-height:24px;margin:12px 0}

.story-desk-nav{display:flex;align-items:center;justify-content:space-between;gap:16px;position:sticky;top:-24px;z-index:2;background:var(--nes-black);padding:12px 0;border-bottom:2px solid var(--nes-sky)}
.story-desk-nav h2{font-size:20px;line-height:28px}.story-desk-nav button{min-height:48px;white-space:normal}
.story-switcher,.story-desk-details{font-size:12px;line-height:22px;margin:16px 0}.story-switcher select{display:block;max-width:100%;width:100%;min-height:48px;margin:12px 0;background:var(--nes-black);color:var(--nes-white);border:2px solid var(--nes-ice);font-size:14px}
.story-board .story-case{border:0;margin:16px 0}.story-board .story-case p{font-size:16px;line-height:26px}.story-board .story-case button{white-space:normal;min-height:48px;line-height:24px}
@media(max-width:600px){.story-desk-nav{top:-16px;gap:8px}.story-desk-nav h2{font-size:16px;line-height:24px}.story-desk-nav button{font-size:12px;padding:10px 12px}.story-switcher select{font-size:12px}}
.quick-earned{display:flex;flex-wrap:wrap;gap:8px 20px}.quick-earned .quick-reward{font-size:14px;margin:8px 0}
/* The title is a game screen. No external art, blurred scaling, flashing, or automatic sound. */
#setup.nes-title{font-family:var(--font);background:var(--nes-black);padding:calc(20px + env(safe-area-inset-top,0px)) 12px calc(16px + env(safe-area-inset-bottom,0px));align-items:center}
#setup.nes-title .title-shell{width:min(100%,960px);max-height:100%;padding:8px 20px;display:flex;flex-direction:column;align-items:center;background:var(--nes-black);box-shadow:none;margin:0;overflow:auto;text-align:center;scrollbar-width:thin;--title-menu-width:360px;--title-entry-height:56px}
#setup.nes-title .title-presents{font-size:12px;line-height:20px;letter-spacing:3px;color:var(--nes-ice);margin:0 0 14px}
#setup.nes-title h1.title{font-size:64px;line-height:1.12;letter-spacing:4px;margin:0;color:var(--nes-white);text-shadow:4px 4px 0 var(--nes-blue),8px 8px 0 var(--nes-navy)}
#setup.nes-title .title span{display:block}
#setup.nes-title .title-tagline{color:var(--nes-ice);font-size:12px;line-height:20px;letter-spacing:2px;margin:16px 0 0}
#setup.nes-title #titleArt{width:864px;max-width:100%;height:auto;margin:8px 0 0;display:block}
.title-diorama{position:relative;width:100%;aspect-ratio:3/1;overflow:hidden;image-rendering:pixelated}
.title-diorama canvas{width:100%;height:100%;display:block;image-rendering:pixelated}
.title-sky{position:absolute;inset:0}
.title-parallax{position:absolute;left:0;top:0;width:200%;height:100%;animation:title-scroll 14s steps(288,end) infinite;will-change:transform}
.title-distant{animation-duration:32s}
.title-pavement{animation-duration:8s}
@keyframes title-scroll{to{transform:translateX(-50%)}}
#setup.nes-title .intro-location{font-size:10px;line-height:16px;top:0;left:0;padding:2px 4px;max-width:none;color:var(--nes-ice)}
.title-scene-caption{position:absolute;bottom:0;right:0;font-size:10px;line-height:16px;padding:2px 4px;background:var(--nes-black);color:var(--nes-ice)}
.title-packet{position:absolute;left:34%;top:22%;width:2px;height:2px;background:var(--nes-ice)}
#setup.nes-title .title-start{position:relative;display:block;width:min(100%,var(--title-menu-width));text-align:center;margin:10px 0 6px;padding:10px 24px;min-height:var(--title-entry-height);background:var(--nes-black);border:0;box-shadow:none;color:var(--nes-white);font-size:24px;line-height:28px;letter-spacing:3px}
#setup.nes-title .title-start::before{content:'▶';position:absolute;left:14px;top:50%;transform:translateY(-50%);color:var(--nes-ice);display:block;margin:0;font-size:12px;line-height:12px}
#setup.nes-title .title-game-menu{display:flex;flex-direction:column;align-items:stretch;gap:0;width:min(100%,var(--title-menu-width));margin:0;padding:0}
#setup.nes-title .title-game-menu .big{background:var(--nes-black);color:var(--nes-white);box-shadow:none;min-height:var(--title-entry-height);margin:0;padding:12px 28px;text-align:center;line-height:24px;font-size:16px}
#setup.nes-title .title-game-menu .big:hover,#setup.nes-title .title-game-menu .big:focus-visible{background:var(--nes-navy)}
#setup.nes-title button:focus-visible,#setup.nes-title summary:focus-visible,#setup.nes-title select:focus-visible{outline:2px solid var(--nes-ice);outline-offset:3px}
#setup.nes-title .title-start:hover,#setup.nes-title .title-start:focus-visible{background:var(--nes-navy)}
#setup.nes-title button:disabled{color:var(--nes-light);cursor:wait}
#setup.nes-title #setupSession{font-size:11px;line-height:18px;color:var(--nes-ice);max-width:540px;margin:8px 0;overflow-wrap:anywhere}
#setup.nes-title .title-utility{display:flex;justify-content:center;align-items:flex-start;flex-wrap:wrap;gap:4px 16px;margin:0;width:100%}
#setup.nes-title .title-utility>button,#setup.nes-title summary{min-height:44px;line-height:20px;font-size:12px;padding:12px 8px;background:var(--nes-black);color:var(--nes-ice);border:0;box-shadow:none;text-align:center}
#setup.nes-title .title-utility>button::before{display:none}
#setup.nes-title #titleOptions{margin:0;max-width:100%}
#setup.nes-title #titleOptions summary{list-style:none;cursor:pointer;letter-spacing:1px}
#setup.nes-title #titleOptions summary::-webkit-details-marker{display:none}
#setup.nes-title #titleOptions[open]{flex-basis:100%;width:min(100%,640px)}
#setup.nes-title .title-options-body{padding:12px 16px;text-align:left;border:2px solid var(--nes-sky);background:var(--nes-black)}
#setup.nes-title .title-options-body .setting{margin:8px 0;display:flex;align-items:center;flex-wrap:wrap;gap:8px 16px}
#setup.nes-title .title-options-body p,#setup.nes-title .title-options-body .hint{font-size:12px;line-height:20px;color:var(--nes-ice)}
#setup.nes-title .title-options-body .season-picker{justify-content:flex-start;font-size:12px;margin:12px 0}
#setup.nes-title .title-footer{font-size:10px;line-height:18px;letter-spacing:1px;color:var(--nes-light);margin:4px 0 0}
#setup.nes-title #setupMsg{margin:0;font-size:12px;line-height:20px;max-width:540px}
#setup.nes-title .season-banner{display:none}
[data-season=halloween] #setup.nes-title .season-banner{display:flex;gap:6px;align-items:center;margin:6px 0 0;padding:0;border:0;max-width:100%}
#setup.nes-title .season-banner .season-icon{width:16px;height:16px}
#setup.nes-title .season-banner .season-title{font-size:10px;line-height:18px;letter-spacing:2px;color:var(--nes-peach)}
#setup.nes-title .season-banner p:not(.season-title){display:none}
#setup.nes-title .analytics-banner{width:min(100%,650px);margin:8px 0 0;padding:8px 0 0;border-top:1px solid var(--nes-dark);display:flex;justify-content:center;align-items:center;flex-wrap:wrap;gap:0 12px;font-size:10px;line-height:18px;color:var(--nes-light)}
#setup.nes-title .analytics-banner>span{flex-basis:100%;max-width:500px}
#setup.nes-title .analytics-banner .choice{font-size:11px;min-height:44px;box-shadow:none;padding:8px;color:var(--nes-ice)}
@media(max-width:699px){
 #setup.nes-title{padding-top:calc(12px + env(safe-area-inset-top,0px));align-items:flex-start}
 #setup.nes-title .title-shell{padding:8px 4px;min-height:min(760px,100%);--title-menu-width:304px;--title-entry-height:60px}
 #setup.nes-title .title-presents{font-size:10px;letter-spacing:2px;margin-bottom:16px}
 #setup.nes-title h1.title{font-size:32px;line-height:40px;letter-spacing:1px;text-shadow:2px 2px 0 var(--nes-blue),4px 4px 0 var(--nes-navy)}
 #setup.nes-title .title-tagline{font-size:10px;letter-spacing:1px;margin:10px 0 0}
 #setup.nes-title #titleArt{width:288px;margin-top:16px}
 #setup.nes-title .intro-location,.title-scene-caption{font-size:7px;line-height:10px;padding:0 2px}
 #setup.nes-title .title-start{font-size:20px;letter-spacing:2px;margin:16px 0 8px;min-height:var(--title-entry-height)}
 #setup.nes-title .title-game-menu{width:min(100%,var(--title-menu-width))}
 #setup.nes-title #setupSession{max-width:300px;margin:8px 0;line-height:18px}
 #setup.nes-title .title-utility{gap:0 8px}
 #setup.nes-title .title-footer{max-width:288px}

}
@media(min-width:700px) and (max-height:800px){
 #setup.nes-title{padding-top:12px;padding-bottom:12px}
 #setup.nes-title .title-shell{--title-entry-height:48px}
 #setup.nes-title h1.title{font-size:48px;line-height:52px}
 #setup.nes-title #titleArt{width:576px}
 #setup.nes-title .title-presents{margin-bottom:6px}
 #setup.nes-title .title-tagline{margin-top:10px}
 #setup.nes-title .title-start{margin-top:4px;gap:2px;font-size:20px;min-height:var(--title-entry-height);padding:4px 20px}
}
@media(max-height:500px) and (orientation:landscape){
 #setup.nes-title .title-shell{display:grid;grid-template-columns:minmax(0,1fr) minmax(220px,1fr);gap:0 20px;align-content:start;padding:4px 12px}
 #setup.nes-title .title-presents,#setup.nes-title .title,#setup.nes-title .title-tagline,#setup.nes-title #titleArt,#setup.nes-title .season-banner{grid-column:1}
 #setup.nes-title h1.title{font-size:32px;line-height:38px;letter-spacing:1px}
 #setup.nes-title #titleArt{width:288px}
 #setup.nes-title .title-start{grid-column:2;grid-row:1;margin:0;align-self:center;justify-self:center}
 #setup.nes-title .title-game-menu,#setup.nes-title #setupSession,#setup.nes-title .title-utility,#setup.nes-title .title-footer,#setup.nes-title #setupMsg{grid-column:2;justify-self:center}
 #setup.nes-title .title-game-menu{grid-row:2;align-self:start;margin-top:8px}
 #setup.nes-title #setupSession{grid-row:3;align-self:start}
 #setup.nes-title .title-utility{grid-row:4;align-self:start}
 #setup.nes-title .title-footer{grid-row:5;align-self:start}
 #setup.nes-title #setupMsg{grid-row:6}
 #setup.nes-title .title-scene-caption{display:none}
 #setup.nes-title .analytics-banner{grid-column:1/-1}
}
/* Wrapped utility controls must not center the walker below a short panel's clip. */
@media(max-height:360px) and (orientation:landscape){
 #setup.nes-title #titleArt{align-self:start;margin-top:0}
}
/* Each pose is drawn on one fixed pixel grid; no texture travel, crossfade or subpixel limb transform. */
.title-hero{position:absolute;left:44.965%;top:44.792%;width:15.625%;height:46.875%;overflow:hidden;image-rendering:pixelated}
.title-walk-strip{display:block;width:100%;height:100%}
.title-walk-strip svg{display:block;width:100%;height:100%;image-rendering:pixelated}
.title-gait-still{display:none}
.title-gait-frame{visibility:hidden;animation:title-footstep 1s step-end infinite}
.title-gait-1{animation-delay:-0.9375s}
.title-gait-2{animation-delay:-0.875s}
.title-gait-3{animation-delay:-0.8125s}
.title-gait-4{animation-delay:-0.75s}
.title-gait-5{animation-delay:-0.6875s}
.title-gait-6{animation-delay:-0.625s}
.title-gait-7{animation-delay:-0.5625s}
.title-gait-8{animation-delay:-0.5s}
.title-gait-9{animation-delay:-0.4375s}
.title-gait-10{animation-delay:-0.375s}
.title-gait-11{animation-delay:-0.3125s}
.title-gait-12{animation-delay:-0.25s}
.title-gait-13{animation-delay:-0.1875s}
.title-gait-14{animation-delay:-0.125s}
.title-gait-15{animation-delay:-0.0625s}
@keyframes title-footstep{0%{visibility:visible}6.25%,100%{visibility:hidden}}
#setup.hidden .title-parallax,#setup.hidden .title-gait-frame{animation-play-state:paused}
@media(prefers-reduced-motion:reduce){
 .title-parallax,.title-gait-frame,.title-packet{animation:none;will-change:auto}
 .title-gait-track{display:none}.title-gait-still{display:inline}
}
#onboarding{background:var(--nes-black);z-index:160;padding:0}
#onboarding .nes-intro{width:min(100%,980px);max-width:980px;min-height:100dvh;border:0;background:var(--nes-black);box-shadow:none;display:flex;flex-direction:column;justify-content:center;padding:24px 32px;gap:16px}
.intro-title{color:var(--nes-gold);letter-spacing:2px;margin:0;text-align:center}
.intro-cinematic{position:relative;padding-top:12px;border-top:8px dashed var(--nes-dark)}
.intro-office{position:relative;overflow:hidden;border:4px solid var(--nes-dark);background:var(--nes-black);width:100%}
.intro-office canvas{display:block;width:100%;height:auto;image-rendering:pixelated;aspect-ratio:20/9}
.intro-location,.intro-deadline{position:absolute;top:12px;background:var(--nes-black);padding:4px 8px;font-size:12px;line-height:20px;color:var(--nes-white)}
.intro-location{left:12px}.intro-deadline{right:12px;color:var(--nes-gold)}
.intro-scene-caption{position:absolute;left:50%;top:52%;transform:translateX(-50%);background:var(--nes-cream);color:var(--nes-black);padding:8px 12px;box-shadow:0 4px 0 var(--nes-black);white-space:nowrap;font-size:16px}
.intro-focus-vending .intro-scene-caption{left:auto;right:10px;transform:none;top:auto;bottom:16px}
.intro-cast{position:relative;display:flex;justify-content:space-between;margin-top:-104px;padding:0 12px;pointer-events:none;height:144px;z-index:1}
.intro-character{width:144px;height:144px;padding:8px;background:var(--nes-dark);border:4px solid var(--nes-gray);image-rendering:pixelated}
.intro-character svg{width:100%;height:100%;image-rendering:pixelated}
.intro-character.speaking{background:var(--nes-navy);border-color:var(--nes-gold);transform:translateY(-8px)}
.intro-character:not(.speaking){filter:brightness(.65)}
.intro-dialogue{position:relative;min-height:190px;margin:-20px 0 0;background:var(--bg);padding:26px 28px 16px;box-shadow:var(--win);border-bottom:4px solid var(--nes-sky)}
#onboarding .intro-dialogue h2{display:table;margin:-44px auto 16px;padding:6px 16px;background:var(--nes-gold);color:var(--nes-black);box-shadow:0 4px 0 var(--nes-black);font-size:20px;line-height:28px;position:relative;z-index:2}
.intro-text{white-space:pre-wrap;min-height:112px;margin:0;line-height:28px;font-size:18px;color:var(--nes-white)}
.intro-actions{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between;padding-top:20px}
.intro-actions .big{margin:0;min-height:48px}
.intro-count{color:var(--dim)}
.intro-controls{color:var(--dim);font-size:14px;line-height:24px}
.intro-controls summary{cursor:pointer;min-height:44px;text-align:center;padding:8px}
#setup .panel{width:min(100%,880px)}
#setup .title{text-align:center;color:var(--nes-gold);margin-bottom:16px}
#setup .cinematic-title-art{display:block;height:auto;margin:0 0 20px}
#setup .cinematic-title-art .intro-office{max-height:300px}
#setup .cinematic-title-art canvas{max-height:300px;object-fit:cover;object-position:center}
#setup .panel>p{max-width:720px;margin-left:auto;margin-right:auto}
#setup .row{justify-content:center}
@media(max-width:600px){
 #onboarding .nes-intro{padding:16px 12px;justify-content:flex-start;gap:12px}
 .intro-title{font-size:12px;line-height:20px;letter-spacing:1px}
 .intro-location,.intro-deadline{top:6px;padding:2px 5px;font-size:10px;line-height:16px}
 .intro-location{left:4px;max-width:54%}.intro-deadline{right:4px}
 .intro-office canvas{min-height:180px;object-fit:cover}
 .intro-cast{height:96px;margin-top:-60px;padding:0 6px}
 .intro-character{width:88px;height:96px;padding:4px}
 .intro-scene-caption{font-size:12px;padding:5px 8px}
 .intro-dialogue{padding:24px 16px 14px;min-height:230px}
 #onboarding .intro-dialogue h2{font-size:14px;line-height:24px;padding:4px 8px;margin-top:-40px;max-width:calc(100% - 140px);text-align:center}
 .intro-text{font-size:16px;line-height:26px;min-height:160px}
 .intro-actions{gap:8px;justify-content:center;padding-top:16px}
 .intro-actions .big{font-size:14px;padding:8px 12px}
 .intro-count{order:3;width:100%;text-align:center;font-size:12px}
 #setup .title{font-size:32px;line-height:40px}
}
@media(max-height:540px) and (min-width:601px){
 #onboarding .nes-intro{padding:12px 24px;justify-content:flex-start;gap:8px}
 .intro-cinematic{padding-top:6px;border-top-width:4px}
 .intro-office{height:140px}.intro-office canvas{height:100%;object-fit:cover}
 .intro-cast{height:96px;margin-top:-80px}.intro-character{height:88px;width:88px;padding:4px}
 .intro-dialogue{min-height:112px;padding:22px 20px 10px}
 #onboarding .intro-dialogue h2{font-size:16px;line-height:20px;margin-top:-40px;margin-bottom:8px}
 .intro-text{font-size:16px;line-height:24px;min-height:72px}
 .intro-actions{padding-top:12px}.intro-controls{font-size:12px}
}
/* The text view of a saved campaign: the same blue windows and the same font as the game, laid out as a page on black.
   Long-form text stays at 16px or larger (the font is drawn on an 8px grid, so it is crispest at 16, 24 and 32). */
.account{position:fixed;inset:0;z-index:100;background:var(--nes-black);color:var(--nes-white);overflow:auto;padding:32px max(24px,calc((100vw - 1100px)/2));
  font-family:"Smplify 8",ui-monospace,Menlo,Consolas,monospace;font-weight:400;font-synthesis:none;line-height:26px;font-size:calc(16px * var(--text-scale,1))}
.account.hidden{display:none}
.account h1{font-size:32px;line-height:40px;font-weight:400;color:var(--nes-white);margin:0;text-shadow:4px 4px 0 var(--nes-navy)}
.account h2{font-size:24px;line-height:32px;font-weight:400;margin:0 0 12px}
.account h3{font-size:16px;font-weight:400;color:var(--nes-ice)}
.account-row{display:flex;flex-wrap:wrap;gap:16px;align-items:center;justify-content:space-between;margin:16px 0}
.account-row span{background:var(--nes-navy);padding:8px 16px;box-shadow:0 -2px 0 0 var(--nes-sky),0 2px 0 0 var(--nes-sky),-2px 0 0 0 var(--nes-sky),2px 0 0 0 var(--nes-sky)}
.account-card{background:var(--nes-navy);padding:22px 24px;margin:24px 2px;box-shadow:0 -2px 0 0 var(--nes-white),0 2px 0 0 var(--nes-white),-2px 0 0 0 var(--nes-white),2px 0 0 0 var(--nes-white)}
.account-muted{color:var(--nes-ice)}
.account-status{background:var(--nes-navy);padding:14px 18px;min-height:56px;color:var(--nes-white);
  box-shadow:0 -2px 0 0 var(--nes-gold),0 2px 0 0 var(--nes-gold),-2px 0 0 0 var(--nes-gold),2px 0 0 0 var(--nes-gold);margin:4px 2px}
.account button{font:inherit;border:0;border-radius:0;background:var(--nes-navy);color:var(--nes-white);padding:8px 18px;cursor:pointer;margin:6px;
  box-shadow:0 -2px 0 0 var(--nes-white),0 2px 0 0 var(--nes-white),-2px 0 0 0 var(--nes-white),2px 0 0 0 var(--nes-white)}
.account button:hover{background:var(--nes-white);color:var(--nes-navy)}
.account button:focus-visible{outline:2px solid var(--nes-white);outline-offset:4px;background:var(--nes-white);color:var(--nes-navy)}
.account button:disabled{background:var(--nes-gray);color:var(--nes-black);cursor:wait;box-shadow:none}
.account button.secondary{background:var(--nes-navy)}
.account button.selected{color:var(--nes-gold);box-shadow:0 -2px 0 0 var(--nes-gold),0 2px 0 0 var(--nes-gold),-2px 0 0 0 var(--nes-gold),2px 0 0 0 var(--nes-gold)}
.account button.selected:hover,.account button.selected:focus-visible{color:var(--nes-black);background:var(--nes-gold)}
.account-issue{display:flex;justify-content:space-between;gap:16px;align-items:center;box-shadow:0 -2px 0 0 var(--nes-sky);padding:14px 0;margin-top:2px}
.account input,.account select,.account textarea{font:inherit;background:var(--nes-navy);border:0;color:var(--nes-white);padding:8px 12px;max-width:100%;border-radius:0;
  box-shadow:0 -2px 0 0 var(--nes-sky),0 2px 0 0 var(--nes-sky),-2px 0 0 0 var(--nes-sky),2px 0 0 0 var(--nes-sky)}
.account input:focus,.account select:focus,.account textarea:focus{outline:2px solid var(--nes-white);outline-offset:2px}
.account label{display:block;margin:12px 0}
.account small{display:block;color:var(--nes-ice)}
.account a{color:var(--nes-white)}
.account a:focus-visible{outline:2px solid var(--nes-white);outline-offset:4px}
.booking-link{color:var(--nes-white)}
@media(max-width:600px){.account{padding:20px 14px}.account-card{padding:16px}.account-issue{align-items:flex-start;flex-direction:column}.account h1{font-size:24px;line-height:32px}}
/* Foreman's message in the text view (the same three parts the phone shows). */
.account-foreman{margin:12px 0;padding:6px 16px;box-shadow:0 -2px 0 0 var(--nes-sky),0 2px 0 0 var(--nes-sky),-2px 0 0 0 var(--nes-sky),2px 0 0 0 var(--nes-sky)}
.account-foreman h3{margin:8px 0}
.account-foreman p{margin:8px 0}
/* Server mode: the small "Saving…" note while the server is slow to answer. */
#saving{position:absolute;right:12px;bottom:12px;z-index:6;background:var(--bg);color:var(--fg);padding:2px 12px;font-family:var(--font);box-shadow:var(--edge-dim);pointer-events:none}
/* Keyboard play (MAR-15): the skip link, the map's focus frame, key hints beside buttons, and the Controls screen.
   Same palette and same windows as the rest of the game. Focus is never color alone: it is an outline or the ▶ cursor. */

/* ---------- Tab order: skip link, the game, the HUD buttons ----------
   focus.ts moves the map first in the page so Tab reaches it before the HUD; these orders keep it looking as it did. */
#app>#hud{order:1}
#app>#tokenbar{order:2}
#app>#questbar{order:3}
#app>#stage{order:4}
#app>#pad{order:5}

.skip{position:fixed;left:12px;top:-80px;z-index:60;padding:6px 16px;background:var(--nes-white);color:var(--nes-navy);text-decoration:none;box-shadow:var(--win)}
.skip:focus,.skip:focus-visible{top:12px;outline:2px solid var(--nes-white);outline-offset:6px}

/* The map takes focus. Its window edge is already 2px white and 2px black, so the frame stands 6px out, where it can be seen. */
#cv:focus{outline:0}
#cv:focus-visible{outline:4px solid var(--nes-white);outline-offset:6px}
#questbar:focus-visible{background:var(--nes-white);color:var(--nes-navy);outline-offset:-2px}
#questbar:focus-visible span{color:var(--nes-navy)}
.ticket:focus-visible,#dialog:focus-visible{outline-offset:4px}

/* ---------- key hints ----------
   A small key name beside a button that has a key of its own. Desktops always show them; a touch screen shows them
   once a key has been pressed (focus.ts adds .using-keys). Screen readers get aria-keyshortcuts instead. */
[data-key]::after{content:"[" attr(data-key) "]";content:"[" attr(data-key) "]" / "";margin-left:10px;color:var(--dim);white-space:nowrap}
.choice:hover[data-key]::after,.choice:focus-visible[data-key]::after,.big:hover[data-key]::after,.big:focus-visible[data-key]::after{color:inherit}
#moves button[data-key]::after{order:-1;margin:0 10px 0 0;min-width:3ch}
#moves button[data-key]>span:first-child{flex:1}
#moves button[data-key]:hover:not(:disabled)::after,#moves button[data-key]:focus-visible::after{color:inherit}
#moves button:disabled[data-key]::after{color:inherit}
.town[data-key]::after{position:absolute;right:10px;top:8px;margin:0}
@media (pointer:coarse) and (hover:none){
  body:not(.using-keys) [data-key]::after{content:none}
}
.keyhint{color:var(--dim);margin:0}
#bkeys{grid-area:keys;padding:0 4px}
#battle .panel.has-keys{grid-template-areas:"arena arena" "msg cmd" "prompt cmd" "keys keys"}
@media (max-width:760px){#battle .panel.has-keys{grid-template-areas:"arena" "msg" "prompt" "cmd" "keys"}}
@media (pointer:coarse) and (hover:none){body:not(.using-keys) #bkeys{display:none}}

/* ---------- the Controls screen ---------- */
.controls{width:min(100%,860px)}
.controls .intro{margin-top:0}
.controls dl{margin:0 2px 8px;display:flex;flex-direction:column;gap:10px}
.controls dl>div{display:grid;grid-template-columns:minmax(220px,300px) minmax(0,1fr);gap:4px 20px;align-items:baseline;padding:8px 12px;background:var(--bg);box-shadow:var(--edge-dim)}
.controls dt{margin:0;color:var(--fg);display:flex;flex-wrap:wrap;gap:6px 8px;align-items:baseline}
.controls dd{margin:0;color:var(--dim)}
.controls kbd{font-family:var(--font);display:inline-block;min-width:24px;padding:0 8px;background:var(--nes-white);color:var(--nes-navy);text-align:center;box-shadow:0 2px 0 0 var(--nes-light)}
.controls .or{color:var(--dim)}
.controls h2:focus-visible{outline-offset:4px}
@media (max-width:560px){.controls dl>div{grid-template-columns:minmax(0,1fr)}}
/* The in-world rewards UX: the HUD pointer, the Supply Closet, the final mission and the journal's newer tabs.
   Same windows as the rest of the game: deep blue fill, a 2px white edge with notched corners. Gold is for tokens. */
.sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}

#tokenNext{background:none;border:0;padding:4px 0;color:var(--dim);text-decoration:underline dotted;text-underline-offset:4px}
#tokenNext:hover,#tokenNext:focus-visible{color:var(--nes-navy);background:var(--nes-white);text-decoration:none}

.closet,.finale{width:min(100%,700px);font-family:var(--font)}
.closet{width:min(100%,1040px)}
input,textarea{font-family:var(--font)}
.panel p.closet-banner{background:var(--bg);color:var(--fg);padding:8px 14px;box-shadow:var(--edge-dim);margin-left:2px;margin-right:2px}
.panel p.closet-next,.panel p.vm-prize{color:var(--gold)}
.panel .closet-notice,.panel .finale-status{color:var(--ok);min-height:1em}
.panel .closet-notice.bad,.panel .finale-status.bad{color:var(--drift)}
.closet-chips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 8px}

/* ---------- the vending machine ----------
   A cabinet, a glass window with a coil and a goodie in every slot, a side panel with the display, the coin slot and the keypad's
   button, and a tray. The frames are small pixel pictures set by theme.ts (--vm-*) and cut into nine pieces with border-image, so
   the machine stretches to any width without a blurry pixel. --px is how many screen pixels one art pixel is: whole numbers only. */
.closet-top{display:flex;margin:0 0 16px 2px}
.closet .big{min-height:44px}
.closet-wrap{display:grid;grid-template-columns:minmax(0,1fr);gap:24px;align-items:start}
.closet-info{min-width:0}
.closet-info>*:first-child{margin-top:0}
.vm{--px:3px;min-width:0}
.pic{display:inline-block;line-height:0;flex:none}
.pic svg{display:block;width:100%;height:100%;image-rendering:pixelated}
.vm-cabinet{display:grid;grid-template-columns:minmax(0,1fr);gap:calc(3 * var(--px));padding:calc(1 * var(--px));
  border:solid transparent;border-width:calc(6 * var(--px));border-image:var(--vm-cabinet) 6 fill / calc(6 * var(--px)) stretch}
.panel .vm-sign{display:flex;align-items:center;justify-content:center;gap:12px;margin:0;padding:0 8px;font-size:24px;line-height:32px;color:var(--nes-white);
  border:solid transparent;border-width:calc(4 * var(--px));border-image:var(--vm-sign) 4 fill / calc(4 * var(--px)) stretch;text-shadow:2px 2px 0 var(--nes-navy)}
.vm-sign .vm-token{width:28px;height:28px}
.vm-glass{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));align-content:start;position:relative;min-width:0;
  border:solid transparent;border-width:calc(4 * var(--px));border-image:var(--vm-glass) 4 fill / calc(4 * var(--px)) stretch}
.vm-glass::after{content:"";position:absolute;left:calc(2 * var(--px));top:calc(2 * var(--px));width:calc(8 * var(--px));height:calc(8 * var(--px));background:var(--vm-glint) 0 0 / 100% 100% no-repeat;pointer-events:none;image-rendering:pixelated}
.vm-empty{grid-column:1/-1;margin:16px;color:var(--fg)}

/* a slot: the goodie hangs in its coil, and the plate under it has the slot code and the price */
.vm-slot{position:relative;display:flex;flex-direction:column;align-items:stretch;min-width:0;min-height:44px;padding:calc(5 * var(--px)) calc(1 * var(--px)) 0;
  background:none;border:0;color:var(--fg);font:inherit;text-align:center;cursor:pointer}
.vm-slot:hover{box-shadow:inset 0 0 0 2px var(--nes-sky)}
.vm-slot:focus-visible{outline:2px solid var(--nes-white);outline-offset:-4px}
.vm-slot[aria-pressed=true]{box-shadow:inset 0 0 0 2px var(--nes-white);background:var(--nes-navy)}
.vm-goodie{position:relative;display:block;height:calc(24 * var(--px));margin:0 calc(-1 * var(--px));
  background:var(--vm-coil) repeat-x 0 calc(100% - 3 * var(--px)) / calc(6 * var(--px)) calc(4 * var(--px));image-rendering:pixelated}
.vm-art{position:absolute;left:50%;top:0;width:calc(24 * var(--px));height:calc(24 * var(--px));margin-left:calc(-12 * var(--px))}
.vm-lock{position:absolute;left:50%;top:calc(-2 * var(--px));width:calc(9 * var(--px));height:calc(10 * var(--px));margin-left:calc(3 * var(--px))}
.vm-cursor{position:absolute;left:50%;top:calc(1 * var(--px));width:calc(7 * var(--px));height:calc(4 * var(--px));margin-left:calc(-3.5 * var(--px));visibility:hidden}
.vm-slot:hover .vm-cursor,.vm-slot:focus-visible .vm-cursor,.vm-slot[aria-pressed=true] .vm-cursor{visibility:visible}
.vm-plate{display:flex;flex-direction:column;gap:2px;margin-top:calc(2 * var(--px));padding:2px 4px 4px;background:var(--nes-black);color:var(--nes-white);box-shadow:0 0 0 2px var(--nes-light)}
.vm-row{display:flex;justify-content:space-between;align-items:center;gap:6px}
.vm-price{display:inline-flex;align-items:center;gap:4px;color:var(--gold)}
.vm-price .vm-token{width:14px;height:14px}
.vm-tag{display:flex;align-items:center;justify-content:center;gap:6px;padding:0 2px;text-align:center;overflow-wrap:break-word;background:var(--nes-light);color:var(--nes-black)}
.vm-tag-lock{width:9px;height:10px}
.vm-shelf{display:block;height:calc(4 * var(--px));margin:auto calc(-1 * var(--px)) 0;background:var(--vm-shelf) repeat-x 0 0 / calc(4 * var(--px)) calc(4 * var(--px));image-rendering:pixelated}
/* a locked slot has a dark plate and a padlock; a restocking one has a gray plate and the goodie stays in full color, because showing what you can win is the point of the machine */
.vm-slot.locked .vm-plate{background:var(--nes-dark)}
.vm-slot.locked .vm-price{color:var(--nes-white)}
.vm-slot.soldout .vm-plate{background:var(--nes-gray);color:var(--nes-black)}
/* RESTOCKING SOON is the longest tag. Under about 130px a slot cannot hold RESTOCKING at 16px, so the tag drops to the font's own 8px (still crisp, still one line) instead of breaking a word */
.vm-slot{container-type:inline-size}
@container (max-width:129px){.vm-slot.soldout .vm-tag{font-size:8px;line-height:16px}}
.vm-slot.soldout .vm-price{color:var(--nes-black)}

/* the side panel: the display, the coin slot, and the keypad's button */
.vm-side{display:grid;grid-template-columns:minmax(0,1fr) calc(34 * var(--px));gap:calc(3 * var(--px));align-content:start;min-width:0;
  border:solid transparent;border-width:calc(4 * var(--px));border-image:var(--vm-panel) 4 fill / calc(4 * var(--px)) stretch}
.vm-lcd{display:flex;flex-direction:column;min-width:0;padding:2px 6px;
  border:solid transparent;border-width:calc(3 * var(--px));border-image:var(--vm-lcd) 3 fill / calc(3 * var(--px)) stretch}
.vm-lcd-label{color:var(--dim)}
.panel .vm-lcd-value,.vm-lcd-value{color:var(--gold);font-size:24px;line-height:32px;white-space:nowrap}
.vm-lcd-pick{color:var(--fg);min-height:24px;overflow-wrap:break-word}
.vm-coin{display:flex;flex-direction:column;align-items:center;gap:6px}
.vm-coin-art{width:calc(15 * var(--px));height:calc(22 * var(--px))}
.vm-coin-plate{padding:0 8px;background:var(--nes-black);color:var(--ok);box-shadow:var(--edge-dim);text-align:center}
.vm[data-coin=paused] .vm-coin-plate,.vm[data-coin=display-only] .vm-coin-plate,.vm[data-coin=sign-in] .vm-coin-plate{background:var(--nes-dark);color:var(--nes-white);box-shadow:var(--edge-dim)}
.vm-insert{grid-column:1/-1;min-height:48px;padding:8px 10px 8px 26px;text-align:center}

/* the tray */
.vm-tray{display:flex;align-items:center;gap:12px;min-height:calc(20 * var(--px));padding:4px 12px;overflow:hidden;color:var(--fg);
  border:solid transparent;border-width:calc(5 * var(--px)) calc(3 * var(--px)) calc(3 * var(--px));border-image:var(--vm-tray) 5 3 3 3 fill / calc(5 * var(--px)) calc(3 * var(--px)) calc(3 * var(--px)) stretch}
.panel .vm-tray p{margin:0;color:var(--fg)}
.panel .vm-tray p.closet-notice:not(.bad){color:var(--ok)}
.vm-tray-idle{color:var(--dim)}
.vm-tray-text b{display:block;color:var(--gold)}
.vm-slip{width:calc(12 * var(--px));height:calc(14 * var(--px))}
@keyframes vm-drop{from{transform:translateY(calc(-16 * var(--px)))}to{transform:none}}
@keyframes vm-press{50%{transform:translateY(calc(2 * var(--px)))}}
.vm-animating .vm-slip{animation:vm-drop .5s steps(5) both}
.vm-animating .vm-coin-art{animation:vm-press .5s steps(3) both}

/* the details beside the machine (under it on a phone) */
.vm-detail{padding:12px 16px 4px;margin:2px 2px 16px;box-shadow:var(--edge-dim)}
.panel .vm-facts{color:var(--gold);margin-top:0}
.vm-detail .qlist{margin:0 0 12px;gap:8px}
.vm-detail .qlist li{box-shadow:none;padding:4px 0}

@media (max-width:560px){
  .vm-glass{grid-template-columns:repeat(2,minmax(0,1fr))}
  .panel .vm-sign{font-size:16px;line-height:24px;gap:8px}
  .vm-sign .vm-token{width:14px;height:14px}
  .vm-tray{padding:4px 8px;gap:8px}
}
@media (min-width:900px){
  .vm{--px:4px}
  .closet-wrap{grid-template-columns:minmax(0,700px) minmax(240px,1fr)}
  .vm-cabinet{grid-template-columns:minmax(0,1fr) 216px;grid-template-areas:"sign sign" "glass side" "tray tray"}
  .vm-sign{grid-area:sign}.vm-glass{grid-area:glass}.vm-side{grid-area:side;grid-template-columns:minmax(0,1fr);align-content:start}
  .vm-tray{grid-area:tray}
  .vm-coin{flex-direction:column}
}
.closet-mine{margin-top:8px}
textarea{resize:vertical}
.closet-form .hint,.finale-form .hint{display:block;margin-top:8px}

.speech{background:var(--bg);padding:10px 14px;margin:10px 2px;box-shadow:var(--edge)}
.panel .speech p{margin:4px 0;color:var(--fg)}
.speech b{color:var(--gold)}
.speech b.fm{color:var(--fg)}
.speech b.fm::before{content:"";display:inline-block;width:14px;height:10px;margin-right:8px;background:var(--ic-robot) center/14px 10px no-repeat;image-rendering:pixelated}

a.finale-link{display:inline-block;text-decoration:none}
.panel p.finale-state{color:var(--fg);background:var(--bg);padding:8px 14px;box-shadow:var(--edge-dim);margin-left:2px;margin-right:2px}
.panel p.finale-state.ok{color:var(--ok);box-shadow:var(--edge-ok)}

.badge.secret{box-shadow:var(--edge)}
.badge.secret small{display:block;color:var(--dim);margin-top:4px}

.leaderboard{margin:8px 0 0;padding-left:32px}
.leaderboard li{background:var(--bg);padding:6px 12px;margin:8px 2px;box-shadow:var(--edge-dim)}
.leaderboard span{color:var(--dim)}
#tab-crew input[readonly]{color:var(--fg)}
#tab-crew .stats,#tab-missions .qlist{margin-top:12px}

/* Field notes: the journal's catalogue of Smplify's write-ups (field-notes-ui.ts). A card is a small window with the plate
   number beside the study's name. White and ice type on the blue window; no gold (that is tokens) and no red (danger). */
a.big{display:inline-block;text-decoration:none}
.notes{list-style:none;margin:12px 2px 0;padding:0;display:flex;flex-direction:column;gap:16px}
.note{background:var(--bg);padding:12px 14px;display:flex;gap:16px;box-shadow:var(--edge-dim)}
.note-plate{flex:none;width:72px;text-align:center;color:var(--dim)}
.note-plate small{display:block}
.note-plate b{display:block;font-size:32px;line-height:40px;color:var(--fg);text-shadow:4px 4px 0 var(--nes-black)}
.note-body{flex:1;min-width:0}
.panel h4.note-title{margin:0;font-size:16px;line-height:24px;color:var(--fg);font-weight:400}
.panel p.note-meta{margin:0 0 8px;color:var(--dim)}
.note-new{display:inline-block;padding:0 6px;margin-right:8px;background:var(--nes-indigo);color:var(--nes-white)}
.panel p.note-take{margin:0 0 8px;color:var(--fg)}
.panel p.note-where{margin:0;color:var(--dim)}
.note .row{margin-top:12px}
@media (max-width:560px){
  .note{flex-direction:column;gap:4px}
  .note-plate{width:auto;display:flex;gap:8px;align-items:baseline;text-align:left}
  .note-plate b{font-size:24px;line-height:32px;text-shadow:2px 2px 0 var(--nes-black)}
}
/* The cabinet stays in the world; the storefront does not advertise unavailable goods. */
.coming-soon-header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin-bottom:12px}.coming-soon-header h2{margin:0}.coming-soon-body{display:flex;align-items:center;gap:16px;margin-bottom:12px}.coming-soon-machine{width:64px;flex:0 0 64px;image-rendering:pixelated}.coming-soon-machine svg{display:block;width:100%;height:auto}.coming-soon-copy{min-width:0}.coming-soon-copy p{margin:0 0 8px;line-height:1.4}.coming-soon-label{font-size:20px}.coming-soon-balance{color:var(--nes-gold)}.coming-soon-history{margin-top:12px}
/* Phones and small windows (MAR-18). Nothing in here touches a desktop: every rule sits inside the compact query, which is the same
   one layout.ts uses to size the map (a test keeps the two equal). Same palette, same font, same windows as the rest of the game.

   The picture: the map takes every pixel the HUD leaves, at a whole-number scale (layout.ts). The HUD is a block at the top, in
   short rows: where you are, the meters, the four buttons (with pixel icons and short labels), and the quest on one line. The joystick
   (bottom left) and the A button (bottom right) float over the bottom corners of the map, so they cost no layout space; the camera
   scrolls the last rows of the office clear of them (layout.ts, slideFor). On a phone held sideways the HUD is one slim strip.
   Targets are 44px or more. Content that is taller than the screen scrolls inside its own window. */

.hic{display:none}
/* The speech bubble goes under the player's feet (with its arrow on top) when over his head it would leave the map or sit on the toast. */
#bubble.below{transform:translate(-50%,0)}
#bubble.below::after{content:"\25B2";content:"\25B2" / "";bottom:auto;top:-24px}
#titleTouch{display:none}
@media (pointer: coarse) { #titleTouch{display:block} }
/* A touch control on the Controls screen wears the same white slab as a key. */
.controls .cap{font-family:var(--font);display:inline-block;min-width:24px;padding:0 8px;background:var(--nes-white);color:var(--nes-navy);text-align:center;box-shadow:0 2px 0 0 var(--nes-light)}
.controls ul.touch{list-style:none;margin:0 2px 8px;padding:0;display:flex;flex-direction:column;gap:10px}
.controls ul.touch>li{display:grid;grid-template-columns:minmax(110px,170px) minmax(0,1fr);gap:4px 20px;align-items:baseline;padding:8px 12px;background:var(--bg);box-shadow:var(--edge-dim)}
.controls ul.touch .what{color:var(--dim)}
.controls ul.touch .cap{justify-self:start}
@media (max-width: 560px) { .controls ul.touch>li{grid-template-columns:minmax(0,1fr)} }

@media (pointer: coarse), (max-width: 720px), (max-height: 520px) {
  /* ---------- the page ---------- */
  /* Nothing in the page may push it wider than the screen: a phone's browser would zoom the whole game out to fit (the HUD's longest line, a
     signed-in player's "N tokens to the T-shirt", is the one that did). */
  #app{position:relative;overflow:hidden;overflow:clip}
  #stage{padding:8px}
  #toast{top:12px}

  /* ---------- the HUD: one block (hud.ts moves the token line and the quest line into it, see layout.ts/ initLayout) ----------
     Rows, by flex order: where you are | the meters | the coffee and the tokens | the buttons | the quest. */
  #hud{display:flex;flex-wrap:wrap;gap:0 10px;padding:4px 12px 0;align-items:center;justify-content:flex-start;box-shadow:0 2px 0 0 var(--nes-white)}
  #hud::after{display:block;order:5}
  #loc{order:1;flex:1 0 100%;margin:0;max-width:none;font-size:16px;line-height:28px}
  #hud .stat{order:2;gap:6px;line-height:24px;min-height:24px}
  #hud #coffeeStat{order:3}
  #hud #tokenbar{order:4;flex:0 1 auto;min-width:0;max-width:100%;margin-left:auto;padding:0;min-height:24px;gap:8px;background:none;flex-wrap:nowrap;white-space:nowrap}
  #hud #tokenTxt{padding:0;flex:none}
  /* Signed in, the pointer to the next reward is a button (44px high), and gives way with an ellipsis when the line is long. */
  #hud #tokenNext{display:block;flex:0 1 auto;min-width:0;min-height:44px;padding:0 4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #hud .bar{--seg:5px;--gap:1px}
  #hud .cups{--cw:9px;--ch:7px}

  /* The four buttons: a tile each, icon over a short label. The icon is a mask in the text color, so it inverts with the button on focus. */
  #hud .hudbtn{order:6;flex:1 1 0;min-width:0;min-height:52px;margin:6px 0;padding:4px 2px 2px;display:flex;flex-direction:column;align-items:center;justify-content:center;
    text-align:center;white-space:nowrap;line-height:20px;box-shadow:var(--edge-dim);--cx:0}
  #hud .hudbtn::before{display:none}
  #hud .hudbtn:hover,#hud .hudbtn:focus-visible{background:var(--nes-white);color:var(--nes-navy);box-shadow:var(--edge)}
  .hic{display:block;flex:none;width:24px;height:24px;background:currentColor;-webkit-mask:var(--hic) center/24px 24px no-repeat;mask:var(--hic) center/24px 24px no-repeat}
  #travelBtn .hic{--hic:var(--hic-travel)} #journalBtn .hic{--hic:var(--hic-journal)} #menuBtn .hic{--hic:var(--hic-menu)} #vendingBtn .hic{--hic:var(--hic-vending)}
  /* "◈ Vending machine" reads "Vending" on the button; a screen reader still hears all of it. */
  #hud .gl,#hud .more{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}

  /* The quest: one line, the whole row a 44px button. */
  #hud #questbar{order:7;flex:1 0 100%;display:block;height:44px;line-height:44px;margin:0 -12px;padding:0 12px;box-shadow:0 -2px 0 0 var(--nes-sky)}

  /* ---------- windows over the map ----------
     A window scrolls inside itself when its content is taller than the screen, and the row with its way out (.pin) stays in view at the
     bottom, so the button that closes it is never a long scroll away. */
  .overlay{padding:calc(10px + env(safe-area-inset-top,0px)) 10px calc(10px + env(safe-area-inset-bottom,0px))}
  .panel{padding:16px;margin:4px;overscroll-behavior:contain}
  .panel>.row.pin{position:sticky;bottom:0;z-index:3;margin:16px -16px -16px;padding:10px 16px 10px 18px;background:var(--bg);box-shadow:0 -2px 0 0 var(--nes-sky);gap:8px 12px}
  .panel>.row.pin .big{flex:1 1 auto;justify-content:center;text-align:center}
  .panel h2{margin-bottom:4px}

  .tabs{gap:4px 10px;padding-left:0}
  .tabs button{padding:2px 4px}

  /* The travel picker: two offices across on a phone. */
  #towns{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px;margin:12px 0;padding:0 2px}
  .town{padding:10px 10px 10px 14px}

  /* The Menu: its row of ways out is two across. */
  #menu .row.pin{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
  #menuMode{margin-bottom:8px}
  #menuFields{max-height:132px}
}
/* Seven tabs in one or two short rows on a narrow screen (three at the very narrowest). */
@media (max-width: 700px) {
  .tabs{display:flex;flex-wrap:wrap;gap:4px;padding:0;margin:8px 0 12px}
  .tabs button{flex:1 1 auto;padding:2px 4px;justify-content:center;text-align:center;--cx:0}
  .tabs button::before{display:none}
  .tabs .t{text-transform:capitalize}
  .tabs .more{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
  .rankcard{gap:12px;padding:8px 12px;margin:4px 0 8px}
  .rankcard .lv{font-size:32px;line-height:32px}
}

/* ---------- the dialog and the battle, on a phone ---------- */
@media (pointer: coarse), (max-width: 720px), (max-height: 520px) {
  #dialog{bottom:calc(10px + env(safe-area-inset-bottom,0px));width:calc(100vw - 20px);max-width:760px;padding:16px 18px 10px}
  #dtext{max-height:38vh}
  #dchoices{gap:0 16px;margin-top:8px;padding-left:12px}
  #bubble{max-width:min(300px,calc(100vw - 32px))}

  /* The battle fits the screen, whatever the screen: the foe beside its name plate, you under them, then what happened (a box that scrolls
     inside itself when the text is long, newest at the bottom), then what you can do. Every command is a 44px row even when its label wraps,
     so a foe with eight commands still shows them all without scrolling the page. The line of key hints is for a keyboard and a desktop:
     here it stays out of the way (the Controls screen lists every key). */
  #battle{align-items:stretch;padding:calc(10px + env(safe-area-inset-top,0px)) 10px calc(10px + env(safe-area-inset-bottom,0px))}
  #battle .panel,#battle .panel.has-keys{height:100%;max-height:100%;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(44px,1fr) auto;grid-template-areas:"arena" "msg" "cmd";gap:8px;align-content:stretch;align-items:stretch}
  #bkeys{display:none}
  .arena{height:auto;display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:6px 12px;border-bottom:0;padding-bottom:0}
  .arena .plate,.arena #foeCv,.arena #intentTag,.arena #pendingTag{position:static;margin:0}
  .arena #foePlate{order:1;flex:1 1 0;min-width:150px} .arena #foeCv{order:2;flex:0 0 auto;width:96px;height:96px;margin-right:2px}
  .arena #heroPlate{order:3;flex:1 0 100%} .arena #intentTag{order:4;flex:1 0 100%} .arena #pendingTag{order:5;flex:1 0 100%;max-width:none}
  .plate{min-width:0;padding:4px 10px 4px}
  #intentTag,#pendingTag{padding:0 8px;line-height:22px}
  .plate .bar,.plate .cups{margin-top:0}
  /* The foe: its name, then the drift squares with the word beside them. */
  #foePlate{display:grid;grid-template-columns:auto minmax(0,1fr);grid-template-areas:"name name" "bar sub";gap:2px 10px;align-items:center}
  #foePlate>span{grid-area:name}
  #foePlate .bar{grid-area:bar;--seg:9px;--gap:3px}
  #foePlate small{grid-area:sub}
  /* You: the name on top, the cups and the count under it, side by side. */
  #heroPlate{display:grid;grid-template-columns:auto minmax(0,1fr);grid-template-areas:"name name" "cups lv";gap:2px 8px;align-items:center}
  #heroPlate>span{grid-area:name}
  #heroPlate .cups{grid-area:cups;margin:0}
  #heroPlate .lv{grid-area:lv;text-align:right;white-space:nowrap}
  #btext{grid-area:msg;align-self:stretch;min-height:0;margin:2px;padding:8px 14px;line-height:22px;overflow-y:auto;overscroll-behavior:contain}
  #moves{grid-area:cmd;margin:2px;padding:4px 8px}
  #moves button{min-height:44px;padding:0 8px 0 4px;line-height:22px}
  /* The foe still bobs, by one art pixel of its smaller picture, so the top of the bob stays on the screen on a phone held sideways. */
  .arena #foeCv:not(.hit){animation-name:bob-sm}
}
@keyframes bob-sm{50%{transform:translateY(-3px)}}
/* A short upright phone (360x640): the foe is two screen pixels to an art pixel, not three, so the commands fit under it. */
@media (max-width: 760px) and (max-height: 700px) {
  .arena #foeCv{width:64px;height:64px}
}
/* On a touch screen the ▶ cursor beside a command is for the keyboard, and gives its room to the label. */
@media (pointer: coarse) {
  #moves{padding-left:8px}
  #moves button::before{display:none}
}
/* Held sideways: the foe and you on the left, the commands on the right, all on one screen. */
@media (max-height: 520px) {
  .panel{padding:12px 16px}
  .panel>.row.pin{margin:12px -16px -12px;padding:6px 16px;gap:8px}
  .panel>.row.pin .big{flex:0 1 auto;min-width:160px}
  #menu .row.pin{display:flex;flex-wrap:nowrap}
  #menu .row.pin .big{flex:1 1 0;min-width:0;padding-left:12px;padding-right:12px}
  .panel h2{margin-bottom:0}
  .rankcard{margin:4px 0 6px}
  #dialog{font-size:16px;line-height:24px;padding:12px 20px 6px;bottom:calc(6px + env(safe-area-inset-bottom,0px))}
  #dialog #dname{font-size:16px}
  #dialog #dtext{min-height:48px;max-height:32vh}
  #battle{padding:calc(4px + env(safe-area-inset-top,0px)) calc(10px + env(safe-area-inset-right,0px)) calc(4px + env(safe-area-inset-bottom,0px)) calc(10px + env(safe-area-inset-left,0px))}
  #battle .panel,#battle .panel.has-keys{grid-template-columns:minmax(300px,336px) minmax(0,1fr);grid-template-rows:auto minmax(44px,1fr);grid-template-areas:"arena cmd" "msg cmd";gap:8px 12px}
  #moves{align-self:start;max-height:100%;overflow-y:auto}
}

/* ---------- the gate desk, the forms and the text view, on a phone ---------- */
@media (pointer: coarse), (max-width: 720px), (max-height: 520px) {
  /* The three calls stay at the bottom of the window while the request above them scrolls. */
  .gatepanel .gbtns{position:sticky;bottom:-16px;z-index:2;margin:0 -2px -16px;padding:10px 2px 14px;background:var(--bg);gap:10px}
  .gbtns button{min-height:52px}
  .ticket{padding:12px 14px;margin:12px 2px}
  .ticket h3{padding-right:110px}
  .gtimer{margin:10px 2px}
  input[type=text],input[type=email],input[type=tel],input[type=password],input[type=url],textarea,select{min-height:44px}
  .finale-form input[type=checkbox]{min-width:44px;min-height:44px;vertical-align:middle}
  input[type=range]{height:44px}
  #dlink a{display:inline-flex;align-items:center;min-height:44px}
  .account button{min-height:44px}
  .account a.button{min-height:44px}
}
/* The Menu's choice of touch control is only for a touch screen, which is the only one with a pad. */
#padRow{display:none}
@media (pointer: coarse) {
  /* A keyboard hint means little under a thumb: the title screen says what the touch controls are instead. */
  #titleKeys{display:none}
  #padRow{display:flex}
}

/* ---------- a phone held sideways: the HUD is a slim strip ----------
   Two rows: where you are, the meters and the tokens (28px), then the quest line with the four buttons beside it (48px). The map gets the rest. */
@media (max-height: 520px) {
  #stage{padding:7px 8px}
  #toast{top:8px}
  #hud{padding:2px 12px 6px;gap:0 12px}
  #hud::after{order:4}
  #loc{flex:1 1 0;min-width:48px;order:1}
  #hud .stat{order:2}
  #hud #coffeeStat{order:3}
  #hud .cups{display:none}
  #hud .bar{--segs:6;--seg:4px;--gap:1px}
  /* The second row is the quest, the tokens and the four buttons. The quest takes what the others leave; the token line keeps up to
     two fifths of the row, and its pointer to the next reward gives way with an ellipsis. Each button is its icon alone: its name is
     still there for a screen reader. */
  #hud #tokenbar{order:6;flex:0 1 auto;max-width:40%;margin:2px 0 0 8px;min-height:44px;align-items:center}
  #hud #questbar{order:5;flex:1 1 0;min-width:0;height:44px;line-height:44px;margin:2px 0 0 -12px;padding:0 12px;box-shadow:none}
  #hud .hudbtn{order:7;flex:0 0 auto;width:48px;min-height:44px;height:44px;margin:2px 0 2px 8px;padding:0;flex-direction:row;justify-content:center}
  #hud .hudbtn .lbl{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
}
/* A narrow phone held sideways (667px): the plain token line (the offline demo) joins the meters in the first row, so the quest keeps the second row to
   itself. A signed-in player's line has a 44px button in it and stays in the second row. (Needs :has(); without it the line stays in the second row.) */
@media (max-height: 520px) and (max-width: 799px) {
  #hud #tokenbar:not(:has(#tokenNext:not(.hidden))){order:3;max-width:34%;margin:0 0 0 auto;min-height:24px}
}
/* Wide enough for it (a big phone held sideways), the short labels come back beside the icons. */
@media (max-height: 520px) and (min-width: 900px) {
  #hud .hudbtn{width:auto;gap:6px;padding:0 10px}
  #hud .hudbtn .lbl{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto;clip-path:none}
}

/* ---------- the touch pad: a joystick or a D-pad at the bottom left, the A button at the bottom right, over the map ---------- */
@media (pointer: coarse) {
  #pad{display:block;position:absolute;inset:0;padding:0;z-index:10;pointer-events:none}
  #pad>*{pointer-events:auto}
  /* A window (dialog, battle, Journal...) is open: the pad is out of the way, and cannot be pressed. */
  body.has-window #pad{visibility:hidden}
  .abtn{position:absolute;right:16px;bottom:28px;width:72px;height:72px;margin:0;font-family:var(--font)}
  .dpad{position:absolute;left:12px;bottom:12px}

  /* The joystick: the ring is the pixel art from art-data.ts at a whole-number scale; the knob rides on it. Its hit area is a little
     bigger than the ring (the ::before), and it never scrolls or zooms the page. */
  .joy{--jpx:4px;position:absolute;left:14px;bottom:14px;width:calc(32 * var(--jpx));height:calc(32 * var(--jpx));touch-action:none;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}
  .joy::before{content:"";position:absolute;inset:-20px}
  .joy-ring{position:absolute;inset:0;background:var(--joy-ring) 0 0/100% 100% no-repeat;image-rendering:pixelated}
  .joy-knob{position:absolute;left:calc(9 * var(--jpx));top:calc(9 * var(--jpx));width:calc(14 * var(--jpx));height:calc(14 * var(--jpx));
    background:var(--joy-knob) 0 0/100% 100% no-repeat;image-rendering:pixelated;transform:translate(var(--kx,0px),var(--ky,0px))}
  /* One of the two is showing: the Menu's "Touch controls" picks (touch-pad.ts). */
  body.pad-joystick .dpad,body.pad-dpad .joy{display:none}
}
/* Held sideways there is less height: a smaller ring (still a big target), nearer the corner. */
@media (pointer: coarse) and (max-height: 520px) {
  .joy{--jpx:3px;left:12px;bottom:10px}
  .abtn{bottom:16px;width:64px;height:64px}
}

/* A small upright phone (a 360x640 screen): the frame is one screen pixel to an art pixel, so the whole message fits in 70% of the height. */
@media (max-width: 760px) and (max-height: 720px) {
  .phone{--px:1px}
  .bub{--bpx:1px}
  .phone-head{padding-bottom:4px}
  .phone-thread{padding-top:4px}
}

/* ---------- Foreman's phone ----------
   Held upright it is a sheet as wide as the screen (phone.css). Held sideways there is no height for a tall phone, so it lies on its side:
   the message on the left, Approve and Deny on the right. The whole message is always in view, and the phone is never more than 70% of
   the screen's height (e2e/helpers.ts, expectWholeMessage, checks every size). */
@media (max-height: 520px) {
  #phone{justify-content:center;padding:8px calc(10px + env(safe-area-inset-right,0px)) calc(8px + env(safe-area-inset-bottom,0px)) calc(10px + env(safe-area-inset-left,0px))}
  .phone{--px:2px;width:100%;max-width:760px;max-height:70%}
  .phone-screen{display:grid;grid-template-columns:minmax(0,1fr) minmax(256px,270px);grid-template-areas:"thread head" "thread actions" "thread hint";grid-template-rows:auto auto 1fr;column-gap:10px}
  /* Who is writing moves to the right-hand column, above the buttons, so the message has the whole height on the left. */
  .phone-head{grid-area:head;flex-wrap:wrap;gap:4px 8px;padding:2px 4px 6px}
  .phone-chan{margin-left:0}
  .phone-thread{grid-area:thread}
  .phone-actions{grid-area:actions;flex-direction:column;gap:6px;padding:6px 4px 0}
  .phone-btn{min-height:44px;padding:4px 8px}
  .phone-hint{grid-area:hint;align-self:start;margin:4px 0 0;white-space:nowrap}
  #phoneNote{top:calc(8px + env(safe-area-inset-top,0px));width:min(92vw,560px)}
}

/* The phone on a 667px screen: a thin frame and a narrower button column give the message the room it needs inside 70% of the height; the hint may take two lines. */
@media (max-height: 520px) and (max-width: 799px) {
  .phone{--px:1px}
  .phone-screen{grid-template-columns:minmax(0,1fr) 200px}
  .phone-hint{white-space:normal}
}

/* ---------- a phone held sideways: the title, the vending machine, the gate desk ---------- */
@media (max-height: 520px) {
  .title{font-size:32px;line-height:40px;margin-bottom:4px}
  .title-art{height:64px;margin:4px 0 10px;gap:12px}
  .title-art .hero,.title-art .fm{width:48px;height:48px}
  .title-art .foe{width:64px;height:64px}
  /* The title screen on its side: the story on the left, the buttons on the right, so Play is on the first screen. */
  #setup:not(.nes-title) .panel{width:min(100%,780px);display:grid;grid-template-columns:minmax(0,1fr) minmax(230px,280px);column-gap:24px;align-content:start}
  #setup:not(.nes-title) .panel>:not(.row):not(.setting):not(#setupMsg){grid-column:1}
  #setup:not(.nes-title) .row{grid-column:2;grid-row:1;flex-direction:column;flex-wrap:nowrap;align-self:start;margin-top:6px;gap:12px}
  #setup:not(.nes-title) .setting{grid-column:2;grid-row:2;align-self:start;margin-top:0}
  #setup:not(.nes-title) #setupMsg{grid-column:2;grid-row:3;margin-top:0}
  .ticket{padding:8px 14px;margin:8px 2px}
  .ticket dl{gap:2px 12px}
  .ticket .why{margin-top:6px}
  .gtimer{margin:6px 2px}
  .gatepanel .gbtns{bottom:-12px;margin-bottom:-12px;padding:6px 2px 8px}
  .gbtns button{min-height:44px}
  .panel p{margin:6px 0 10px}
  /* The machine at two screen pixels to an art pixel. */
  .vm{--px:2px}
}
/* Wide enough (an 844px phone and up): the display and the coin slot beside the glass, and the details beside the machine. A 667px phone keeps
   the machine in one column, as an upright phone does, because beside each other the slots are only about 35px wide. */
@media (max-height: 520px) and (min-width: 800px) {
  .closet-wrap{grid-template-columns:minmax(0,1fr) minmax(200px,280px)}
  .vm-cabinet{grid-template-columns:minmax(0,1fr) 150px;grid-template-areas:"sign sign" "glass side" "tray tray"}
  .vm-sign{grid-area:sign}.vm-glass{grid-area:glass}.vm-side{grid-area:side;grid-template-columns:minmax(0,1fr);align-content:start}
  .vm-tray{grid-area:tray}
  .vm-coin{flex-direction:column}
}
/* A slot at two screen pixels to an art pixel is under 110px wide: the price drops its token to fit beside the slot code. */
@container (max-width: 110px) { .vm-price .vm-token { display: none; } }
