/* GENERATED by scripts/build-css.mjs from the other files in css/. Do not edit this file. */

/* ===== tokens.css ===== */
/* =============================================================================
   tokens.css — Design tokens and font loading for PLAYER ONE.
   Change colours, fonts, and the base "pixel" size here. Nothing else in the
   stylesheets hard-codes a palette colour.
   ============================================================================= */

@font-face {
  font-family: 'Press Start 2P';
  src: url('../assets/fonts/press-start-2p-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../assets/fonts/ibm-plex-sans-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../assets/fonts/ibm-plex-sans-latin-600-normal.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Midnight surfaces */
  --void: #070b16;       /* page / deepest background */
  --night: #0d1426;      /* inset areas */
  --panel: #121b33;      /* window background */
  --panel-2: #1a2646;    /* title bars, raised rows */
  --line: #32456f;       /* light window border */
  --ink: #0a0e1a;        /* outer border / outlines */

  /* Accents */
  --teal: #2bb5a0;
  --teal-dim: #187064;   /* 4.7:1 against --cream (text on buttons) */
  --green: #3aa05a;
  --green-dim: #1f6b3a;
  --gold: #e8b84a;       /* earned / achievements */
  --gold-dim: #a8762a;
  --red: #d9534f;        /* warnings / unavailable */
  --red-deep: #b8403c;   /* white text on red (5.4:1) */
  --orange: #e07b39;

  /* Text */
  --cream: #efe6cf;
  --pale: #c3cbdb;
  --muted: #98a4bf;

  /* Type */
  --font-pixel: 'Press Start 2P', 'Courier New', monospace;
  --font-body: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* The base "game pixel". Borders and shadows are multiples of this. */
  --px: 4px;
  --hud-h: 60px;
  --content-max: 1200px;

  /* Comfort options (see comfort.css): every px font size is multiplied by this. */
  --ts-big: 1;
  --ts-read: 1;
  --type-scale: calc(var(--ts-big) * var(--ts-read));
}

@media (max-width: 640px) {
  :root {
    --px: 3px;
    --hud-h: 54px;
  }
}


/* ===== base.css ===== */
/* =============================================================================
   base.css — Reset, typography, accessibility helpers.
   ============================================================================= */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: calc(100% * var(--ts-big));
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--void);
  scroll-behavior: auto;
}

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--void);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

h1, h2, h3, h4, p, ul, ol, dl, dd, figure {
  margin: 0;
}

ul, ol {
  padding: 0;
  list-style: none;
}

a {
  color: var(--teal);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

a:hover {
  color: var(--cream);
}

button {
  font: inherit;
  color: inherit;
}

img, svg {
  display: block;
  max-width: 100%;
}

[hidden] {
  display: none !important;
}

.muted {
  color: var(--muted);
}

/* Pixel sprites stay crisp at any integer scale. */
.sprite {
  image-rendering: pixelated;
  shape-rendering: crispEdges;
}

/* ── Accessibility helpers ─────────────────────────────────── */

.sr-only {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  left: 12px;
  top: -80px;
  z-index: 100;
  padding: 12px 16px;
  background: var(--gold);
  color: var(--ink);
  font-family: var(--font-pixel);
  font-size: calc(11px * var(--type-scale));
  text-decoration: none;
}

.skip-link:focus {
  top: 12px;
}

:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
}

/* Elements focused only by script (headings, panels) do not need a ring. */
[tabindex='-1']:focus {
  outline: none;
}

::selection {
  background: var(--teal-dim);
  color: var(--cream);
}

/* Static fallback shown only when JavaScript is not running. */
.static-fallback {
  max-width: 640px;
  margin: 0 auto;
  padding: 48px 20px;
}

.static-fallback h1,
.static-fallback h2 {
  font-family: var(--font-pixel);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--gold);
  margin: 24px 0 12px;
}

.static-fallback ul {
  list-style: square;
  padding-left: 1.25rem;
}

.static-fallback li {
  margin: 4px 0;
}

.js-enabled .static-fallback {
  display: none;
}

/* ── Reduced motion: everything is shown in its final state ── */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* CALM MOTION option: the same as the device setting, chosen inside the site. */
html.pref-calm *,
html.pref-calm *::before,
html.pref-calm *::after {
  animation: none !important;
  transition: none !important;
  scroll-behavior: auto !important;
}


/* ===== components.css ===== */
/* =============================================================================
   components.css — Reusable retro UI pieces: windows, buttons, tags, badges, inputs.

   The "pixel border" is built from box-shadows offset by multiples of --px.
   Each ring is four offset copies (top/bottom/left/right) of the box, which
   leaves the corners notched like a classic 16-bit dialog window.
   ============================================================================= */

/* ── Window ────────────────────────────────────────────────── */

.win {
  --ring: var(--line);
  position: relative;
  margin: calc(var(--px) * 2);
  background: var(--panel);
  box-shadow:
    inset var(--px) var(--px) 0 0 rgba(255, 255, 255, 0.05),
    inset calc(var(--px) * -1) calc(var(--px) * -1) 0 0 rgba(0, 0, 0, 0.3),
    0 calc(var(--px) * -1) 0 0 var(--ring),
    0 var(--px) 0 0 var(--ring),
    calc(var(--px) * -1) 0 0 0 var(--ring),
    var(--px) 0 0 0 var(--ring),
    0 calc(var(--px) * -2) 0 0 var(--ink),
    0 calc(var(--px) * 2) 0 0 var(--ink),
    calc(var(--px) * -2) 0 0 0 var(--ink),
    calc(var(--px) * 2) 0 0 0 var(--ink);
}

.win-title {
  margin: 0;
  padding: 12px 16px;
  background: var(--panel-2);
  border-bottom: var(--px) solid var(--ink);
  font-family: var(--font-pixel);
  font-size: calc(11px * var(--type-scale));
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.08em;
  color: var(--gold);
}

.win-body {
  padding: 18px 20px 20px;
}

.win-body > * + * {
  margin-top: 12px;
}

.win-body > .sub-label:not(:first-child) {
  margin-top: 20px;
}

.item-body > :not(:first-child),
.quest-body > :not(:first-child) {
  margin-top: 14px;
}

.sub-label {
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  font-weight: 400;
  letter-spacing: 0.08em;
  line-height: 1.6;
  color: var(--teal);
  margin: 0 0 8px;
}

/* ── Screen header ─────────────────────────────────────────── */

.screen-header {
  margin-bottom: 20px;
}

.screen-title {
  font-family: var(--font-pixel);
  font-size: clamp(1.1rem, 3.4vw, 1.75rem);
  font-weight: 400;
  line-height: 1.4;
  color: var(--cream);
  text-shadow: var(--px) var(--px) 0 var(--ink), 0 calc(var(--px) * 2) 0 var(--gold-dim);
}

.screen-subtitle {
  margin-top: 8px;
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  letter-spacing: 0.08em;
  line-height: 1.6;
  color: var(--muted);
}

/* ── Buttons ───────────────────────────────────────────────── */

.btn {
  --btn-bg: var(--teal-dim);
  --btn-ring: var(--ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: var(--px);
  padding: 12px 16px;
  min-height: 44px;
  background: var(--btn-bg);
  border: 0;
  color: var(--cream);
  font-family: var(--font-pixel);
  font-size: calc(11px * var(--type-scale));
  line-height: 1.4;
  letter-spacing: 0.05em;
  text-decoration: none;
  cursor: pointer;
  box-shadow:
    inset 0 calc(var(--px) * -1) 0 0 rgba(0, 0, 0, 0.3),
    inset 0 var(--px) 0 0 rgba(255, 255, 255, 0.15),
    0 calc(var(--px) * -1) 0 0 var(--btn-ring),
    0 var(--px) 0 0 var(--btn-ring),
    calc(var(--px) * -1) 0 0 0 var(--btn-ring),
    var(--px) 0 0 0 var(--btn-ring);
  transition: transform 60ms steps(1, end);
}

.btn .sprite {
  width: calc(var(--px) * 4);
  height: calc(var(--px) * 4);
  flex: none;
}

.btn:hover {
  --btn-bg: var(--teal);
  color: var(--ink);
}

.btn:active {
  transform: translateY(var(--px));
  box-shadow:
    inset 0 var(--px) 0 0 rgba(0, 0, 0, 0.3),
    0 calc(var(--px) * -1) 0 0 var(--btn-ring),
    calc(var(--px) * -1) 0 0 0 var(--btn-ring),
    var(--px) 0 0 0 var(--btn-ring);
}

.btn:focus-visible {
  outline-offset: calc(var(--px) * 2);
}

.btn-ghost {
  --btn-bg: var(--panel-2);
  --btn-ring: var(--line);
}

.btn-ghost:hover {
  --btn-bg: var(--line);
  color: var(--cream);
}

.btn-block {
  display: flex;
  width: calc(100% - var(--px) * 2);
}

.flip {
  transform: scaleX(-1);
}

/* ── Tags & badges ─────────────────────────────────────────── */

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tag {
  display: inline-block;
  padding: 3px 10px;
  background: var(--night);
  border: 2px solid var(--line);
  color: var(--pale);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.5;
}

.badge {
  display: inline-block;
  padding: 4px 8px;
  border: 2px solid currentColor;
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.06em;
  line-height: 1.4;
  white-space: nowrap;
}

.badge-earned,
.badge-completed {
  color: var(--gold);
}

.badge-in-progress {
  color: var(--teal);
}

.badge-planned,
.badge-experimental {
  color: var(--orange);
}

/* ── Forms ─────────────────────────────────────────────────── */

.field {
  margin-bottom: 14px;
}

.field-label {
  display: block;
  margin-bottom: 6px;
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  letter-spacing: 0.06em;
  color: var(--teal);
}

.input {
  width: 100%;
  padding: 10px 12px;
  background: var(--night);
  border: 3px solid var(--line);
  border-radius: 0;
  color: var(--cream);
  font: inherit;
  font-size: 1rem;
}

.input::placeholder {
  color: var(--muted);
}

.input:focus {
  border-color: var(--gold);
  outline: none;
}

.input[aria-invalid='true'] {
  border-color: var(--red);
}

.textarea {
  resize: vertical;
  min-height: 120px;
}

.field-error {
  min-height: 1.25rem;
  margin-top: 4px;
  color: #ff8d88;
  font-size: 0.875rem;
}

.form-status,
.copy-status {
  margin-top: 12px;
  color: var(--pale);
  font-size: 0.9375rem;
}

/* ── Lists ─────────────────────────────────────────────────── */

.bullet-list li {
  position: relative;
  padding-left: 20px;
  margin: 6px 0;
}

.bullet-list li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 0.6em;
  width: 8px;
  height: 8px;
  background: var(--teal);
  box-shadow: 0 0 0 2px var(--ink);
}

.link-list li {
  margin: 4px 0;
}

/* ── Dialog (typed text box) ───────────────────────────────── */

.dialog-window .win-body {
  min-height: 84px;
}

.dialog-speaker {
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  letter-spacing: 0.08em;
  color: var(--teal);
}

.dialog-text {
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--cream);
}

.dialog-text-lg {
  font-size: 1.25rem;
}

.typed::after {
  content: '';
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-left: 8px;
  background: var(--gold);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  animation: blink 1s steps(1, end) infinite;
}

/* ── Shared keyframes ──────────────────────────────────────── */

@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

@keyframes twinkle {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.2; }
}

@keyframes pop {
  0% { transform: scale(1.18); }
  100% { transform: scale(1); }
}

@keyframes slide-in {
  from { transform: translateX(16px); opacity: 0; }
  to { transform: none; opacity: 1; }
}

.return-row {
  margin-top: 28px;
}


/* ===== shell.css ===== */
/* =============================================================================
   shell.css — Persistent application shell: background stage, HUD, transition wipe.
   ============================================================================= */

.app {
  position: relative;
  min-height: 100dvh;
}

/* ── Background stage ──────────────────────────────────────── */

.stage {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  /* Fallback if the generated scene fails: a banded night sky. */
  background: linear-gradient(180deg, #04061a 0%, #0e173d 55%, #223763 80%, #14473f 80%, #0d2b26 100%);
}

.scene {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.stage-dim {
  position: absolute;
  inset: 0;
  background: var(--void);
  opacity: 0;
  transition: opacity 240ms steps(4, end);
}

/* Inner screens dim the scene so panels stay readable. */
.app:not([data-scene='title']):not([data-scene='boot']) .stage-dim {
  opacity: 0.9;
}

/* Scene animations */
.twinkle { animation: twinkle 2.6s steps(1, end) infinite; }
.window-blink { animation: twinkle 3.4s steps(1, end) infinite; }
.cursor-blink { animation: blink 1s steps(1, end) infinite; }
.beacon { animation: blink 1.6s steps(1, end) infinite; }
.hero-frame-a { animation: frame-a 1.2s steps(1, end) infinite; }
.hero-frame-b { animation: frame-b 1.2s steps(1, end) infinite; }

@keyframes frame-a { 0%, 49.9% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes frame-b { 0%, 49.9% { opacity: 0; } 50%, 100% { opacity: 1; } }

/* Save battery: pause the scene whenever it is only a dimmed backdrop. */
.app:not([data-scene='title']) .scene * {
  animation-play-state: paused;
}

/* ── HUD ───────────────────────────────────────────────────── */

.hud {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: var(--hud-h);
  padding: 0 calc(var(--px) * 4);
  background: rgba(7, 11, 22, 0.92);
  border-bottom: var(--px) solid var(--ink);
  box-shadow: 0 var(--px) 0 0 var(--line);
}

.app[data-scene='title'] .hud,
.app[data-scene='boot'] .hud {
  background: transparent;
  border-bottom-color: transparent;
  box-shadow: none;
  pointer-events: none;
}

.app[data-scene='title'] .hud > *,
.app[data-scene='boot'] .hud > * {
  pointer-events: auto;
}

.app[data-scene='title'] .hud-title,
.app[data-scene='boot'] .hud-title {
  visibility: hidden;
}

.hud-title {
  flex: 1;
  text-align: center;
  font-family: var(--font-pixel);
  font-size: calc(11px * var(--type-scale));
  letter-spacing: 0.1em;
  color: var(--gold);
}

.hud-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 8px 12px;
  background: var(--panel-2);
  border: 0;
  color: var(--cream);
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  letter-spacing: 0.06em;
  text-decoration: none;
  cursor: pointer;
  box-shadow:
    0 calc(var(--px) * -1) 0 0 var(--line),
    0 var(--px) 0 0 var(--line),
    calc(var(--px) * -1) 0 0 0 var(--line),
    var(--px) 0 0 0 var(--line);
  margin: var(--px);
}

.hud-btn:hover {
  background: var(--line);
  color: var(--cream);
}

.hud-btn:active {
  transform: translateY(var(--px));
}

.hud-btn[aria-pressed='true'] .sound-state {
  color: var(--teal);
}

.sound-state {
  color: var(--muted);
}

/* Pixel left-pointing arrow drawn with borders */
.hud-arrow {
  width: 0;
  height: 0;
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
  border-right: 8px solid var(--gold);
}

/* The title screen has no back button: keep the sound toggle on the right. */
.app[data-scene='title'] .hud,
.app[data-scene='boot'] .hud {
  justify-content: flex-end;
}

/* ── Main region ───────────────────────────────────────────── */

.screen {
  position: relative;
  z-index: 1;
  min-height: 100dvh;
}

.screen-inner {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: calc(var(--hud-h) + 28px) 24px 72px;
  /* backwards (not both): a lingering transform would trap position:fixed children */
  animation: slide-in 220ms steps(4, end) backwards;
}

@media (max-width: 640px) {
  .screen-inner {
    padding-inline: 14px;
  }
}

/* ── Transition wipe (pixel bars) ──────────────────────────── */

.wipe {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  pointer-events: none;
}

.wipe.is-active {
  pointer-events: all;
}

.wipe i {
  flex: 1;
  background: var(--void);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 200ms steps(5, end);
  transition-delay: calc(var(--i) * 12ms);
  box-shadow: 1px 0 0 0 var(--void);
}

.wipe.is-covering i {
  transform: scaleY(1);
}

.wipe.is-revealing i {
  transform-origin: bottom;
  transform: scaleY(0);
}


/* ===== title.css ===== */
/* =============================================================================
   title.css — The title screen: logo, subtitle, blinking PRESS START.
   Total intro length is about 2 seconds. Reduced motion shows the final state.
   ============================================================================= */

.title {
  position: relative;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding: clamp(48px, 9dvh, 110px) 20px 24px;
  text-align: center;
  animation: title-fade 400ms steps(4, end) backwards;
}

.title-inner {
  width: 100%;
  max-width: 900px;
}

@keyframes title-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ── Logo ──────────────────────────────────────────────────── */

.title-logo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35em;
  margin: 0;
  font-family: var(--font-pixel);
  font-weight: 400;
  font-size: clamp(2.25rem, 11.5vw, min(5.25rem, 11dvh));
  line-height: 1;
  letter-spacing: 0.02em;
}

.logo-line {
  display: block;
  white-space: nowrap;
}

.logo-letter {
  display: inline-block;
  animation: logo-drop 480ms steps(6, end) var(--d, 0s) backwards;
}

@keyframes logo-drop {
  0% { transform: translateY(-140%); opacity: 0; }
  70% { transform: translateY(8%); opacity: 1; }
  100% { transform: translateY(0); opacity: 1; }
}

.logo-line-1 {
  color: var(--gold);
  text-shadow:
    0 var(--px) 0 var(--gold-dim),
    0 calc(var(--px) * 2) 0 var(--ink),
    var(--px) var(--px) 0 var(--ink),
    calc(var(--px) * -1) var(--px) 0 var(--ink),
    var(--px) 0 0 var(--ink),
    calc(var(--px) * -1) 0 0 var(--ink),
    0 calc(var(--px) * -1) 0 var(--ink),
    var(--px) calc(var(--px) * -1) 0 var(--ink),
    calc(var(--px) * -1) calc(var(--px) * -1) 0 var(--ink);
}

.logo-line-2 {
  color: var(--teal);
  text-shadow:
    0 var(--px) 0 var(--teal-dim),
    0 calc(var(--px) * 2) 0 var(--ink),
    var(--px) var(--px) 0 var(--ink),
    calc(var(--px) * -1) var(--px) 0 var(--ink),
    var(--px) 0 0 var(--ink),
    calc(var(--px) * -1) 0 0 var(--ink),
    0 calc(var(--px) * -1) 0 var(--ink),
    var(--px) calc(var(--px) * -1) 0 var(--ink),
    calc(var(--px) * -1) calc(var(--px) * -1) 0 var(--ink);
}

/* ── Subtitle & tagline ────────────────────────────────────── */

.title-sub {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  margin-top: clamp(18px, 3.5dvh, 36px);
  font-family: var(--font-pixel);
  font-size: clamp(0.6875rem, 2.4vw, 1.125rem);
  letter-spacing: 0.22em;
  color: var(--cream);
  text-shadow: var(--px) var(--px) 0 var(--ink);
  animation: title-fade 300ms steps(3, end) 1.45s backwards;
}

.title-sub::before,
.title-sub::after {
  content: '';
  width: clamp(16px, 5vw, 48px);
  height: var(--px);
  background: var(--gold);
  box-shadow: 0 var(--px) 0 0 var(--gold-dim);
}

.title-tag {
  margin-top: 14px;
  font-size: clamp(0.9375rem, 2vw, 1.125rem);
  color: var(--pale);
  text-shadow: 2px 2px 0 var(--ink);
  animation: title-fade 300ms steps(3, end) 1.6s backwards;
}

/* ── PRESS START ───────────────────────────────────────────── */

.press-start {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  margin-top: clamp(20px, 4dvh, 40px);
  padding: 16px 20px;
  min-height: 52px;
  background: rgba(7, 11, 22, 0.72);
  border: 0;
  color: var(--gold);
  font-family: var(--font-pixel);
  font-size: clamp(0.9rem, 3vw, 1.25rem);
  letter-spacing: 0.12em;
  text-shadow: var(--px) var(--px) 0 var(--ink);
  cursor: pointer;
  box-shadow:
    0 calc(var(--px) * -1) 0 0 var(--ink),
    0 var(--px) 0 0 var(--ink),
    calc(var(--px) * -1) 0 0 0 var(--ink),
    var(--px) 0 0 0 var(--ink);
  animation:
    title-fade 1ms linear 1.9s both,
    blink 1.1s steps(1, end) 1.9s infinite;
}

.press-start .sprite {
  width: calc(var(--px) * 4);
  height: calc(var(--px) * 5);
  flex: none;
}

.press-start:hover {
  color: var(--cream);
}

.press-start:focus-visible {
  outline-offset: calc(var(--px) * 2);
  animation: title-fade 1ms linear 1.9s both;
}

.title.is-starting .press-start {
  animation: none;
  color: var(--cream);
}

.title-hint {
  margin-top: 16px;
  font-size: 0.875rem;
  color: var(--muted);
  text-shadow: 2px 2px 0 var(--ink);
  animation: title-fade 300ms steps(3, end) 2s backwards;
}

.title-foot {
  margin-top: auto;
  padding-top: 24px;
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.1em;
  line-height: 1.8;
  color: var(--cream);
  text-shadow: 2px 2px 0 var(--ink);
  position: relative;
  z-index: 2;
}

/* Keep the title block above the ground/terminal on short landscape screens. */
@media (max-height: 520px) {
  .title {
    padding-top: 56px;
  }

  .title-logo {
    flex-direction: row;
    gap: 0.5em;
    font-size: clamp(1.75rem, 8vw, 3.5rem);
  }

  .press-start {
    margin-top: 16px;
  }

  .title-tag,
  .title-hint {
    display: none;
  }
}


/* ===== screens.css ===== */
/* =============================================================================
   screens.css — Main menu, profile, quest log, achievements, contact.
   ============================================================================= */

/* ── Shared: portrait, stat lists ──────────────────────────── */

.portrait-frame {
  flex: none;
  width: calc(var(--px) * 34);
  height: calc(var(--px) * 34);
  display: grid;
  place-items: end center;
  padding: var(--px);
  background: repeating-conic-gradient(var(--panel-2) 0 25%, var(--night) 0 50%) 0 0 / 16px 16px;
  box-shadow:
    0 calc(var(--px) * -1) 0 0 var(--line),
    0 var(--px) 0 0 var(--line),
    calc(var(--px) * -1) 0 0 0 var(--line),
    var(--px) 0 0 0 var(--line);
  margin: var(--px);
}

.portrait {
  width: 100%;
  height: 100%;
}

.portrait-frame-lg {
  width: calc(var(--px) * 40);
  height: calc(var(--px) * 40);
}

.stat-list > div {
  margin-bottom: 10px;
}

.stat-list dt {
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.08em;
  color: var(--teal);
}

.stat-list dd {
  margin-top: 4px;
  color: var(--cream);
  line-height: 1.4;
}

/* ── Dialog window spacing (contact) ───────────────────────── */

.dialog-window {
  margin-top: 20px;
}

/* ── Profile ───────────────────────────────────────────────── */

.profile-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 12px 20px;
  align-items: start;
}

.profile-identity { grid-column: span 5; }
.profile-background { grid-column: span 7; }
.profile-abilities { grid-column: span 7; }
.profile-interests { grid-column: span 5; }
.profile-strengths { grid-column: span 7; }
.profile-goals { grid-column: span 5; }

.profile-id {
  display: flex;
  gap: 18px;
  align-items: center;
  margin-bottom: 16px;
}

.profile-name {
  font-family: var(--font-pixel);
  font-size: calc(13px * var(--type-scale));
  line-height: 1.6;
  color: var(--gold);
}

.profile-alias {
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.875rem;
}

.profile-title {
  margin-top: 8px;
  font-weight: 600;
}

.edu-list {
  display: grid;
  gap: 12px;
}

.edu-list li {
  padding-left: 14px;
  border-left: var(--px) solid var(--teal-dim);
}

.edu-school {
  font-weight: 600;
  color: var(--cream);
}

.ability-group + .ability-group {
  margin-top: 14px;
}

.strength-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 16px;
}

.strength-name {
  font-weight: 600;
  color: var(--gold);
}

.item-empty-title {
  font-family: var(--font-pixel);
  font-size: calc(12px * var(--type-scale));
  letter-spacing: 0.08em;
  color: var(--teal);
}

/* ── Profile: equipment screen ────────────────────────────── */

.view-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 4px 0 14px;
}

.view-tab {
  min-height: 44px;
  padding: 10px 16px;
  margin: var(--px);
  background: var(--panel-2);
  border: 0;
  color: var(--pale);
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  letter-spacing: 0.08em;
  cursor: pointer;
  box-shadow:
    0 calc(var(--px) * -1) 0 0 var(--line),
    0 var(--px) 0 0 var(--line),
    calc(var(--px) * -1) 0 0 0 var(--line),
    var(--px) 0 0 0 var(--line);
}
.view-tab:hover { background: var(--line); color: var(--cream); }
.view-tab[aria-pressed='true'] { background: var(--teal-dim); color: var(--cream); box-shadow: 0 0 0 var(--px) var(--ink), 0 0 0 calc(var(--px) * 2) var(--teal); }

.equip-view[hidden], .profile-grid[hidden] { display: none; }

.ribbon {
  position: relative;
  display: inline-block;
  margin: 4px 0 18px var(--px);
  padding: 10px 40px 10px 18px;
  background: var(--red-deep);
  color: #fff;
  font-family: var(--font-pixel);
  font-size: calc(14px * var(--type-scale));
  line-height: 1.5;
  letter-spacing: 0.06em;
  box-shadow: inset 0 calc(var(--px) * -1) 0 rgba(0, 0, 0, 0.28);
  clip-path: polygon(0 0, 100% 0, calc(100% - 14px) 50%, 100% 100%, 0 100%);
}

.equip {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(250px, 300px) minmax(0, 1fr);
  gap: 12px 16px;
  align-items: start;
}

.equip-middle { display: grid; gap: 12px; align-content: start; }
.equip-middle .win, .hero-card { margin: calc(var(--px) * 2); }

.gear-column { margin: var(--px); }
.gear-list { display: grid; gap: 12px; }
.gear-list li { list-style: none; }

.gear-slot {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: 64px;
  padding: 10px 12px;
  background: var(--night);
  border: 0;
  color: var(--cream);
  text-align: left;
  cursor: pointer;
  box-shadow: inset 0 0 0 3px var(--line);
}
.gear-slot:hover, .gear-slot.is-selected { background: var(--panel-2); box-shadow: inset 0 0 0 3px var(--gold); }

.gear-box {
  display: grid;
  place-items: center;
  flex: none;
  width: 48px;
  height: 48px;
  background: var(--panel-2);
  box-shadow: inset 0 0 0 3px var(--gold-dim);
}
.gear-box .sprite { width: 30px; height: 30px; }

.gear-text { display: grid; gap: 6px; min-width: 0; }
.gear-text small {
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.06em;
  color: var(--muted);
}
.gear-text b { font-weight: 600; font-size: 0.9375rem; line-height: 1.35; }

.hero-card {
  display: grid;
  justify-items: center;
  gap: 6px;
  padding: 18px 14px 20px;
  text-align: center;
  background: radial-gradient(circle at 50% 38%, #25396b, var(--night) 72%);
  box-shadow: inset 0 0 0 var(--px) var(--ink), inset 0 0 0 calc(var(--px) * 2) var(--line);
}
.hero-stage .portrait-frame {
  width: calc(var(--px) * 52);
  height: calc(var(--px) * 52);
  max-width: 100%;
  background: none;
  box-shadow: none;
}
.hero-name {
  margin-top: 8px;
  font-family: var(--font-pixel);
  font-size: calc(13px * var(--type-scale));
  color: var(--gold);
}
.hero-line { font-size: 0.875rem; color: var(--pale); line-height: 1.45; }
.hero-line.muted { color: var(--muted); }

.inspect-body { min-height: 5.5em; display: grid; gap: 8px; align-content: start; font-size: 0.9375rem; line-height: 1.5; }
.inspect-slot { font-family: var(--font-pixel); font-size: calc(9px * var(--type-scale)); letter-spacing: 0.08em; color: var(--teal); }
.inspect-item strong { color: var(--gold); }

.stat-strip-window { margin: calc(var(--px) * 3) var(--px) 0; }
.stat-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}
.stat-strip > div {
  display: flex;
  flex-direction: column-reverse;
  gap: 8px;
  padding: 14px 8px;
  text-align: center;
  background: var(--night);
  box-shadow: inset 0 0 0 3px var(--line);
}
.stat-strip dd { margin: 0; font-family: var(--font-pixel); font-size: calc(18px * var(--type-scale)); color: var(--gold); }
.stat-strip dt { font-size: 0.75rem; letter-spacing: 0.08em; color: var(--pale); }

.gear-inline {
  display: none;
  margin-top: 8px;
  padding: 10px 12px;
  background: var(--night);
  box-shadow: inset 0 0 0 2px var(--teal-dim);
  font-size: 0.9375rem;
  line-height: 1.5;
}
.gear-inline > * + * { margin-top: 6px; }

@media (max-width: 1000px) {
  .equip { grid-template-columns: minmax(0, 1fr); }
  .equip-middle { order: -1; }
  .inspect-window { display: none; }
  .gear-list li.is-open .gear-inline { display: block; }
}
@media (max-width: 560px) {
  .stat-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ribbon { font-size: calc(11px * var(--type-scale)); }
}

/* ── Contact ───────────────────────────────────────────────── */

.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px 20px;
  align-items: start;
  margin-top: 20px;
}

.party-list {
  display: grid;
  gap: 10px;
  margin-bottom: 16px;
}

.party-slot {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 60px;
  padding: 10px 14px;
  background: var(--night);
  border: 3px solid var(--line);
  color: var(--cream);
  text-decoration: none;
}

.party-slot:hover {
  border-color: var(--gold);
  background: var(--panel-2);
  color: var(--cream);
}

.party-icon .sprite {
  width: calc(var(--px) * 8);
  height: calc(var(--px) * 8);
}

.party-text {
  display: grid;
  min-width: 0;
}

.party-text strong {
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  letter-spacing: 0.08em;
  font-weight: 400;
  color: var(--teal);
}

.party-text small {
  font-size: 1rem;
  overflow-wrap: anywhere;
}

/* ── Responsive ────────────────────────────────────────────── */

/* ── Contact: post office ─────────────────────────────────── */

.post-grid { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
.post-side { display: grid; gap: 12px; align-content: start; }
.post-side .win { margin: calc(var(--px) * 2); }

/* The letter: a parchment sheet inside the dark window. */
.letter {
  --ink-text: #2a2218;
  position: relative;
  padding: 18px 20px 20px;
  background: #efe6cf;
  color: var(--ink-text);
  box-shadow: inset 0 0 0 3px #cdbf9e, inset 0 0 0 6px #efe6cf, inset 0 0 0 8px #cdbf9e;
}
.letter-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.letter-to { font-weight: 600; font-size: 0.9375rem; line-height: 1.5; }
.letter-to span { font-family: var(--font-pixel); font-size: calc(9px * var(--type-scale)); letter-spacing: 0.06em; color: #6a3a34; }
.letter-stamp {
  display: grid;
  place-items: center;
  flex: none;
  width: 52px;
  height: 60px;
  background: var(--teal-dim);
  outline: 3px dotted #efe6cf;
  outline-offset: -5px;
  box-shadow: 0 0 0 2px #8a6a4a;
}
.letter-stamp .sprite { width: 28px; height: 28px; }
.letter .field-label, .letter legend.field-label { color: #6a3a34; padding: 0; }
.letter .input { background: #fffaf0; border-color: #8a6a4a; color: var(--ink-text); }
.letter .input:focus { border-color: var(--teal-dim); outline: 3px solid rgba(24, 112, 100, 0.45); }
.letter .input[aria-invalid='true'] { border-color: #a63c39; }
.letter .field-error { color: #a63c39; font-weight: 600; }
.letter .form-status { color: var(--ink-text); }

.topic-group { margin: 0 0 16px; padding: 0; border: 0; min-width: 0; }
.topic-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.topic { position: relative; cursor: pointer; }
.topic input { position: absolute; opacity: 0; inset: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.topic span {
  display: inline-block;
  padding: 9px 12px;
  background: #fffaf0;
  border: 3px solid #8a6a4a;
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.05em;
  line-height: 1.4;
  color: var(--ink-text);
}
.topic:hover span { border-color: var(--teal-dim); }
.topic input:checked + span { background: var(--teal-dim); border-color: var(--ink); color: #fff; box-shadow: 2px 2px 0 var(--ink); }
.topic input:focus-visible + span { outline: 3px solid var(--ink); outline-offset: 2px; }

.postmark {
  position: absolute;
  top: 16px;
  right: 86px;
  padding: 6px 12px;
  border: 4px solid #a63c39;
  color: #a63c39;
  font-family: var(--font-pixel);
  font-size: calc(14px * var(--type-scale));
  letter-spacing: 0.1em;
  transform: rotate(-12deg);
  opacity: 0;
  pointer-events: none;
}
.letter.is-posted .postmark { opacity: 0.85; animation: stamp-in 240ms steps(4, end) backwards; }
@keyframes stamp-in { from { transform: rotate(-12deg) scale(1.8); opacity: 0; } to { transform: rotate(-12deg) scale(1); opacity: 0.85; } }

/* Links as stamps */
.stamp-slot { box-shadow: inset 0 0 0 3px var(--line); }
.stamp-slot:hover, .stamp-slot:focus-visible { box-shadow: inset 0 0 0 3px var(--gold); }

@media (max-width: 859px) {
  .post-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 1000px) {
  .profile-grid {
    grid-template-columns: 1fr;
  }

  .profile-identity,
  .profile-background,
  .profile-abilities,
  .profile-interests,
  .profile-strengths,
  .profile-goals {
    grid-column: auto;
  }
}

@media (max-width: 859px) {
  .contact-grid {
    grid-template-columns: 1fr;
  }

  .strength-list {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 480px) {
  .profile-id {
    flex-direction: column;
    align-items: flex-start;
  }

  .win-body {
    padding: 14px;
  }
}


/* ===== skilltree.css ===== */
/* =============================================================================
   skilltree.css — Certification skill tree: radial graph, compact list, item window.

   The graph uses a fixed aspect ratio (1000 × 650) with percent-based node
   positions, and the SVG rail layer uses the same viewBox, so rails always meet
   their nodes at any width. Node size is fixed in pixels so nodes never shrink
   into unreadable dots; narrow screens use the list instead.
   ============================================================================= */

/* Colour families. Meaning never relies on colour alone: every node also has a
   glyph, a text label, and a status word (and a star when earned). */
.cat-web     { --accent: #5aa0e8; --fill: #1f3a66; --rail: #3d6fb0; }
.cat-data    { --accent: #4bc47a; --fill: #1c4a2e; --rail: #2f8a52; }
.cat-support { --accent: #e07b9a; --fill: #5a2338; --rail: #a8506a; }
.cat-digital { --accent: #35c7d9; --fill: #164a52; --rail: #25808c; }

.tree-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}

/* Side-by-side only when the tree still gets its full width. */
.skills-screen { max-width: 1440px; }

@media (min-width: 1400px) {
  .tree-layout {
    grid-template-columns: minmax(0, 1fr) 360px;
  }

  .item-window {
    position: sticky;
    top: calc(var(--hud-h) + 24px);
  }
}

.is-earned { --c: var(--gold); }
.is-in-progress { --c: var(--teal); }
.is-planned { --c: #55648a; }

.legend-note {
  margin: 0;
  font-family: var(--font-body);
  font-size: 0.875rem;
  letter-spacing: 0;
  color: var(--muted);
}

.legend-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  flex: none;
  background: var(--panel-2);
  box-shadow: 0 0 0 3px var(--c, var(--line));
}

/* ── Stage: dark circuit board ─────────────────────────────── */

.tree-stage {
  position: relative;
  padding: 0;
  background:
    linear-gradient(rgba(80, 104, 160, 0.09) 1px, transparent 1px) 0 0 / 32px 32px,
    linear-gradient(90deg, rgba(80, 104, 160, 0.09) 1px, transparent 1px) 0 0 / 32px 32px,
    radial-gradient(circle, rgba(152, 164, 191, 0.2) 1.5px, transparent 1.6px) 16px 16px / 32px 32px,
    #080c17;
}

/* Title tab and button hints */
.tree-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 14px 0 0;
  border-bottom: var(--px) solid var(--ink);
  background: rgba(7, 11, 22, 0.6);
}

.tree-tab {
  padding: 12px 26px 12px 18px;
  background: var(--panel-2);
  color: var(--cream);
  font-family: var(--font-pixel);
  font-size: calc(11px * var(--type-scale));
  letter-spacing: 0.1em;
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 100%, 0 100%);
}

.tree-bar-actions {
  display: flex;
  gap: 8px;
}

.tbtn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 34px;
  padding: 6px 10px;
  background: var(--panel-2);
  border: 0;
  color: var(--cream);
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.06em;
  cursor: pointer;
  box-shadow: inset 0 0 0 2px var(--line);
}

.tbtn:hover { background: var(--line); }

kbd {
  display: inline-block;
  min-width: 18px;
  padding: 3px 5px;
  background: var(--night);
  color: var(--gold);
  font-family: var(--font-pixel);
  font-size: 8px;
  text-align: center;
  box-shadow: inset 0 0 0 2px var(--ink), 0 2px 0 0 var(--ink);
}

.tree-help {
  position: absolute;
  z-index: 6;
  top: 52px;
  right: 14px;
  width: min(300px, calc(100% - 28px));
  padding: 14px 16px;
  background: var(--panel);
  box-shadow: 0 0 0 3px var(--line), 0 0 0 6px var(--ink);
}

.tree-help[hidden] { display: none; }

.tree-help-title {
  margin: 0 0 10px;
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  letter-spacing: 0.08em;
  color: var(--gold);
}

.tree-help ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.tree-help li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; font-size: 0.875rem; color: var(--pale); }

/* Bottom-left chip: counts straight from the data */
.tree-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 20px;
  padding: 0 16px 14px;
}

.tree-chip {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  margin: 0;
  padding: 8px 12px;
  list-style: none;
  background: var(--panel);
  box-shadow: inset 0 0 0 2px var(--line);
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.06em;
  color: var(--pale);
}

.tree-chip li { display: flex; align-items: center; gap: 8px; }
.tree-chip b { color: var(--gold); font-weight: 400; }

/* ── Graph ─────────────────────────────────────────────────── */

.tree-viewport {
  overflow-x: auto;
  padding: 24px 12px 16px;
}

.tree-canvas {
  position: relative;
  aspect-ratio: 1000 / 650;
  min-width: 880px;
  max-width: 1100px;
  margin-inline: auto;
}

.tree-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.rail-casing {
  stroke: var(--ink);
  stroke-width: 13;
  stroke-linecap: square;
  shape-rendering: crispEdges;
}

.edge {
  stroke: var(--rail, var(--line));
  stroke-width: 5;
  stroke-linecap: butt;
  stroke-linejoin: miter;
  shape-rendering: crispEdges;
}

.edge-in-progress { stroke-dasharray: 12 6; }
.edge-planned { stroke: #2d3b5e; stroke-dasharray: 8 8; }
.edge-stub { stroke: #2d3b5e; stroke-width: 4; stroke-dasharray: none; }
.edge.is-lit { stroke: var(--gold); }

/* Junction diamonds in the middle of each rail */
.tjoint {
  position: absolute;
  width: 11px;
  height: 11px;
  transform: translate(-50%, -50%) rotate(45deg);
  background: var(--rail);
  box-shadow: 0 0 0 3px var(--ink);
  pointer-events: none;
}

/* ── Nodes ─────────────────────────────────────────────────── */

.tnode {
  position: absolute;
  width: 80px;
  height: 80px;
  display: grid;
  place-items: center;
  padding: 0;
  transform: translate(-50%, -50%);
  background: none;
  border: 0;
  color: var(--cream);
}

button.tnode { cursor: pointer; }

/* The diamond: a rotated square with bevel and layered metal rings. */
.tframe {
  --size: 48px;
  --r1: 3px;
  --r2: 3px;
  --r3: 3px;
  --r4: 2px;
  --metal: #8892ad;
  position: relative;
  display: grid;
  place-items: center;
  width: var(--size);
  height: var(--size);
  background: var(--fill, var(--panel-2));
  transform: rotate(45deg);
  box-shadow:
    inset 3px 3px 0 0 rgba(255, 255, 255, 0.22),
    inset -3px -3px 0 0 rgba(0, 0, 0, 0.35),
    0 0 0 var(--r1) var(--accent, var(--line)),
    0 0 0 calc(var(--r1) + var(--r2)) var(--ink),
    0 0 0 calc(var(--r1) + var(--r2) + var(--r3)) var(--metal),
    0 0 0 calc(var(--r1) + var(--r2) + var(--r3) + var(--r4)) var(--ink);
}

.tgem {
  transform: rotate(-45deg);
  font-family: var(--font-pixel);
  font-size: 11px;
  line-height: 1;
  color: var(--cream);
  text-shadow: 2px 2px 0 var(--ink);
}

.tgem::before { content: attr(data-glyph); }
.tgem-long { font-size: 8px; }

.tframe-sm { --size: 26px; --r1: 2px; --r2: 2px; --r3: 0px; --r4: 0px; }
.tframe-sm .tgem { font-size: 8px; }
.tframe-sm .tgem-long { font-size: 6px; }
.tframe-md { --size: 34px; --r3: 0px; --r4: 0px; }
.tframe-md .tgem { font-size: 9px; }
.tframe-md .tgem-long { font-size: 7px; }

/* Status looks */
.is-planned .tframe { --accent: #55648a; --fill: var(--night); --metal: #46506c; }
.is-planned .tgem { color: var(--muted); }
.is-in-progress .tframe { animation: frame-glow 1.2s steps(2, end) infinite; }
.is-earned .tgem { color: var(--cream); }

@keyframes frame-glow {
  0%, 100% { filter: none; }
  50% { filter: brightness(1.5); }
}

button.tnode:hover .tframe,
button.tnode:focus-visible .tframe { --fill: color-mix(in srgb, var(--accent) 55%, #0d1426); }

button.tnode:focus-visible { outline: none; }
button.tnode:focus-visible .tframe { outline: 3px solid #fff; outline-offset: 16px; }

.tnode.is-selected .tframe { --fill: var(--gold-dim); --accent: var(--gold); }
.tnode.is-selected .tgem { color: var(--cream); }
.tnode.just-selected .tframe { animation: frame-pop 240ms steps(3, end); }

@keyframes frame-pop {
  0% { transform: rotate(45deg) scale(1.2); }
  100% { transform: rotate(45deg) scale(1); }
}

.tnode-star {
  position: absolute;
  top: 2px;
  right: 2px;
  z-index: 1;
  animation: twinkle 3s steps(1, end) infinite;
}

.tnode-star .sprite { width: 20px; height: 20px; }

.tnode-label {
  position: absolute;
  top: calc(50% + 62px);
  left: 50%;
  width: 112px;
  transform: translateX(-50%);
  margin: 0;
  padding: 2px 4px;
  background: rgba(7, 11, 22, 0.7);
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
  color: var(--cream);
  text-shadow: 2px 2px 0 var(--ink);
}

.label-up .tnode-label {
  top: auto;
  bottom: calc(50% + 62px);
}

.tnode-state {
  display: block;
  margin-top: 4px;
  font-family: var(--font-pixel);
  font-size: 8px;
  font-weight: 400;
  letter-spacing: 0.06em;
  color: var(--muted);
}

/* Branch start nodes: smaller, no metal ring */
.tnode-branch { width: 64px; height: 64px; }

.tnode-branch .tframe {
  --size: 30px;
  --r3: 0px;
  --r4: 0px;
}

.tnode-branch .tgem { font-size: 8px; }
.tnode-branch .tgem-long { font-size: 7px; }

.tnode-branch .tnode-label {
  top: calc(50% + 46px);
  width: 150px;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
}

.tnode-branch.label-up .tnode-label {
  top: auto;
  bottom: calc(50% + 46px);
}

/* The hub: a round player medallion */
.tnode-root { width: 88px; height: 88px; }

.tframe-hub {
  --size: 64px;
  --accent: var(--gold);
  --fill: #14203d;
  transform: none;
  border-radius: 50%;
  overflow: hidden;
  align-items: end;
}

.tframe-hub .sprite { width: 28px; height: 44px; margin-bottom: 2px; }

.tnode-root .tnode-label {
  top: calc(50% + 56px);
  width: auto;
  padding: 3px 8px;
  background: #080c17;
  white-space: nowrap;
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.06em;
  color: var(--gold);
}

/* The orange selection diamond */
.tree-cursor {
  position: absolute;
  z-index: 3;
  width: 74px;
  height: 74px;
  display: none;
  transform: translate(-50%, -50%) rotate(45deg);
  border: 4px solid #f08a2c;
  box-shadow: 0 0 0 3px var(--ink), inset 0 0 0 3px var(--ink);
  pointer-events: none;
  transition: left 160ms steps(5, end), top 160ms steps(5, end);
  animation: cursor-pulse 900ms steps(2, end) infinite;
}

.tree-cursor.is-on { display: block; }

@keyframes cursor-pulse {
  0%, 100% { border-color: #f08a2c; }
  50% { border-color: #ffc27a; }
}

/* ── Compact (mobile) list ─────────────────────────────────── */

.tree-list {
  display: none;
}

.branch + .branch { margin-top: 22px; }

.branch-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: 0.05em;
  color: var(--accent);
}

.lnode-mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
}

.tframe-branch { --r3: 0px; --r4: 0px; }

.branch-nodes {
  position: relative;
  margin-left: 27px;
  padding-left: 22px;
  border-left: 5px solid var(--rail);
}

.branch-nodes li {
  position: relative;
  padding: 5px 0;
}

.branch-nodes li::before {
  content: '';
  position: absolute;
  left: -22px;
  top: 50%;
  width: 18px;
  height: 5px;
  background: var(--rail);
}

.lnode {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 64px;
  padding: 4px 10px 4px 2px;
  text-align: left;
  background: var(--panel);
  border: 3px solid var(--line);
  cursor: pointer;
}

.lnode.is-selected {
  border-color: var(--gold);
  background: var(--panel-2);
}

.lnode.is-selected .tframe { --fill: var(--gold-dim); --accent: var(--gold); }

.lnode-text {
  display: grid;
  flex: 1;
  min-width: 0;
}

.lnode-text strong { font-weight: 600; line-height: 1.3; }
.lnode-text small { color: var(--muted); font-size: 0.8125rem; }

.lnode-status {
  font-family: var(--font-pixel);
  font-size: 8px;
  letter-spacing: 0.05em;
  color: var(--gold);
}

.lnode-status-in-progress { color: var(--teal); }
.lnode-status-planned { color: var(--orange); }

/* ── Item window (detail panel) ────────────────────────────── */

.item-window {
  min-height: 280px;
}

.item-window.is-open {
  --ring: var(--gold);
  animation: slide-in 220ms steps(4, end) backwards;
}

.item-head {
  display: flex;
  gap: 16px;
  align-items: center;
}

.item-gem {
  flex: none;
  display: grid;
  place-items: center;
  width: 76px;
  height: 76px;
}

.item-name {
  margin-bottom: 6px;
  font-family: var(--font-pixel);
  font-size: 0.8125rem;
  font-weight: 400;
  line-height: 1.6;
  color: var(--gold);
}

.item-rows > div {
  display: flex;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 2px dashed var(--line);
}

.item-rows dt {
  flex: none;
  width: 110px;
  padding-top: 3px;
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.06em;
  color: var(--teal);
}

.item-rows dd {
  min-width: 0;
  overflow-wrap: anywhere;
}

.item-desc {
  color: var(--pale);
}

.item-warn {
  padding: 8px 10px;
  background: var(--night);
  border-left: var(--px) solid var(--orange);
  font-size: 0.9375rem;
}

.item-actions {
  display: none;
}

.sheet-backdrop {
  display: none;
}

/* ── Small screens: list + bottom sheet ────────────────────── */

@media (max-width: 959px) {
  .tree-viewport,
  .tree-bar,
  .tree-help {
    display: none;
  }

  .tree-stage {
    padding: 16px 12px;
  }

  .tree-footer {
    padding: 18px 0 0;
  }

  .tree-list {
    display: block;
  }

  .item-window {
    display: none;
    position: fixed;
    left: 14px;
    right: 14px;
    bottom: 14px;
    z-index: 45;
    max-height: 78dvh;
    margin: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .item-window.is-open {
    display: block;
    animation: sheet-in 240ms steps(5, end) backwards;
  }

  .item-actions {
    display: block;
  }

  body.sheet-open .sheet-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 44;
    background: rgba(7, 11, 22, 0.78);
  }

  body.sheet-open {
    overflow: hidden;
  }

  .item-rows dt {
    width: 96px;
  }
}

@keyframes sheet-in {
  from { transform: translateY(24px); opacity: 0; }
  to { transform: none; opacity: 1; }
}


/* ===== book.css ===== */
/* =============================================================================
   book.css — The QUEST LOG as an open book.
   Left page: quest list. Right page: the selected quest. Bookmark tabs filter by
   status. Parchment colours are local to this file; they are the only place the
   site leaves the midnight palette.
   ============================================================================= */

.book {
  --page: #ecdab4;
  --page-2: #e0c796;
  --page-edge: #c9a874;
  --page-row: #dcc08e;
  --page-row-hi: #d1ac70;
  --page-ink: #4a3320;
  --page-ink-2: #5a3f27;
  --page-accent: #7a4a12;
  --book-frame: #2c3347;
  --book-frame-hi: #5b6785;
  --tab-all: #c0473f;
  --tab-completed: #4f9a58;
  --tab-in-progress: #4f86c6;
  --tab-experimental: #a04a9c;

  position: relative;
  margin-top: 12px;
  padding: calc(var(--px) * 4);
  background: var(--book-frame);
  box-shadow:
    0 calc(var(--px) * -1) 0 0 var(--ink),
    0 var(--px) 0 0 var(--ink),
    calc(var(--px) * -1) 0 0 0 var(--ink),
    var(--px) 0 0 0 var(--ink),
    inset 0 0 0 var(--px) var(--book-frame-hi);
  margin-inline: var(--px);
}

/* Stone corner brackets */
.book-corner {
  position: absolute;
  z-index: 3;
  width: calc(var(--px) * 9);
  height: calc(var(--px) * 9);
  background: #6c7893;
  box-shadow: inset 0 0 0 var(--px) var(--ink), inset calc(var(--px) * 2) calc(var(--px) * 2) 0 0 #8f9ab4;
}

.book-corner::after {
  content: '';
  position: absolute;
  inset: calc(var(--px) * 3);
  background: var(--book-frame);
  box-shadow: inset 0 0 0 var(--px) var(--ink);
}

.book-corner-tl { top: calc(var(--px) * -2); left: calc(var(--px) * -2); }
.book-corner-tr { top: calc(var(--px) * -2); right: calc(var(--px) * -2); }
.book-corner-bl { bottom: calc(var(--px) * -2); left: calc(var(--px) * -2); }
.book-corner-br { bottom: calc(var(--px) * -2); right: calc(var(--px) * -2); }

/* ── The two pages ─────────────────────────────────────────── */

.book-spread {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
  height: clamp(560px, calc(100dvh - 230px), 720px);
  background: var(--page);
  box-shadow: 0 0 0 var(--px) #7b4a2e, 0 0 0 calc(var(--px) * 2) var(--ink);
  color: var(--page-ink);
  /* Pixel-stepped shadow down the middle (the spine) */
  background-image: linear-gradient(90deg,
    transparent calc(48% - 24px), rgba(110, 70, 30, 0.08) calc(48% - 24px), rgba(110, 70, 30, 0.08) calc(48% - 16px),
    rgba(110, 70, 30, 0.16) calc(48% - 16px), rgba(110, 70, 30, 0.16) calc(48% - 8px),
    rgba(110, 70, 30, 0.28) calc(48% - 8px), rgba(110, 70, 30, 0.28) 48%,
    transparent 48%);
}

.book-spread::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(48% - 2px);
  width: calc(var(--px) * 1.5);
  background: #8a5a36;
  pointer-events: none;
}

.page {
  position: relative;
  min-width: 0;
  min-height: 0;
  padding: 20px 22px 24px;
  overflow-y: auto;
  scrollbar-color: #a87d4a #e0c796;
  scrollbar-width: auto;
}

.page::-webkit-scrollbar { width: 12px; }
.page::-webkit-scrollbar-track { background: var(--page-2); box-shadow: inset 0 0 0 2px var(--page-edge); }
.page::-webkit-scrollbar-thumb { background: #a87d4a; box-shadow: inset 0 0 0 2px #7b4a2e; }

.page-left { padding-right: 30px; }
.page-right { padding-left: 30px; }

/* Text defaults on parchment */
.page p, .page li, .page dd { color: var(--page-ink); }
.page .muted { color: var(--page-ink-2); }
.page .sub-label { color: var(--page-accent); }

/* ── Ribbon title ──────────────────────────────────────────── */

.book-ribbon {
  position: relative;
  margin: 4px 14px 18px;
  padding: 12px 18px;
  text-align: center;
  font-family: var(--font-pixel);
  font-size: clamp(0.9rem, 1.8vw, 1.25rem);
  letter-spacing: 0.12em;
  color: #7a4f2d;
  background: var(--page-row);
  clip-path: polygon(0 12%, 4% 12%, 4% 0, 96% 0, 96% 12%, 100% 12%, 100% 88%, 96% 88%, 96% 100%, 4% 100%, 4% 88%, 0 88%);
  text-shadow: 2px 2px 0 rgba(255, 245, 220, 0.6);
}

/* ── Quest rows ────────────────────────────────────────────── */

.quest-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}

.quest-empty {
  padding: 16px;
  color: var(--page-ink-2);
  font-style: italic;
}

.quest-item {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  width: 100%;
  min-height: 60px;
  padding: 8px 12px 8px 14px;
  text-align: left;
  color: var(--page-ink);
  background: var(--page-row);
  border: 0;
  box-shadow: inset 0 0 0 2px var(--page-edge);
  cursor: pointer;
}

.quest-item:hover { background: #d6b985; }

.quest-item.is-selected {
  background: var(--page-row-hi);
  box-shadow: inset 0 0 0 2px #8a5a36;
}

/* Red selection arrow, drawn with borders */
.quest-item.is-selected::before {
  content: '';
  position: absolute;
  left: -16px;
  top: 50%;
  margin-top: -7px;
  border-top: 7px solid transparent;
  border-bottom: 7px solid transparent;
  border-left: 9px solid #c0473f;
}

.quest-item:focus-visible { outline: 3px solid var(--page-accent); outline-offset: 2px; }

.quest-icon {
  display: grid;
  place-items: center;
  width: calc(var(--px) * 11);
  height: calc(var(--px) * 11);
  background: var(--page);
  box-shadow: inset 0 0 0 2px #8a5a36;
}

.quest-icon .sprite { width: calc(var(--px) * 7); height: calc(var(--px) * 7); }
.quest-icon-lg { width: calc(var(--px) * 14); height: calc(var(--px) * 14); flex: none; }
.quest-icon-lg .sprite { width: calc(var(--px) * 9); height: calc(var(--px) * 9); }

.quest-text { display: grid; min-width: 0; }
.quest-text strong { font-weight: 600; font-size: 1rem; color: var(--page-ink); overflow-wrap: anywhere; }
.quest-text small { color: var(--page-ink-2); font-size: 0.8125rem; line-height: 1.35; }

.quest-state {
  display: grid;
  place-items: center;
  width: calc(var(--px) * 8);
  height: calc(var(--px) * 8);
  background: var(--page);
  box-shadow: inset 0 0 0 2px var(--page-edge);
}

.quest-state .sprite { width: calc(var(--px) * 5); height: calc(var(--px) * 5); }

/* ── Bookmark tabs ─────────────────────────────────────────── */

.book-tabs {
  position: absolute;
  z-index: 2;
  top: 64px;
  right: calc(var(--px) * -9);
  display: grid;
  gap: 10px;
}

.book-tab {
  display: flex;
  align-items: center;
  gap: 8px;
  writing-mode: vertical-rl;
  padding: 12px 6px 18px;
  min-height: 48px;
  color: #fff;
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.1em;
  text-shadow: 1px 1px 0 rgba(10, 14, 26, 0.7);
  background: var(--tab-all);
  border: 0;
  cursor: pointer;
  /* Notched ribbon end */
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 8px), 50% 100%, 0 calc(100% - 8px));
  box-shadow: inset 0 0 0 2px rgba(10, 14, 26, 0.5);
  transform: translateX(-6px);
  transition: transform 120ms steps(3, end);
}

.book-tab[data-filter='completed'] { background: var(--tab-completed); }
.book-tab[data-filter='in-progress'] { background: var(--tab-in-progress); }
.book-tab[data-filter='experimental'] { background: var(--tab-experimental); }

.book-tab:hover { transform: translateX(0); }
.book-tab[aria-pressed='true'] { transform: translateX(4px); box-shadow: inset 0 0 0 3px #fff3d6; }
.book-tab:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }

.book-tab-count { opacity: 0.85; }

/* ── Right page ────────────────────────────────────────────── */

.quest-detail:focus-visible { outline: 3px solid var(--page-accent); outline-offset: -6px; }

.quest-body { display: grid; gap: 14px; }

.book-art {
  display: block;
  padding: 6px;
  background: var(--page-2);
  box-shadow: inset 0 0 0 3px #8a5a36, inset 0 0 0 5px var(--page);
}

.book-art-svg { display: block; width: 100%; height: auto; }

.book-shots { display: flex; gap: 8px; overflow-x: auto; }
.shot { max-height: 220px; width: auto; }

.quest-head { display: flex; gap: 14px; align-items: center; }

.quest-name {
  margin: 0 0 4px;
  font-family: var(--font-pixel);
  font-size: clamp(0.8125rem, 1.8vw, 1.0625rem);
  line-height: 1.5;
  color: #6a3f14;
}

.quest-note {
  margin: 0;
  padding: 10px 12px;
  background: var(--page-2);
  border-left: var(--px) solid #c0702a;
  font-size: 0.9375rem;
}

.quest-section { display: grid; gap: 6px; }
.quest-section p { margin: 0; }
.quest-section .sub-label { margin: 6px 0 0; }

.quest-links { display: flex; flex-wrap: wrap; gap: 4px; margin: calc(var(--px) * -1); }
.quest-back { display: none; }

/* Components restyled for parchment */
.book .tag { background: var(--page-row); color: var(--page-ink); box-shadow: inset 0 0 0 2px #8a5a36; }
.book .badge { box-shadow: inset 0 0 0 2px var(--page-ink); }
.book .badge-completed { background: #8cc78f; color: #17361b; }
.book .badge-in-progress { background: #f1cd78; color: #4a3207; }
.book .badge-experimental { background: #d9aee0; color: #3a1740; }
.book .bullet-list li::before { color: var(--page-accent); }
.book .link-list a { color: #1f4f8f; }
.book .item-empty-title { color: var(--page-accent); }

/* Page turn: the right page wipes in from the spine */
.quest-detail.just-opened .quest-body { animation: page-turn 260ms steps(5, end) backwards; }

@keyframes page-turn {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}

/* ── Tablet / phone: one page at a time, tabs along the top ── */

@media (max-width: 859px) {
  .book { padding: calc(var(--px) * 3); }
  .book-corner { display: none; }

  .book-tabs {
    position: static;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 0 calc(var(--px) * 3);
  }

  .book-tab {
    writing-mode: horizontal-tb;
    padding: 10px 12px;
    min-height: 44px;
    clip-path: none;
    transform: none;
  }

  .book-tab[aria-pressed='true'] { transform: none; }

  .book-spread {
    display: block;
    height: auto;
    background-image: none;
  }

  .book-spread::after { display: none; }
  .page { overflow: visible; padding: 16px 14px 22px; }
  .page-left, .page-right { padding-inline: 14px; }
  .book-ribbon { margin-inline: 4px; }
  .quest-item.is-selected::before { display: none; }

  .quest-layout[data-view='list'] .quest-detail { display: none; }
  .quest-layout[data-view='detail'] .quest-list-window { display: none; }

  .quest-back { display: inline-flex; margin-bottom: 4px; justify-self: start; }
}

@media (min-width: 860px) {
  .book { margin-right: calc(var(--px) * 10); }
}


/* ===== badges.css ===== */
/* =============================================================================
   badges.css — ACHIEVEMENTS: pixel badges on shelves, summary bar, detail window.
   The item window and bottom-sheet behaviour are shared with the skill tree
   (see skilltree.css: .item-window, .sheet-backdrop, body.sheet-open).
   ============================================================================= */

/* ── Summary ───────────────────────────────────────────────── */

.ach-summary {
  display: grid;
  grid-template-columns: auto minmax(120px, 1fr);
  align-items: center;
  gap: 8px 18px;
  padding: 14px 18px;
  margin-bottom: 18px;
}

.ach-count {
  margin: 0;
  font-family: var(--font-pixel);
  font-size: calc(11px * var(--type-scale));
  letter-spacing: 0.08em;
  color: var(--pale);
}

.ach-count b { color: var(--gold); font-weight: 400; }

.ach-bar {
  height: calc(var(--px) * 3);
  background: var(--night);
  box-shadow: inset 0 0 0 2px var(--ink);
}

.ach-bar i {
  display: block;
  height: 100%;
  background: var(--gold);
  box-shadow: inset 0 calc(var(--px) * -1) 0 0 var(--gold-dim);
}

.ach-note { grid-column: 1 / -1; margin: 0; font-size: 0.875rem; }

/* ── Layout ────────────────────────────────────────────────── */

.ach-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}

@media (min-width: 1100px) {
  .ach-layout { grid-template-columns: minmax(0, 1fr) 340px; }
  .ach-layout .item-window { position: sticky; top: calc(var(--hud-h) + 24px); }
}

.ach-wall { display: grid; gap: 18px; }

/* ── Shelves ───────────────────────────────────────────────── */

.shelf {
  padding: 14px 16px 6px;
  background: var(--panel);
  box-shadow: 0 0 0 3px var(--line), 0 0 0 6px var(--ink);
  margin: 6px;
}

.shelf-title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
  font-family: var(--font-pixel);
  font-size: calc(11px * var(--type-scale));
  font-weight: 400;
  letter-spacing: 0.08em;
  color: var(--gold);
}

.shelf-icon .badge-svg { width: 24px; height: 24px; display: block; }
.shelf-count { color: var(--muted); }

.badge-wall {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  /* Rows grow with the text-size options so captions are never clipped. */
  --rh: calc(184px + (var(--type-scale) - 1) * 110px);
  grid-auto-rows: var(--rh);
  /* A wooden plank under every row */
  background: repeating-linear-gradient(to bottom, transparent 0 calc(var(--rh) - 12px), #3a2a22 calc(var(--rh) - 12px) calc(var(--rh) - 8px), #6b4a38 calc(var(--rh) - 8px) calc(var(--rh) - 4px), var(--ink) calc(var(--rh) - 4px) var(--rh));
}

.badge-wall > li { min-width: 0; }

/* ── One badge ─────────────────────────────────────────────── */

.badge-btn {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 100%;
  padding: 8px 6px 14px;
  background: none;
  border: 0;
  color: var(--cream);
  text-align: center;
  cursor: pointer;
  animation: badge-in 260ms steps(4, end) calc(var(--i, 0) * 45ms) backwards;
}

@keyframes badge-in {
  from { opacity: 0; filter: brightness(2.2); }
  to { opacity: 1; filter: none; }
}

.badge-art {
  position: relative;
  display: block;
  width: 104px;
  height: 104px;
  flex: none;
  transition: transform 120ms steps(3, end);
}

.badge-svg { display: block; width: 100%; height: 100%; }

.badge-btn:hover .badge-art,
.badge-btn:focus-visible .badge-art { transform: translateY(calc(var(--px) * -1)); }

.badge-btn:focus-visible { outline: none; }
.badge-btn:focus-visible .badge-art { outline: 3px solid var(--cream); outline-offset: 4px; }

.badge-btn.is-selected .badge-art { outline: 3px solid var(--gold); outline-offset: 4px; }

.badge-caption {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--cream);
}

.badge-btn.is-locked .badge-caption { color: var(--muted); }
.badge-btn.is-locked .badge-art { opacity: 0.9; }

/* Shine sweep (unlocked badges): once on arrival, again on hover/focus */
.badge-shine {
  opacity: 0;
  animation: badge-shine 700ms steps(8, end) calc(var(--i, 0) * 45ms + 400ms) 1 backwards;
}

.badge-btn:hover .badge-shine,
.badge-btn:focus-visible .badge-shine { animation: badge-shine 600ms steps(8, end) 1; }

@keyframes badge-shine {
  0% { opacity: 0.55; transform: translateX(0); }
  100% { opacity: 0.55; transform: translateX(50px); }
}

/* "×2" stack count */
.badge-count {
  position: absolute;
  right: -6px;
  bottom: -2px;
  padding: 3px 6px;
  background: var(--ink);
  color: var(--gold);
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  box-shadow: inset 0 0 0 2px var(--gold-dim);
}

/* ── Detail window ─────────────────────────────────────────── */

.ach-hero {
  position: relative;
  width: 128px;
  height: 128px;
  margin: 4px auto 10px;
}

.badge-count-lg { font-size: calc(12px * var(--type-scale)); right: -8px; bottom: 0; }

.ach-tags {
  margin-bottom: 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0;
}

.ach-group {
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.06em;
  color: var(--muted);
}

.ach-detail .item-name { text-align: center; }
.ach-detail .badge-date {
  margin: 0;
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  letter-spacing: 0.05em;
  color: var(--gold);
}

/* ── Small screens ─────────────────────────────────────────── */

@media (max-width: 640px) {
  .shelf { padding: 12px 10px 4px; }
  .badge-wall {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    --rh: calc(150px + (var(--type-scale) - 1) * 130px);
  }
  .badge-art { width: 72px; height: 72px; }
  .badge-caption { font-size: 0.75rem; }
  .ach-summary { grid-template-columns: 1fr; }
}


/* ===== extras.css ===== */
/* =============================================================================
   extras.css — The "more unique" layer: options window, scanlines, pixel cursor,
   living background (clouds, shooting star, cat, hero walk), blinking portrait,
   and the skill-tree power-on intro.
   Everything here is decoration or a progressive enhancement; reduced-motion
   users get the final state with no animation (see base.css).
   ============================================================================= */

/* ── HUD: options + sound on the right ─────────────────────── */

.hud-right {
  display: flex;
  align-items: center;
  gap: 4px;
}

.hud-icon {
  justify-content: center;
  min-width: 40px;
  padding: 8px;
}

.hud-icon .sprite {
  width: 20px;
  height: 20px;
}

@media (max-width: 520px) {
  .hud-title { display: none; }
  .hud { gap: 4px; }
}

/* ── Options window (modal) ────────────────────────────────── */

.modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 16px;
}

.modal[hidden] { display: none; }

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(4, 6, 14, 0.8);
}

.modal-win {
  position: relative;
  width: min(520px, 100%);
  max-height: calc(100dvh - 32px);
  overflow: auto;
  animation: pop 160ms steps(3, end) backwards;
}

body.modal-open { overflow: hidden; }

.option-list {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  display: grid;
  gap: 18px;
}

.switch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: calc(100% - var(--px) * 2);
  min-height: 48px;
  margin: var(--px);
  padding: 10px 14px;
  background: var(--panel-2);
  border: 0;
  color: var(--cream);
  font-family: var(--font-pixel);
  font-size: calc(11px * var(--type-scale));
  letter-spacing: 0.06em;
  text-align: left;
  cursor: pointer;
  box-shadow:
    0 calc(var(--px) * -1) 0 0 var(--line),
    0 var(--px) 0 0 var(--line),
    calc(var(--px) * -1) 0 0 0 var(--line),
    var(--px) 0 0 0 var(--line);
}

.switch:hover { background: var(--line); }

.switch-state {
  min-width: 52px;
  padding: 6px 8px;
  text-align: center;
  color: var(--muted);
  background: var(--night);
  box-shadow: inset 0 0 0 2px var(--ink);
}

.switch[aria-checked='true'] .switch-state {
  color: var(--ink);
  background: var(--teal);
}

.switch-hint {
  margin: 10px 4px 0;
  font-size: 0.875rem;
}

.option-reset {
  margin-bottom: 14px;
}

.option-reset .switch-hint { margin-top: 10px; }

/* ── Scanlines (optional) ──────────────────────────────────── */

html.crt-on::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  background:
    repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0.2) 0 1px, transparent 1px 3px),
    radial-gradient(ellipse at center, transparent 62%, rgba(0, 0, 0, 0.32) 100%);
}


/* ── Pixel cursor (generated from the "cursor" sprite; fine pointers only) ── */
@media (pointer: fine) {
  html, body { cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='18' shape-rendering='crispEdges'%3E%3Crect x='0' y='0' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='2' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='2' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='4' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='4' width='2' height='2' fill='%23efe6cf'/%3E%3Crect x='4' y='4' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='6' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='6' width='2' height='2' fill='%23efe6cf'/%3E%3Crect x='4' y='6' width='2' height='2' fill='%23efe6cf'/%3E%3Crect x='6' y='6' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='8' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='8' width='2' height='2' fill='%23efe6cf'/%3E%3Crect x='4' y='8' width='2' height='2' fill='%23efe6cf'/%3E%3Crect x='6' y='8' width='2' height='2' fill='%23efe6cf'/%3E%3Crect x='8' y='8' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='10' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='10' width='2' height='2' fill='%23efe6cf'/%3E%3Crect x='4' y='10' width='2' height='2' fill='%23efe6cf'/%3E%3Crect x='6' y='10' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='12' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='12' width='2' height='2' fill='%23efe6cf'/%3E%3Crect x='4' y='12' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='14' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='14' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='16' width='2' height='2' fill='%230a0e1a'/%3E%3C/svg%3E") 0 0, default; }
  html :is(a, button, [role='switch'], .tnode-cert) { cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='18' shape-rendering='crispEdges'%3E%3Crect x='0' y='0' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='2' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='2' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='4' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='4' width='2' height='2' fill='%23e8b84a'/%3E%3Crect x='4' y='4' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='6' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='6' width='2' height='2' fill='%23e8b84a'/%3E%3Crect x='4' y='6' width='2' height='2' fill='%23e8b84a'/%3E%3Crect x='6' y='6' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='8' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='8' width='2' height='2' fill='%23e8b84a'/%3E%3Crect x='4' y='8' width='2' height='2' fill='%23e8b84a'/%3E%3Crect x='6' y='8' width='2' height='2' fill='%23e8b84a'/%3E%3Crect x='8' y='8' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='10' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='10' width='2' height='2' fill='%23e8b84a'/%3E%3Crect x='4' y='10' width='2' height='2' fill='%23e8b84a'/%3E%3Crect x='6' y='10' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='12' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='12' width='2' height='2' fill='%23e8b84a'/%3E%3Crect x='4' y='12' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='14' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='2' y='14' width='2' height='2' fill='%230a0e1a'/%3E%3Crect x='0' y='16' width='2' height='2' fill='%230a0e1a'/%3E%3C/svg%3E") 0 0, pointer; }
}

/* ── Living background ─────────────────────────────────────── */

.cloud-mover {
  animation: cloud-drift 80s linear infinite;
}

@keyframes cloud-drift {
  from { transform: translateX(calc(var(--cx, 0px) * -1 - 24px)); }
  to { transform: translateX(calc(192px - var(--cx, 0px) + 24px)); }
}

.shooting-star-mover {
  opacity: 0;
  animation: shoot 17s steps(10, end) 3s infinite;
}

@keyframes shoot {
  0%, 94% { opacity: 0; transform: translate(0, 0); }
  95% { opacity: 1; transform: translate(0, 0); }
  100% { opacity: 0; transform: translate(34px, 16px); }
}

.cat-shut { opacity: 0; }
.cat-open { animation: cat-open 6s steps(1, end) infinite; }
.cat-shut { animation: cat-shut 6s steps(1, end) infinite; }

@keyframes cat-open { 0%, 90% { opacity: 1; } 91%, 96% { opacity: 0; } 97%, 100% { opacity: 1; } }
@keyframes cat-shut { 0%, 90% { opacity: 0; } 91%, 96% { opacity: 1; } 97%, 100% { opacity: 0; } }

/* PRESS START: the hero walks up to the terminal. */
.is-launching .scene-hero {
  animation: hero-walk 520ms steps(8, end) both;
}

.is-launching .hero-frame-a { animation-duration: 0.2s; }
.is-launching .hero-frame-b { animation-duration: 0.2s; }

@keyframes hero-walk {
  to { transform: translateX(8px); }
}

/* ── Title screen: greeting + readable plates over bright skies ── */

.title-greeting {
  margin-top: 14px;
  font-family: var(--font-pixel);
  font-size: clamp(0.5625rem, 1.8vw, 0.6875rem);
  letter-spacing: 0.12em;
  color: var(--teal);
  animation: title-fade 300ms steps(3, end) 1.8s backwards;
}

.title-tag,
.title-hint,
.title-greeting {
  display: block;
  width: fit-content;
  margin-inline: auto;
  padding: 3px 10px;
  background: rgba(7, 11, 22, 0.62);
}

.title-tag { margin-top: 8px; color: var(--cream); }
.title-greeting { margin-top: 14px; }
.title-hint { margin-top: 8px; color: var(--pale); }

/* Tighter vertical rhythm so the stacked lines stay clear of the hero and terminal. */
.title { padding-top: clamp(40px, 6dvh, 110px); }
.title-sub { margin-top: clamp(12px, 2.2dvh, 36px); }
.press-start { margin-top: clamp(12px, 2.4dvh, 32px); }

@media (max-height: 680px) {
  .title-greeting,
  .title-hint { display: none; }
}

/* ── Blinking portrait ─────────────────────────────────────── */

.portrait-wrap {
  position: relative;
  width: 100%;
  height: 100%;
}

.portrait-wrap .sprite {
  position: absolute;
  inset: 0;
}

.portrait-blink {
  opacity: 0;
  animation: portrait-blink 5.5s steps(1, end) infinite;
}

@keyframes portrait-blink {
  0%, 94% { opacity: 0; }
  95%, 98% { opacity: 1; }
  99%, 100% { opacity: 0; }
}

/* ── Skill tree power-on intro ─────────────────────────────── */
/* Opacity and brightness only: nodes are positioned with transforms we must not override. */

.tree-intro .tnode,
.tree-intro .lnode,
.tree-intro .tjoint {
  animation: node-on 360ms steps(4, end) calc(var(--depth, 0) * 170ms) backwards;
}

.tree-intro .edge,
.tree-intro .rail-casing {
  animation: edge-on 360ms steps(4, end) calc(var(--depth, 0) * 170ms - 120ms) backwards;
}

.tree-intro .tree-cursor { visibility: hidden; }

@keyframes node-on {
  0% { opacity: 0; filter: brightness(2.2); }
  60% { opacity: 1; filter: brightness(1.8); }
  100% { opacity: 1; filter: none; }
}

@keyframes edge-on {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Keep the animated background on its own compositor layer so drifting clouds
   can never repaint on top of the foreground text. */
.scene {
  will-change: transform;
}

/* ── Title-screen hot-spots: cat, hero, terminal ─────────────── */

.scene-hits {
  position: fixed;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}

.scene-hit {
  position: absolute;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
}

/* Keep the hot-spots out of the way while the logo plays or the hero walks away. */
.is-launching .scene-hits { visibility: hidden; }

.scene-hit::after {
  content: attr(data-tip);
  position: absolute;
  left: 50%;
  bottom: 100%;
  transform: translateX(-50%);
  margin-bottom: 6px;
  padding: 4px 8px;
  background: var(--ink);
  color: var(--cream);
  font-family: var(--font-pixel);
  font-size: calc(8px * var(--type-scale));
  letter-spacing: 0.08em;
  white-space: nowrap;
  box-shadow: 0 0 0 2px var(--line);
  opacity: 0;
  pointer-events: none;
}

.scene-hit:hover::after,
.scene-hit:focus-visible::after { opacity: 1; }

.scene-hit:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
}

.scene-bubble {
  position: absolute;
  transform: translate(-50%, -100%);
  max-width: min(260px, 80vw);
  padding: 8px 12px;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  line-height: 1.6;
  text-align: center;
  box-shadow: 0 0 0 3px var(--ink);
  pointer-events: none;
  animation: bubble-pop 160ms steps(3, end) backwards;
}

.scene-bubble::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 100%;
  margin-left: -6px;
  border: 6px solid transparent;
  border-top-color: var(--ink);
}

@keyframes bubble-pop {
  from { opacity: 0; transform: translate(-50%, -80%); }
  to { opacity: 1; transform: translate(-50%, -100%); }
}

/* The title text always wins over a hot-spot that overlaps it (e.g. the terminal's antenna). */
.title-inner { position: relative; z-index: 2; pointer-events: none; }
.title-inner > * { pointer-events: auto; }
.scene-hits { z-index: 1; }


/* ===== summary.css ===== */
/* =============================================================================
   summary.css — "Skip the game" recruiter summary (#/summary) + print sheet.
   A plain paper-style page: readable first, game second. No animation.
   ============================================================================= */

.summary-screen {
  max-width: 920px;
  animation: none;
}

.sum-sheet {
  --paper: #f7f2e4;
  --paper-ink: #1b2236;
  --paper-muted: #4a5470;
  --paper-rule: #cfc6ab;
  --paper-link: #0f5f55;
  padding: clamp(20px, 4vw, 44px);
  background: var(--paper);
  color: var(--paper-ink);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  box-shadow:
    0 calc(var(--px) * -1) 0 0 var(--ink),
    0 var(--px) 0 0 var(--ink),
    calc(var(--px) * -1) 0 0 0 var(--ink),
    var(--px) 0 0 0 var(--ink),
    0 calc(var(--px) * 2) 0 calc(var(--px) * -0) rgba(0, 0, 0, 0.35);
}

.sum-sheet a { color: var(--paper-link); text-underline-offset: 3px; }
.sum-sheet a:hover { color: var(--ink); }
.sum-sheet a:focus-visible { outline: 3px solid var(--paper-link); outline-offset: 2px; }

.sum-name {
  margin: 0;
  font-family: var(--font-pixel);
  font-size: clamp(1rem, 3.6vw, 1.625rem);
  line-height: 1.4;
  letter-spacing: 0.02em;
  text-wrap: balance;
}
.sum-name:focus { outline: none; }
.sum-name:focus-visible { outline: 3px solid var(--paper-link); outline-offset: 4px; }

.sum-role { margin: 10px 0 0; font-weight: 600; font-size: 1.125rem; }
.sum-meta { margin: 2px 0 0; color: var(--paper-muted); }

.sum-contact {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}

.sum-actions {
  display: flex;
  flex-wrap: wrap;
  margin: 18px calc(var(--px) * -1) 0;
}
.sum-actions .btn { color: var(--cream); }
.sum-actions .btn:hover { color: var(--ink); }
.sum-actions .btn-ghost { --btn-bg: #2a3a63; --btn-ring: #121b33; }
.sum-actions .btn-ghost:hover { --btn-bg: var(--teal); color: var(--ink); }

.sum-body { margin-top: 20px; }

.sum-section {
  padding-top: 18px;
  margin-top: 18px;
  border-top: 2px solid var(--paper-rule);
}

.sum-h2 {
  break-after: avoid;
  margin: 0 0 10px;
  font-family: var(--font-pixel);
  font-size: 0.75rem;
  line-height: 1.5;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #6a4a12;
}

.sum-section p { margin: 0 0 8px; max-width: 74ch; }

.sum-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 16px; }
.sum-list-tight { gap: 8px; }
.sum-list li { break-inside: avoid; }
.sum-list li > p:last-child { margin-bottom: 0; }

.sum-line {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 2px 16px;
}
.sum-date {
  font-size: 0.8125rem;
  color: var(--paper-muted);
  font-weight: 600;
  letter-spacing: 0.03em;
  white-space: nowrap;
}
.sum-tech, .sum-links { font-size: 0.875rem; color: var(--paper-muted); }
.sum-links a { color: var(--paper-link); }

.sum-skills { margin: 0; display: grid; gap: 6px; }
.sum-skills div { display: grid; grid-template-columns: 9.5em 1fr; gap: 12px; }
.sum-skills dt { font-weight: 600; }
.sum-skills dd { margin: 0; }

.sum-bullets { margin: 0; padding-left: 1.4em; list-style: disc; }

.sum-foot {
  margin: 22px 0 0;
  padding-top: 12px;
  border-top: 2px solid var(--paper-rule);
  font-size: 0.8125rem;
  color: var(--paper-muted);
}

@media (max-width: 560px) {
  .sum-skills div { grid-template-columns: 1fr; gap: 0; }
  .sum-date { white-space: normal; }
}

/* The scene behind the paper is just dimmed on this screen. */
[data-scene='summary'] .stage-dim { opacity: 0.55; }

/* ── Title-screen entry link ─────────────────────────────────── */
.title-skip {
  display: inline-block;
  margin-top: 14px;
  padding: 8px 12px;
  min-height: 44px;
  line-height: 28px;
  font-size: 0.875rem;
  color: var(--cream);
  background: rgba(7, 11, 22, 0.62);
  text-shadow: 2px 2px 0 var(--ink);
  text-decoration: underline;
  text-underline-offset: 4px;
  animation: title-fade 300ms steps(3, end) 2.2s backwards;
}
.title-skip:hover { color: var(--gold); }
@media (max-height: 520px) { .title-skip { margin-top: 4px; } }

/* ── Print: a clean one-to-two page résumé sheet ──────────────── */
@media print {
  @page { margin: 14mm; }

  html, body { background: #fff !important; }
  .stage, .hud, .wipe, .skip-link, #announcer, .sum-actions, .title-skip,
  .modal-backdrop, .scanlines { display: none !important; }
  .crt-on::after, .crt-on::before { display: none !important; }

  .screen { min-height: 0; }
  .summary-screen { max-width: none; padding: 0; }
  .sum-sheet {
    padding: 0;
    box-shadow: none;
    background: #fff;
    --paper-ink: #000;
    --paper-muted: #333;
    --paper-link: #000;
    --paper-rule: #999;
    font-size: 10.5pt;
    line-height: 1.45;
  }
  .sum-name { font-size: 18pt; }
  .sum-h2 { color: #000; font-size: 9pt; }
  .sum-section { margin-top: 12px; padding-top: 10px; }
  .sum-sheet a { text-decoration: none; }
  .sum-contact a[href^='http']::after,
  .sum-links a[href^='http']::after { content: ' (' attr(href) ')'; font-size: 8.5pt; word-break: break-all; }
  .sum-list li a[href^='https://www.credly.com']::after { content: none; }
  .sum-foot { display: none; }
}


/* ===== world.css ===== */
/* =============================================================================
   world.css — WALK AROUND: full-screen village, camera, hero, cat, speech bubble, D-pad, locations drawer.
   The map is larger than the screen; --tile (set in JS) is a whole multiple of the 16 px art.
   ============================================================================= */

/* ── Full-screen village ─────────────────────────────────────
   The screen is fixed over everything; the map inside it is larger than the
   screen and slides under it as the hero walks (camera follows the hero).
   --tile is set by js/scenes/world.js as a whole multiple of the 16 px art. */

.app[data-scene='world'] .hud { display: none; }
.app[data-scene='world'] .skip-link:not(:focus) { display: none; }

.world-screen {
  --tile: 96px;
  position: fixed;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  background: #1f6b3a;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
}

.world-viewport { position: absolute; inset: 0; overflow: hidden; }

.world-map {
  position: absolute;
  left: 0;
  top: 0;
  cursor: pointer;
  background: #2f8f5b;
  transition: transform 150ms steps(5, end);
  -webkit-tap-highlight-color: transparent;
}
.world-map.no-glide { transition: none; }

.world-art { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.world-actor {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--tile);
  height: var(--tile);
  transform: translate(calc(var(--x) * var(--tile)), calc(var(--y) * var(--tile)));
  transition: transform 150ms steps(5, end);
  pointer-events: none;
}

.world-flip { position: relative; width: 100%; height: 100%; }
.is-left .world-flip { transform: scaleX(-1); }

.world-hero { z-index: 3; }
.world-cat { z-index: 2; }

.world-hero .sprite {
  position: absolute;
  left: 18.75%;
  bottom: 0;
  width: 62.5%;
  height: 100%;
}

.world-cat .sprite {
  position: absolute;
  left: 25%;
  bottom: 6%;
  width: 50%;
  height: 50%;
}

.world-frame-b { opacity: 0; }
.world-hero.is-step .world-frame-a { opacity: 0; }
.world-hero.is-step .world-frame-b { opacity: 1; }

/* Building names */
.world-label {
  position: absolute;
  left: calc(var(--lx) * var(--tile));
  top: calc(var(--ly) * var(--tile));
  transform: translate(-50%, -115%);
  padding: 0.3em 0.6em;
  background: rgba(7, 11, 22, 0.82);
  box-shadow: 0 0 0 2px var(--ink), 0 0 0 4px var(--line);
  font-family: var(--font-pixel);
  font-size: calc(max(9px, var(--tile) * 0.1) * var(--type-scale));
  letter-spacing: 0.06em;
  white-space: nowrap;
  color: var(--cream);
  pointer-events: none;
  z-index: 2;
}
.world-label.is-tall { margin-top: calc(var(--tile) * -0.8); }

/* Speech bubble beside a door */
.world-bubble {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 5;
  display: grid;
  gap: 4px;
  min-height: 44px;
  padding: 10px 14px;
  background: var(--cream);
  border: 0;
  color: var(--ink);
  text-align: center;
  cursor: pointer;
  box-shadow: 0 0 0 3px var(--ink), 0 6px 0 3px rgba(0, 0, 0, 0.35);
  transform: translate(calc((var(--x) + 0.5) * var(--tile)), calc(var(--y) * var(--tile))) translate(-50%, calc(-100% - 10px));
  transition: transform 150ms steps(5, end);
}
.world-bubble[hidden] { display: none; }
.world-bubble::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -11px;
  margin-left: -8px;
  border: 8px solid transparent;
  border-top: 8px solid var(--cream);
  border-bottom: 0;
}
.world-bubble strong { font-family: var(--font-pixel); font-weight: 400; font-size: calc(10px * var(--type-scale)); letter-spacing: 0.05em; }
.world-bubble small { font-size: 0.8125rem; color: #3a3f55; }
.bubble-key { font-family: var(--font-pixel); font-size: calc(8px * var(--type-scale)); color: var(--red); }

/* Button bar and hint */
.world-bar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 8;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  padding: max(10px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right)) 0 max(10px, env(safe-area-inset-left));
  pointer-events: none;
}
.world-bar > *, .world-bar-right > * { pointer-events: auto; }
.world-bar-right { display: flex; align-items: flex-start; gap: 4px; pointer-events: none; }
.world-key {
  padding: 2px 5px;
  background: var(--ink);
  color: var(--gold);
  font-size: calc(8px * var(--type-scale));
}
@media (pointer: coarse) { .world-key { display: none; } }

.world-hint {
  position: absolute;
  left: 50%;
  bottom: max(14px, env(safe-area-inset-bottom));
  z-index: 6;
  transform: translateX(-50%);
  padding: 10px 14px;
  background: rgba(7, 11, 22, 0.86);
  box-shadow: 0 0 0 2px var(--ink), 0 0 0 4px var(--line);
  font-family: var(--font-pixel);
  font-size: calc(9px * var(--type-scale));
  line-height: 1.6;
  letter-spacing: 0.05em;
  color: var(--pale);
  white-space: nowrap;
  transition: opacity 400ms steps(4, end);
  pointer-events: none;
}
.world-hint span { color: var(--gold); }
.world-screen.has-moved .world-hint { opacity: 0; }
@media (pointer: coarse), (max-width: 959px) { .world-hint { display: none; } }

/* Left side of the bar: TITLE button and the EXPLORED counter */
.world-bar-left { display: flex; align-items: flex-start; gap: 4px; pointer-events: none; }
.world-bar-left > * { pointer-events: auto; }
.world-explore {
  margin: var(--px);
  padding: 11px 12px;
  background: rgba(7, 11, 22, 0.86);
  box-shadow: 0 0 0 2px var(--ink), 0 0 0 4px var(--line);
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  letter-spacing: 0.06em;
  color: var(--pale);
  pointer-events: none !important;
  white-space: nowrap;
}
.world-explore .ex-count { color: var(--teal); }
.world-explore.is-complete .ex-count { color: var(--gold); }
@media (max-width: 560px) { .world-explore .ex-label { display: none; } }

/* One-time "all areas explored" message */
.world-toast {
  position: absolute;
  top: calc(var(--hud-h) + 12px);
  left: 50%;
  z-index: 7;
  transform: translateX(-50%);
  width: min(460px, calc(100% - 24px));
  padding: 16px 18px;
  background: var(--panel);
  color: var(--cream);
  box-shadow: 0 0 0 3px var(--gold), 0 0 0 6px var(--ink);
}
.world-toast p { margin: 0 0 10px; font-size: 0.9375rem; line-height: 1.5; }
.toast-title { font-family: var(--font-pixel); font-size: calc(11px * var(--type-scale)) !important; letter-spacing: 0.08em; color: var(--gold); }
.toast-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.toast-actions .btn { margin: var(--px); }

/* Locations drawer */
.world-drawer {
  position: absolute;
  top: calc(var(--hud-h) + 8px);
  right: max(8px, env(safe-area-inset-right));
  bottom: 8px;
  z-index: 9;
  width: min(380px, calc(100% - 16px));
  overflow-y: auto;
  overscroll-behavior: contain;
}
.world-drawer[hidden] { display: none; }
.world-drawer-close { margin-top: 14px; width: 100%; justify-content: center; }

/* ── On-screen arrows: shown on touch screens and narrow windows ── */
.dpad { display: none; }

@media (pointer: coarse), (max-width: 959px) {
  .dpad {
    position: absolute;
    left: max(14px, env(safe-area-inset-left));
    bottom: max(14px, env(safe-area-inset-bottom));
    z-index: 6;
    display: grid;
    grid-template-columns: repeat(3, 56px);
    grid-template-rows: repeat(2, 56px);
    gap: 6px;
    margin: 0;
  }
  .world-screen.has-drawer .dpad { display: none; }
  .dpad-up { grid-area: 1 / 2; }
  .dpad-left { grid-area: 2 / 1; }
  .dpad-down { grid-area: 2 / 2; }
  .dpad-right { grid-area: 2 / 3; }
}

.dpad-btn {
  position: relative;
  opacity: 0.92;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  background: var(--panel-2);
  border: 0;
  color: var(--cream);
  cursor: pointer;
  box-shadow:
    inset 0 calc(var(--px) * -1) 0 0 rgba(0, 0, 0, 0.3),
    0 0 0 var(--px) var(--line);
}
.dpad-btn:active { transform: translateY(2px); background: var(--line); }
.dpad-btn span {
  position: absolute;
  left: 50%;
  top: 50%;
  border: 9px solid transparent;
}
.dpad-up span { border-bottom: 12px solid currentColor; border-top: 0; transform: translate(-50%, -60%); }
.dpad-down span { border-top: 12px solid currentColor; border-bottom: 0; transform: translate(-50%, -40%); }
.dpad-left span { border-right: 12px solid currentColor; border-left: 0; transform: translate(-60%, -50%); }
.dpad-right span { border-left: 12px solid currentColor; border-right: 0; transform: translate(-40%, -50%); }

/* ── Locations ── */
.loc-list { display: grid; gap: 8px; }

.loc {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 8px 12px;
  background: var(--panel-2);
  border: 0;
  color: var(--cream);
  text-align: left;
  cursor: pointer;
  box-shadow: inset 0 0 0 2px var(--line);
}
.loc:hover { background: var(--line); }
.pref-calm .world-map, .pref-calm .world-bubble, .pref-calm .world-actor { transition: none; }
.loc-icon { display: grid; place-items: center; width: 32px; height: 32px; flex: none; }
.loc-icon .sprite { width: 24px; height: 24px; }
.loc-text { display: grid; flex: 1; gap: 2px; min-width: 0; }
.loc-text strong {
  font-family: var(--font-pixel);
  font-size: calc(10px * var(--type-scale));
  font-weight: 400;
  letter-spacing: 0.06em;
}
.loc-text small { color: var(--muted); font-size: 0.8125rem; }
.loc-check .sprite { width: 16px; height: 16px; }
.world-help { margin-top: 14px; font-size: 0.875rem; }


/* ===== comfort.css ===== */
/* =============================================================================
   comfort.css — Visitor comfort options (OPTIONS window).
   Each rule below is switched by a class that settings.js puts on <html>:
     pref-big       larger text           pref-contrast  high contrast
     pref-readable  plain sans-serif UI   pref-calm      no animation (base.css)
   ============================================================================= */

/* ── Larger text: --ts-big scales rem text (via html) and every px size ── */
html.pref-big { --ts-big: 1.2; }

/* ── Readable text: swap the pixel font for the body font, and scale up
      because the body font is smaller at the same size. ── */
html.pref-readable {
  --ts-read: 1.3;
  --font-pixel: var(--font-body);
}

html.pref-readable :is(h1, h2, h3, button, .btn, .tag, .badge, [class*='label'], [class*='title'], [class*='name'], dt) {
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* The big PLAYER ONE logo is artwork, so it keeps its pixel font. */
html.pref-readable .logo-letter,
html.pref-readable .title-logo {
  font-family: 'Press Start 2P', 'Courier New', monospace;
  font-weight: 400;
  letter-spacing: normal;
}

/* ── High contrast ── */
html.pref-contrast {
  --void: #000;
  --night: #050914;
  --panel: #0a1022;
  --panel-2: #16213f;
  --line: #9db2e6;
  --ink: #000;
  --teal: #55e6cf;
  --teal-dim: #138a79;
  --gold: #ffd35c;
  --cream: #fff;
  --pale: #f2f5ff;
  --muted: #d7deef;
}

/* The picture behind the windows is dimmed further so text never fights it. */
html.pref-contrast .app:not([data-scene='title']):not([data-scene='boot']) .stage-dim { opacity: 0.97 !important; }
html.pref-contrast .title-tag,
html.pref-contrast .title-hint,
html.pref-contrast .title-greeting { background: #000; }

html.pref-contrast :focus-visible {
  outline: 4px solid #fff !important;
  box-shadow: 0 0 0 7px #000 !important;
}

html.pref-contrast a { text-decoration-thickness: 3px; }

html.pref-contrast .sum-sheet {
  --paper: #fff;
  --paper-ink: #000;
  --paper-muted: #1d2230;
  --paper-rule: #000;
  --paper-link: #00403a;
}

/* Pixel-style drop shadows turn plain letters into doubled, blurry ones. */
html.pref-readable :not(.title, .title *) { text-shadow: none; }
