/* Ponoki — The Long Way Home
   Two players, two phones, two completely different screens. Arcade-crisp:
   flat blocks, hard edges on the maze, one strong colour per game object so
   nothing reads as "another yellow dot". */

:root {
  /* Ponoki is dark only (a light theme is deliberately deferred, see
     docs/DESIGN.md). Saying so stops Android browsers, Samsung Internet in
     particular, running their own dark-mode colour transform over a page that
     is already dark, which was lightening the map's corridors far past the
     point where the lighter-walkable / darker-solid rule still read. This page
     does not load shared/styles/tokens.css, so it declares its own. */
  color-scheme: dark;

  --ink:      hsl(230, 35%,  7%);
  --surface:  hsl(230, 28%, 10%);
  --card:     hsl(230, 25%, 14%);
  --line:     hsl(228, 20%, 22%);
  --text:     hsl(220, 20%, 92%);
  --muted:    hsl(220, 16%, 68%);   /* was 58%: 2.9:1 on the page background */
  --dim:      hsl(220, 13%, 56%);   /* was 38%: unreadable for status text */
  --accent:   hsl(185, 70%, 55%);
  --accent-dim: hsl(185, 55%, 34%);

  /* one object, one colour — used identically on both screens */
  --key:      hsl(42, 95%, 62%);
  --fly:      hsl(180, 85%, 78%);
  --lantern:  hsl(30, 88%, 58%);
  --flame:    hsl(48, 100%, 78%);
  --shutter:  hsl(285, 62%, 68%);
  --gate:     hsl(212, 78%, 66%);   /* was violet: at legend-swatch size it was the same colour as the door */
  --home:     hsl(48, 100%, 78%);

  /* Terrain is two materials, each in a walkable and a SOLID form, so the one
     rule a player has to learn is reinforced by every pair:
       LIGHTER THAN THE PATH = you can walk on it
       DARKER  THAN THE PATH = solid, you cannot
     Reeds and loose stones used to sit here too. Both were walkable and both
     did a job ferns and shallows already did, so they were two extra rows in
     the legend buying nothing. */
  --wall:       hsl(230, 30%,  8%);   /* SOLID */
  --moss:       hsl(150, 58%, 13%);   /* SOLID  — dark green  */
  --moss-edge:  hsl(148, 50%, 19%);   /* must stay below --floor */
  --deep:       hsl(203, 60%, 13%);   /* SOLID  — dark teal   */
  --deep-edge:  hsl(198, 52%, 19%);   /* must stay below --floor */
  --floor:      hsl(228, 16%, 22%);   /* the line between the two */
  --shallow:    hsl(190, 48%, 40%);   /* walkable — light teal  */
  --fern:       hsl(108, 40%, 42%);   /* walkable — light green */

  --pk-accent: hsl(248, 38%, 72%);
  --pk-band:   hsl(250, 44%, 81%);
  --pk-eye:    hsl(24, 34%, 19%);
  --pk-body:   hsl(28, 66%, 80%);
  --pk-cheek:  hsl(8, 66%, 72%);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--ink); color: var(--text);
  font-family: var(--font-body); overscroll-behavior: none;
  -webkit-font-smoothing: antialiased;
}

/* ── screens ─────────────────────────────────────────────────── */
.screen {
  position: fixed; inset: 0; z-index: 1;
  display: none; flex-direction: column; gap: 8px;
  padding: calc(8px + env(safe-area-inset-top)) calc(12px + env(safe-area-inset-right))
           calc(10px + env(safe-area-inset-bottom)) calc(12px + env(safe-area-inset-left));
}
.screen.is-active { display: flex; }
#screen-start, #screen-wait, #screen-end { justify-content: center; overflow-y: auto; }
/* When the content is taller than the screen, `justify-content: center` clips
   equally at BOTH ends and the top is unreachable, which cut Ponoki's hat off
   the end screen. `safe center` centres only while there is room. */
#screen-start, #screen-wait, #screen-end { justify-content: safe center; }
#screen-end { gap: 10px; padding-bottom: calc(20px + env(safe-area-inset-bottom)); }

.nav-back {
  position: absolute; top: calc(8px + env(safe-area-inset-top)); left: calc(8px + env(safe-area-inset-left));
  display: grid; place-items: center; width: 44px; height: 44px;
  color: var(--muted); border-radius: 50%; text-decoration: none; z-index: 5;
}

/* ── buttons ─────────────────────────────────────────────────── */
.btn {
  font-family: var(--font-display); font-size: 0.86rem; font-weight: 500;
  padding: 12px 14px; min-height: 50px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  cursor: pointer; width: 100%;
  transition: background 160ms ease, border-color 160ms ease, transform 90ms ease;
}
.btn.primary { background: var(--accent); border-color: var(--accent); color: hsl(228,40%,8%); font-weight: 700; }
.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.32; cursor: default; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .btn:not(:disabled):hover { border-color: var(--accent-dim); }
  .btn.primary:not(:disabled):hover { background: hsl(185,70%,62%); }
}

/* ── start screen ────────────────────────────────────────────── */
.hero { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 0 18px 6px; }
.hero .pk { width: 108px; }
.hero h1 { margin: 0; font-family: var(--font-display); font-size: 1.65rem; font-weight: 600;
  letter-spacing: -0.015em; text-align: center; line-height: 1.15; }
.hero p { margin: 0; font-size: 0.92rem; line-height: 1.55; color: var(--muted);
  text-align: center; max-width: 320px; text-wrap: pretty; }
.actions { display: flex; flex-direction: column; gap: 10px; padding: 16px 18px 0; width: 100%; max-width: 360px; margin: 0 auto; }
.foot-note { margin: 14px auto 0; padding: 0 24px; font-size: 0.78rem; line-height: 1.55;
  color: var(--dim); text-align: center; max-width: 340px; text-wrap: pretty; }

.code-box { display: flex; flex-direction: column; align-items: center; gap: 6px;
  background: var(--card); border: 1px solid var(--line); border-radius: 20px; padding: 20px; }
.code-label { font-family: var(--font-display); font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--dim); }
.code-value { font-family: var(--font-display); font-size: 2.5rem; font-weight: 700;
  letter-spacing: 0.16em; color: var(--accent); line-height: 1.1; }
#code-input {
  width: 100%; font-family: var(--font-display); font-size: 1.6rem; font-weight: 700;
  letter-spacing: 0.24em; text-align: center; text-transform: uppercase;
  padding: 14px; min-height: 56px; border-radius: 16px;
  border: 1px solid var(--line); background: var(--surface); color: var(--text);
}
#code-input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ── the frame: one header bar, the play area, one tray ───────
   Everything that is not the play area lives in the header or the tray.
   Before this, the back arrow was absolutely positioned, the counters wrapped
   onto a second ragged row, and the status lines floated free at the bottom
   with gaps between them. */
/* Above the legend's scrim, so the button that opened the panel can still be
   pressed to close it again. */
.hud {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  min-height: 48px; padding: 0 2px; position: relative; z-index: 13;
}
.hud-back {
  flex: 0 0 auto; display: grid; place-items: center; width: 44px; height: 44px;
  margin-left: -10px; color: var(--muted); border-radius: 50%; text-decoration: none;
}
.hud-right { margin-left: auto; display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }

.role {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px;
  border-radius: 999px; font-family: var(--font-display); font-size: 0.7rem;
  font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap;
}
.role.walker { background: hsla(30,88%,58%,0.12); border: 1px solid hsla(30,88%,58%,0.34); color: hsl(30,88%,70%); }
.role.mapper { background: hsla(185,70%,55%,0.12); border: 1px solid hsla(185,70%,55%,0.34); color: hsl(185,70%,68%); }

.pill {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  padding: 0 11px; height: 34px; min-width: 34px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface);
  font-family: var(--font-display); font-size: 0.76rem; font-weight: 700;
  white-space: nowrap;
}
/* The two icon-only pills are real buttons, so they carry the 44px target the
   project requires; the read-only count pills stay compact at 34. */
.pill.icon-only { padding: 0; width: 44px; height: 44px; font-size: 0.95rem; }
.pill.k { border-color: hsla(42,95%,62%,0.34); color: hsl(42,95%,70%); }
.pill.f { border-color: hsla(180,85%,78%,0.30); color: hsl(180,70%,80%); }
.pill.s { border-color: hsla(285,62%,68%,0.34); color: hsl(285,62%,76%); }

/* Sits directly under the bar as part of the same block, not floating. */
.objective {
  flex: 0 0 auto; margin: 0; padding: 0 4px 8px;
  font-family: var(--font-display); font-size: 0.9rem; font-weight: 600;
  color: var(--text); text-wrap: pretty;
  border-bottom: 1px solid hsla(220, 20%, 60%, 0.09);
}


/* Everything below the play area, as one panel with even spacing. */
.tray {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px;
  padding: 10px 0 2px; border-top: 1px solid hsla(220, 20%, 60%, 0.09);
}

/* ── walker: the lantern view ────────────────────────────────── */
/* Both play areas are sized in JS from the space actually left over, not by
   CSS percentage or vh maths. max-height:100% was not clamping inside the flex
   column, so the map overlapped the tray on two of three phones. */
.lantern-wrap { flex: 1 1 auto; display: flex; align-items: center; justify-content: center;
  min-height: 0; overflow: hidden; position: relative; }
.lantern {
  position: relative; border-radius: 14px; overflow: hidden; background: hsl(230,32%,5%);
  width: 260px; height: 260px;
}
.cellgrid { position: absolute; inset: 0; }
.cell { position: absolute; }
.cell.wall { border-radius: 2px; }
/* the two solid things that are not plain rock say so with a lit rim */
.cell.solid-moss { border-radius: 3px; box-shadow: inset 0 0 0 2px var(--moss-edge); }
.cell.solid-deep { border-radius: 3px; box-shadow: inset 0 0 0 2px var(--deep-edge); }
.cell.floor { border-radius: 14%; }
.icon { position: absolute; display: grid; place-items: center; z-index: 2;
  filter: drop-shadow(0 0 8px hsla(38,95%,64%,0.5)); pointer-events: none; }
.glow, .mask { position: absolute; pointer-events: none; }
.glow { inset: -34px; border-radius: 30px; z-index: 1; }
/* Must sit ABOVE .icon (z-index 2) or keys, lanterns and fireflies render
   through the darkness and the walker sees things outside their light. */
.mask { inset: 0; border-radius: 14px; z-index: 3; }

.pk-here { position: absolute; z-index: 4; pointer-events: none;
  left: 50%; top: 50%; transform: translate(-50%, -62%); width: 15%; }
.pk-here svg { width: 100%; height: auto; display: block; overflow: visible; }

.step-btn {
  position: absolute; z-index: 5; border: 0; background: transparent; padding: 0;
  cursor: pointer; display: grid; place-items: center;
}
.step-btn span {
  display: grid; place-items: center; width: 100%; height: 100%; border-radius: 999px;
  border: 2px solid hsla(185,70%,55%,0.6); background: hsla(185,70%,55%,0.16);
  color: hsl(185,70%,70%); box-shadow: 0 0 12px hsla(185,70%,55%,0.3);
}
.step-btn.shut span { border-color: hsla(285,62%,68%,0.7); background: hsla(285,62%,68%,0.16); color: hsl(285,62%,78%); }
.step-btn:active span { transform: scale(0.92); }

/* ── the readout: the sentence you say out loud ──────────────── */
.readout { background: hsl(228,22%,13%); border: 1px solid var(--line);
  border-radius: 14px; padding: 12px 14px; display: flex; flex-direction: column; gap: 5px; min-height: 104px; }
.readout .say { margin: 0; font-size: 0.95rem; line-height: 1.42; }
.readout .under { margin: 0; font-size: 0.85rem; line-height: 1.42; color: var(--muted); }
.readout .exits { margin: 0; font-family: var(--font-display); font-size: 0.88rem;
  font-weight: 600; line-height: 1.42; color: var(--accent); }
.msg { margin: 0; min-height: 22px; padding: 0 6px;
  font-size: 0.88rem; line-height: 1.42; color: hsl(38,95%,72%); text-align: center; text-wrap: pretty; }

/* ── mapper: the map ─────────────────────────────────────────── */
.map-wrap { flex: 1 1 auto; display: flex; align-items: center; justify-content: center;
  min-height: 0; overflow: hidden; }
/* Height-led so the map always shrinks to fit the column rather than
   overflowing it and covering the controls above. aspect-ratio derives the
   width, max-width catches the wide-phone case. */
.map {
  position: relative; background: var(--wall); border: 1px solid var(--line);
  border-radius: 12px; overflow: hidden;
  width: 288px; height: 360px;   /* JS overrides both from the free space */
}
/* DIRECT child only. As `.map svg` this also caught every marker glyph inside
   the map and stretched it to fill its parent, which blew the door icons up to
   the size of their 44px touch target: they covered three cells each and
   swamped the maze. */
.map > svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.mk { position: absolute; display: grid; place-items: center; pointer-events: none; z-index: 2; }
.mk.taken { opacity: 0.22; filter: grayscale(1); }
.mk.pk { z-index: 5; }
.mk.pk { position: absolute; }
.mk.pk i { position: absolute; inset: 0; border-radius: 999px; background: var(--pk-body);
  box-shadow: 0 0 0 2px hsla(28,66%,80%,0.35), 0 0 12px hsla(28,66%,80%,0.75); }
.mk.pk svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.mk.ghost i { background: hsla(28,66%,80%,0.32); box-shadow: none; }
.mk.start i { display: block; width: 100%; height: 100%; border-radius: 999px;
  border: 2px solid var(--key); background: hsla(42,95%,62%,0.24); }
.shutter-cell { position: absolute; z-index: 3; border: 0; padding: 0; cursor: pointer;
  background: transparent; display: grid; place-items: center; }
.shutter-cell i { display: grid; place-items: center; border-radius: 2px;
  background: hsla(285,62%,68%,0.30); }
.shutter-cell i svg { display: block; }
/* An open door is drawn ajar, not just faded, so the two states differ in
   shape as well as weight. */
.shutter-cell.open i { background: transparent; opacity: 0.5; transform: perspective(40px) rotateY(38deg); }

/* One action, made obvious. The firefly was the thing nobody could find. */
.fly-btn {
  display: flex; align-items: center; gap: 13px; width: 100%;
  padding: 12px 16px; min-height: 62px; border-radius: 16px; cursor: pointer;
  text-align: left; font-family: var(--font-body);
  border: 1px solid hsla(180,85%,78%,0.34); background: hsla(180,85%,78%,0.07);
  color: var(--text); transition: background 160ms ease, border-color 160ms ease, transform 90ms ease;
}
.fly-btn:active { transform: scale(0.985); }
.fly-btn:disabled { cursor: default; border-color: var(--line); background: var(--surface); }
.fly-btn:focus-visible { outline: 2px solid var(--fly); outline-offset: 2px; }
.fly-ico {
  flex: 0 0 auto; display: grid; place-items: center; width: 38px; height: 38px;
  border-radius: 999px; color: var(--fly); background: hsla(180,85%,78%,0.13);
}
.fly-btn:disabled .fly-ico { color: var(--dim); background: hsla(220,12%,38%,0.12); }
.fly-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fly-text b { font-family: var(--font-display); font-size: 0.9rem; font-weight: 700; }
.fly-btn:not(:disabled) .fly-text b { color: hsl(180,70%,82%); }
.fly-text i { font-style: normal; font-size: 0.78rem; line-height: 1.35; color: var(--muted); }
@media (hover: hover) and (pointer: fine) {
  .fly-btn:not(:disabled):hover { background: hsla(180,85%,78%,0.13); border-color: hsla(180,85%,78%,0.5); }
}

/* One status line does the work the objective + message pair used to. */
.status {
  margin: 0; min-height: 22px; padding: 0 6px;
  font-size: 0.88rem; line-height: 1.4; text-align: center; text-wrap: pretty;
  color: var(--muted);
}
.status.hot { color: hsl(38,95%,74%); }

/* Folded away by default. It was nine items across four lines, permanently. */
.pill.ghost { color: var(--muted); cursor: pointer; font-weight: 600; }
/* The legend button sat among the count pills and read as another stat. Giving
   it the accent makes it read as something you press. */
.pill.ghost.info { color: var(--accent); border-color: hsla(185,70%,55%,0.45);
  background: hsla(185,70%,55%,0.09); }
/* Until it has been opened once, it breathes, so the eye finds it without a
   sentence of instructions taking a bite out of the map. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes infoBreathe {
    0%, 100% { box-shadow: 0 0 0 0 hsla(185,70%,55%,0.45); }
    55%      { box-shadow: 0 0 0 7px hsla(185,70%,55%,0); }
  }
  .pill.ghost.info.unseen { animation: infoBreathe 2200ms ease-out infinite; }
}
.pill.ghost[aria-expanded="true"] { color: hsl(228,40%,8%); background: var(--accent); border-color: var(--accent); }
/* An overlay, not a row. As a flex child it pushed the map out of the column
   and the map then covered the button that opens it. */
.legend {
  position: absolute; z-index: 12;
  left: 12px; right: 12px; bottom: calc(150px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 9px; padding: 14px; margin: 0; border-radius: 16px;
  background: hsl(230, 28%, 12%); border: 1px solid var(--line);
  box-shadow: 0 12px 40px hsla(230, 40%, 3%, 0.7);
  font-size: 0.76rem; color: var(--muted);
  max-height: 60vh; overflow-y: auto;
}
.legend[hidden] { display: none; }
.lg-head { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: -2px -2px 2px; }
.lg-head b { font-family: var(--font-display); font-size: 0.92rem; font-weight: 700; color: var(--text); }
.lg-close { width: 44px; height: 44px; margin: -10px -10px -10px 0; display: grid; place-items: center;
  border: 0; background: transparent; color: var(--muted); cursor: pointer; border-radius: 999px; }
.lg-close:active { color: var(--text); }
.lg-close:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; }
/* Tapping anywhere off the panel closes it. */
.legend-scrim { position: absolute; inset: 0; z-index: 11; background: hsla(230,35%,4%,0.5); }
.legend-scrim[hidden] { display: none; }
.legend span { display: inline-flex; align-items: center; gap: 7px; }
/* Terrain swatches get an edge so the darkest ones do not read as holes. */
.sw { width: 14px; height: 14px; border-radius: 3px; display: inline-block; flex: 0 0 auto;
  border: 1px solid hsla(220, 20%, 70%, 0.28); }
.lg-ico { width: 16px; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.lg-rule { margin: 0 0 4px; padding-bottom: 9px; border-bottom: 1px solid hsla(220,20%,60%,0.12);
  font-size: 0.78rem; line-height: 1.45; color: var(--text); }
.lg-rule b { color: var(--accent); font-weight: 600; }

/* ── partner status ──────────────────────────────────────────── */
.partner { margin: 0; display: flex; align-items: center; justify-content: center; gap: 7px;
  font-family: var(--font-display); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--dim); }
.partner .dot { width: 7px; height: 7px; border-radius: 999px; background: var(--dim); flex: 0 0 auto; }
.partner.on .dot { background: hsl(140,60%,55%); box-shadow: 0 0 8px hsla(140,60%,55%,0.8); }
.partner.off .dot { background: hsl(30,80%,58%); }

/* ── arcade beats ────────────────────────────────────────────── */
@media (prefers-reduced-motion: no-preference) {
  /* Ponoki was sliding from cell to cell with his feet welded on, which read
     as the map moving under a stationary character rather than as walking.
     The feet take turns and the body leans the way you asked him to go. */
  @keyframes footFront { 0%,100% { translate: 0 0; } 32% { translate: 0 -9px; } 60% { translate: 0 0; } }
  @keyframes footBack  { 0%,100% { translate: 0 0; } 62% { translate: 0 -9px; } 88% { translate: 0 0; } }
  .pk-here.is-walking .pk-foot-l { animation: footFront 380ms ease-in-out; }
  .pk-here.is-walking .pk-foot-r { animation: footBack 380ms ease-in-out; }
  @keyframes leanUp    { 0%,100% { translate: 0 0; } 45% { translate: 0 -5px; } }
  @keyframes leanDown  { 0%,100% { translate: 0 0; } 45% { translate: 0 5px; } }
  @keyframes leanLeft  { 0%,100% { translate: 0 0; rotate: 0deg; } 45% { translate: -5px -2px; rotate: -7deg; } }
  @keyframes leanRight { 0%,100% { translate: 0 0; rotate: 0deg; } 45% { translate: 5px -2px; rotate: 7deg; } }
  .pk-here.walk-u { animation: leanUp 380ms ease-in-out; }
  .pk-here.walk-d { animation: leanDown 380ms ease-in-out; }
  .pk-here.walk-l { animation: leanLeft 380ms ease-in-out; }
  .pk-here.walk-r { animation: leanRight 380ms ease-in-out; }
  @keyframes pop { 0% { transform: scale(1); } 45% { transform: scale(1.5); } 100% { transform: scale(1); } }
  .icon.pop { animation: pop 320ms cubic-bezier(0.34,1.56,0.64,1); }
  @keyframes flare { 0% { filter: drop-shadow(0 0 4px hsla(48,100%,78%,0.4)); }
    40% { filter: drop-shadow(0 0 24px hsla(48,100%,78%,1)); }
    100% { filter: drop-shadow(0 0 10px hsla(48,100%,78%,0.7)); } }
  .icon.flare { animation: flare 700ms ease-out; }
  @keyframes shake { 0%,100% { transform: translateX(0); } 20% { transform: translateX(-4px); }
    45% { transform: translateX(4px); } 70% { transform: translateX(-2px); } }
  .lantern.shake { animation: shake 300ms ease-out; }
  @keyframes ringPulse { 0%,100% { transform: scale(1); opacity: 0.9; } 50% { transform: scale(1.16); opacity: 0.5; } }
  .step-btn.hint span { animation: ringPulse 1300ms ease-in-out infinite;
    border-color: var(--key); color: var(--key); background: hsla(42,95%,62%,0.2); }
  @keyframes pingWave { from { transform: scale(0.4); opacity: 0.9; } to { transform: scale(3.4); opacity: 0; } }
  .mk.pk::after { content: ""; position: absolute; inset: 0; border-radius: 999px;
    border: 2px solid var(--pk-body); animation: pingWave 1400ms ease-out infinite; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 1ms !important; animation-duration: 1ms !important;
    animation-iteration-count: 1 !important; }
}

/* ── end screen ──────────────────────────────────────────────── */
.end-card { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 0 18px; }
.end-card h2 { margin: 0; font-family: var(--font-display); font-size: 1.5rem; font-weight: 600; text-align: center; }
.stats { display: flex; gap: 26px; justify-content: center; align-items: flex-end; padding: 0; }
.stats > div { display: flex; flex-direction: column; align-items: center; gap: 1px; min-width: 62px; }
.stats b { font-family: var(--font-display); font-size: 1.5rem; font-weight: 700; color: var(--accent);
  line-height: 1.1; text-align: center; font-variant-numeric: tabular-nums; }
.stats div:first-child b { color: var(--flame); }
.stats span { font-family: var(--font-display); font-size: 0.64rem; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); display: block; text-align: center; }
#pk-end { width: 76px; }
.map.end { width: min(214px, calc(100vw - 96px)); height: auto; aspect-ratio: 24 / 30; }

/* A 568px-tall phone cannot hold the mascot, the stats, the whole route map
   and two buttons at full size. It scrolls rather than clips either way, but
   the whole thing fitting is better than a CTA below the fold. */
@media (max-height: 640px) {
  #pk-end { width: 54px; }
  .end-card h2 { font-size: 1.28rem; }
  .map.end { width: min(168px, calc(100vw - 140px)); }
  .stats b { font-size: 1.25rem; }
  #screen-end { gap: 7px; }
  .end-card { gap: 6px; }
}
.end-note { margin: 0; font-size: 0.82rem; color: var(--dim); text-align: center; }
.route { fill: none; stroke: var(--flame); stroke-width: 2.2; stroke-linecap: round;
  stroke-linejoin: round; opacity: 0.9; }
@media (prefers-reduced-motion: no-preference) {
  .route { stroke-dasharray: var(--len); stroke-dashoffset: var(--len);
    animation: drawRoute 2200ms var(--ease-out, cubic-bezier(0.16,1,0.3,1)) forwards; }
  @keyframes drawRoute { to { stroke-dashoffset: 0; } }
}

/* ── practice: one phone, both roles ──────────────────────────
   The role-swap pill is fixed to the corner, so the tray reserves its height
   rather than letting it sit on top of the status lines. */
body.practice .tray { padding-bottom: calc(62px + env(safe-area-inset-bottom)); }

/* iOS Safari shrinks 100dvh as its toolbar appears, so a spacer of exactly one
   dvh let the article show under the fixed game. A little slack costs nothing
   and stops the bleed. Specificity beats seo-block.css without editing it. */
body .seo-spacer { height: calc(100dvh + 56px); }

/* While a game screen is up the document does not scroll, so the article can
   never ride up over the board. It stays in the DOM and is reachable from the
   start screen, so nothing is hidden from a crawler. */
html.is-playing, html.is-playing body { overflow: hidden; height: 100%; overscroll-behavior: none; }
