/* 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 {
  --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, ordered by one rule the player can learn in a second:
     ANYTHING DARKER THAN THE FLOOR IS SOLID. ANYTHING LIGHTER IS WALKABLE.
     Moss used to sit at 24% against a 19% floor, which read as "lighter, so
     walk on it" while the rules said the opposite, and it was one of three
     greens at the same lightness. It is now the darkest thing after rock, in
     a blue-green nothing walkable shares, with a lit rim so it reads as a
     raised bank rather than a hole. */
  --wall:      hsl(230, 30%,  8%);   /* solid  */
  --moss:      hsl(162, 55%, 11%);   /* solid  */
  --moss-edge: hsl(158, 52%, 18%);   /* MUST stay below --floor: it is the part of a solid tile the eye lands on */
  --deep:      hsl(202, 58%, 11%);   /* solid  */
  --deep-edge: hsl(198, 50%, 17%);   /* likewise below --floor */
  --floor:     hsl(228, 16%, 22%);   /* the line between the two */
  --reeds:     hsl( 76, 28%, 28%);   /* walkable */
  --fern:      hsl( 96, 32%, 31%);   /* walkable */
  --shallow:   hsl(192, 42%, 29%);   /* walkable */
  --scree:     hsl(230, 12%, 33%);   /* walkable */

  --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. */
.hud {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  min-height: 48px; padding: 0 2px;
}
.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 */
}
.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; }
.pill.ghost[aria-expanded="true"] { color: var(--accent); border-color: var(--accent-dim); }
/* 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; }
.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) {
  @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); }
