/* ─────────────────────────────────────────────────────────────
   stage.css · shared look for the stage pages (about / experience / contact)
   1-bit, like the hero: white ink on black paper, nothing in between.
   Press Start 2P = game UI (menus, labels, settings)
   VT323          = terminal (commands and the prose they print)
   ───────────────────────────────────────────────────────────── */

:root {
  --ink: #fff;
  --paper: #000;
  --px: 4px;                         /* one "pixel" of UI chrome */
  --col: 760px;                      /* reading column */
  --pixel: 'Press Start 2P', ui-monospace, Menlo, Consolas, monospace;
  --term: 'VT323', ui-monospace, Menlo, Consolas, monospace;
  --cursor: none;                    /* sprites: filled in by stage.js from the hero's art */
  --dither: conic-gradient(var(--ink) 25%, transparent 0 50%, var(--ink) 0 75%, transparent 0) 0 0 / 4px 4px;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; }
html, body { background: var(--paper); color: var(--ink); }
body {
  font-family: var(--pixel);
  font-size: 11px;
  line-height: 1.6;
  -webkit-font-smoothing: none;
  font-smooth: never;
  text-rendering: optimizeSpeed;
  overflow-x: hidden;
}
a { color: inherit; }
::selection { background: var(--ink); color: var(--paper); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

/* the whole screen powers on like the stage-select panel does */
.crt { min-height: 100vh; min-height: 100svh; display: flex; flex-direction: column; animation: boot 0.3s steps(6, end) both; }

/* pixel-art frame: square edges with the corners notched out (same trick as the home page) */
.pixel-frame {
  box-shadow:
    0 calc(-1 * var(--px)) 0 0 var(--ink),
    0 var(--px) 0 0 var(--ink),
    calc(-1 * var(--px)) 0 0 0 var(--ink),
    var(--px) 0 0 0 var(--ink);
}

/* ── sprites (art comes from space-invaders-hero.js) ── */
.sprite {
  --s: 3;
  display: inline-block;
  flex: none;
  position: relative;
  width: calc(var(--w) * var(--s) * 1px);
  height: calc(var(--h) * var(--s) * 1px);
  background: var(--img0) 0 0 / 100% 100% no-repeat;
  image-rendering: pixelated;
}
.f1 .sprite { background-image: var(--img1, var(--img0)); }
.sprite.squid { --w: 8;  --h: 8; --img0: var(--squid-0); --img1: var(--squid-1); }
.sprite.crab  { --w: 11; --h: 8; --img0: var(--crab-0);  --img1: var(--crab-1); }
.sprite.octo  { --w: 12; --h: 8; --img0: var(--octo-0);  --img1: var(--octo-1); }
.sprite.ufo   { --w: 16; --h: 7; --img0: var(--ufo-0); }
.sprite.mini  { --w: 11; --h: 9; --img0: var(--mini-0); }

/* shoot the decorations: they burst, score, and drop back in a few seconds later */
.sprite[data-pts] { cursor: crosshair; }
.sprite.is-hit { background: none; }
.sprite.is-hit::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: calc(13px * var(--s)); height: calc(8px * var(--s));
  transform: translate(-50%, -50%);
  background: var(--boom-0) 0 0 / 100% 100% no-repeat;
  image-rendering: pixelated;
}
.sprite.is-gone { visibility: hidden; }
.pts {
  position: absolute;
  z-index: 20;
  font-family: var(--pixel);
  font-size: 10px;
  line-height: 1;
  pointer-events: none;
  transform: translate(-50%, -50%);
  animation: float-up 0.9s steps(6, end) forwards;
}

/* the fighter as a menu cursor, turned to point right */
.cursor {
  display: inline-block;
  width: 17px;
  height: 19px;
  flex: none;
  margin: 0 1px;
  background: var(--cursor) center / 17px 19px no-repeat;
  image-rendering: pixelated;
  transform: rotate(90deg);
}

/* ── HUD: same layout as the game ── */
.hud {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  column-gap: clamp(20px, 5vw, 56px);
  width: 100%;
  max-width: calc(var(--col) + 32px);
  margin: 0 auto;
  padding: 16px max(16px, env(safe-area-inset-right)) 4px max(16px, env(safe-area-inset-left));
  font-size: 10px;
  line-height: 1;
}
.score { display: grid; gap: 8px; text-align: center; letter-spacing: 0.06em; }
.ufo-lane { position: relative; height: 34px; overflow: hidden; }
.ufo-lane .sprite { position: absolute; left: 0; top: 10px; --s: 2; will-change: transform; }

/* ── stage select: a dropdown in the HUD, styled like the home page's menu ── */
.stage-nav { position: relative; justify-self: start; margin-left: -8px; }
.stage-toggle {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px 10px 8px;
  border: 0;
  font: inherit;
  letter-spacing: 0.06em;
  cursor: pointer;
}
/* the fighter points down at the menu, and up while it's open */
.stage-toggle .cursor { transform: rotate(180deg) scale(0.8); }
.stage-toggle[aria-expanded="true"] .cursor { transform: scale(0.8); }

.dropdown {
  position: absolute;
  top: calc(100% + 12px);
  left: 0;
  z-index: 30;
  min-width: 100%;
  padding: 10px 6px;
  background: var(--paper);
  font-size: 11px;
}
.dropdown[hidden] { display: none; }
.dropdown:not([hidden]) { animation: unroll 0.2s steps(5, end) both; }
.dropdown ul { list-style: none; padding: 0; display: grid; gap: 2px; }
.dropdown li { opacity: 0; }
.dropdown:not([hidden]) li { animation: appear 0s linear forwards; }
.dropdown:not([hidden]) li:nth-child(1) { animation-delay: 0.16s; }
.dropdown:not([hidden]) li:nth-child(2) { animation-delay: 0.22s; }
.dropdown:not([hidden]) li:nth-child(3) { animation-delay: 0.28s; }
.dropdown:not([hidden]) li:nth-child(4) { animation-delay: 0.34s; }
.dropdown a {
  display: grid;
  grid-template-columns: 17px auto;
  align-items: center;
  gap: 14px;
  padding: 12px 18px 12px 8px;
  line-height: 1;
  letter-spacing: 0.08em;
  text-decoration: none;
  white-space: nowrap;
}
.dropdown .cursor { visibility: hidden; }
.dropdown a.is-active .cursor { visibility: visible; animation: blink 0.8s steps(1, end) infinite; }
.dropdown [aria-current="page"] span + span { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 5px; }
/* HOME sits apart from the stages, under a dithered rule */
.dropdown .home { position: relative; margin-top: 10px; padding-top: 10px; }
.dropdown .home::before { content: ''; position: absolute; top: 0; left: 8px; right: 8px; height: 4px; background: var(--dither); }

/* invert on hover / focus, exactly like the home page buttons */
.stage-toggle, .channel-link, .dropdown a {
  color: var(--ink);
  background: transparent;
  outline: none;
}
.stage-toggle:focus-visible, .stage-toggle[aria-expanded="true"],
.channel-link:focus-visible, .channel-link.is-active { background: var(--ink); color: var(--paper); }
.stage-toggle:focus-visible .cursor, .stage-toggle[aria-expanded="true"] .cursor, .channel-link.is-active .cursor { filter: invert(1); }
@media (hover: hover) {
  .stage-toggle:hover { background: var(--ink); color: var(--paper); }
  .stage-toggle:hover .cursor { filter: invert(1); }
}
[data-nav].is-chosen { animation: chosen 0.09s steps(1, end) infinite; }

/* ── the reading column ── */
.screen {
  flex: 1;
  width: 100%;
  max-width: calc(var(--col) + 32px);
  margin: 0 auto;
  padding: 28px 16px max(72px, env(safe-area-inset-bottom));
}

.title-card {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 30px;
}
.title-card h1 {
  font-size: clamp(22px, 5.4vw, 34px);
  font-weight: normal;
  line-height: 1.1;
  letter-spacing: 0.06em;
  animation: banner 0.6s steps(1, end) both;
}
.title-card .sprite { animation: drop-in 0.5s steps(5, end) both; }

/* terminal: a prompt, a command, what it printed */
.console {
  font-family: var(--term);
  font-size: 22px;
  line-height: 1.25;
  margin-bottom: 48px;
}
.cmd::before { content: '> '; content: '> ' / ''; }
.term { font-family: var(--term); font-size: 22px; line-height: 1.3; }

/* section heads: label, then a dithered rule out to the edge */
.sec {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0 0 22px;
  font-size: 12px;
  font-weight: normal;
  letter-spacing: 0.08em;
  line-height: 1;
}
.sec::after {
  content: '';
  flex: 1;
  height: 4px;
  background: var(--dither);
  transform-origin: left;
}
.tw-in.sec::after { animation: grow 0.45s steps(9, end) both; }
.block { margin-bottom: 56px; }

/* game-settings rows: LABEL ........ VALUE */
.kv { display: grid; grid-template-columns: max-content 1fr; column-gap: 14px; row-gap: 14px; line-height: 1.6; }
.kv > div { display: contents; }
.kv dt { white-space: pre; }
.kv dd { overflow-wrap: anywhere; }
.kv .dots { white-space: pre; }

.prose { font-family: var(--term); font-size: 22px; line-height: 1.3; max-width: 62ch; }
.prose + .prose { margin-top: 0.8em; }

/* the last line of every page: a prompt waiting for you */
.prompt { margin-top: 8px; font-family: var(--term); font-size: 22px; line-height: 1; }
.idle-caret { display: inline-block; width: 0.5em; height: 0.9em; vertical-align: -0.1em; background: var(--ink); animation: blink 1s steps(1, end) infinite; }

/* ─────────────── typewriter ───────────────
   Text stays in the layout from the start (transparent until typed), so nothing
   reflows while it types and screen readers get all of it straight away.
   Elements wait at opacity 0 until the typing reaches them. */
.js [data-tw]:not(.tw-armed) { visibility: hidden; animation: failsafe 0s 3s forwards; }
.tw-armed:not(.tw-done) :not(.tw-in, .tw-cur, .tw-off) { opacity: 0; }
.tw-armed:not(.tw-done) { cursor: pointer; }
.tw-armed:not(.tw-done) a { pointer-events: none; }
.tw-off { color: transparent; }
.tw-cur { background: currentColor; -webkit-text-fill-color: transparent; }

/* ── keyframes ── */
@keyframes boot { from { clip-path: inset(49.5% 0 49.5% 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes blink { 50% { visibility: hidden; } }
@keyframes appear { to { opacity: 1; } }
@keyframes unroll { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(-8px -8px -8px -8px); } }
@keyframes banner { 0%, 34%, 68% { visibility: visible; } 17%, 51% { visibility: hidden; } }
@keyframes drop-in { from { transform: translateY(-24px); opacity: 0; } 20% { opacity: 1; } to { transform: none; opacity: 1; } }
@keyframes grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes chosen { 0% { background: var(--ink); color: var(--paper); } 50% { background: transparent; color: var(--ink); } }
@keyframes float-up { from { margin-top: 0; } 80% { opacity: 1; } to { margin-top: -22px; opacity: 0; } }
@keyframes failsafe { to { visibility: visible; } }

@media (max-width: 560px) {
  body { font-size: 10px; }
  .hud { grid-template-columns: 1fr auto; padding-top: 12px; }
  .hud .score.hi { display: none; }
  .stage-nav { margin-left: -4px; }
  .stage-toggle { font-size: 9px; gap: 8px; padding: 8px 10px 8px 4px; }
  .title-card { gap: 14px; margin-bottom: 24px; }
  .title-card .sprite { --s: 2; }
  .console, .term, .prose, .prompt { font-size: 20px; }
  .kv { grid-template-columns: 1fr; row-gap: 4px; }
  .kv dd { padding-left: 2ch; margin-bottom: 10px; }
  .kv .dots { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .crt, .title-card h1, .title-card .sprite, .tw-in.sec::after { animation: none; }
  .idle-caret { animation: none; }
  .dropdown:not([hidden]), .dropdown:not([hidden]) li { animation: none; }
  .dropdown li { opacity: 1; }
}

/* ═════════════ page parts ═════════════ */

/* ── about: player card ── */
.profile { display: grid; grid-template-columns: auto 1fr; gap: 32px 48px; align-items: start; }
.portrait { display: grid; justify-items: center; gap: 18px; padding: var(--px); }
/* a black gap between frame and photo keeps a bright background from merging into the frame */
.portrait canvas { display: block; box-sizing: content-box; width: 240px; height: 280px; padding: var(--px); image-rendering: pixelated; background: var(--paper); }
.portrait figcaption { display: flex; align-items: center; gap: 10px; font-size: 10px; line-height: 1; letter-spacing: 0.08em; }
.portrait .sprite { --s: 2; }
.profile .sec { margin-top: 4px; }

/* ── experience: mission log, laid out like the attract-mode score table ── */
.attract { text-align: center; font-size: 13px; font-weight: normal; letter-spacing: 0.08em; line-height: 1.4; margin: 0 0 44px; }
.table { list-style: none; padding: 0; display: grid; gap: 56px; margin-bottom: 64px; }
.entry { display: grid; grid-template-columns: 56px 1fr; gap: 0 20px; }
.entry > .sprite { justify-self: center; margin-top: 1px; }
.entry-title { font-size: 14px; font-weight: normal; letter-spacing: 0.06em; line-height: 1.3; margin-bottom: 14px; }
.entry-role { font-size: 10px; line-height: 1.9; letter-spacing: 0.04em; margin-bottom: 4px; }
.entry-meta { margin-bottom: 16px; }


/* ── contact: comms menu ── */
.channels { list-style: none; padding: 0; display: grid; gap: 6px; }
.channels li { display: flex; }
.channel-link {
  flex: 0 1 auto;
  min-width: 0;
  display: grid;
  grid-template-columns: 17px max-content 1fr;
  align-items: center;
  gap: 14px;
  padding: 13px 14px 13px 8px;
  line-height: 1.5;
  text-decoration: none;
}
.channel-link .cursor { visibility: hidden; }
.channel-link.is-active .cursor { visibility: visible; animation: blink 0.8s steps(1, end) infinite; }
.channel-link .k, .channel-link .dots { white-space: pre; }
.channel-link .v { overflow-wrap: anywhere; }


/* wide screens: the cursor hangs in the margin so the labels line up with the rest of the page */
@media (min-width: 880px) {
  .channel-link { margin-left: -39px; }
}
@media (max-width: 640px) {
  .profile { grid-template-columns: 1fr; }
  .portrait { justify-self: center; }
}
@media (max-width: 560px) {
  .entry { grid-template-columns: 36px 1fr; gap: 0 12px; }
  .entry > .sprite { --s: 2; }
  .entry-title { font-size: 12px; }
  .channel-link { grid-template-columns: 1fr; row-gap: 8px; margin-left: -8px; }
  .channel-link .cursor, .channel-link .dots { display: none; }
}
