/* ==========================================================================
   INTENTIONAL INTERFACES — styles.css
   Pixel-art night-sky theme · mobile-first · WCAG 2.2 AA
   --------------------------------------------------------------------------
   HOW THIS FILE IS ORGANISED
   Every block is wrapped in  START / END  comments so you can search for a
   section name (e.g. "START: HEADER") and jump straight to it.

   TABLE OF CONTENTS
    1. TOKENS            colours, type, spacing, motion
    2. RESET + BASE      element defaults
    3. ACCESSIBILITY     skip link, focus rings, visually-hidden, motion
    4. LAYOUT            container, sections, grids
    5. HEADER + NAV      glass bar, menu, HUD, walking trail
    6. BUTTONS + CHIPS   buttons, filter chips, tags
    7. HERO SCENE        night sky, moon, peaks, Dee
    8. GAME LAYER        coins, gems, toast, speech bubble
    9. PROJECT CARDS     "levels" grid
   10. ABOUT             player card
   11. CONTACT FORM      fields, status messages
   12. FOOTER
   13. CASE STUDY        banner, meta, prose, figures, jump list
   14. LIGHTBOX          zoomable images
   15. UNLOCK + ERROR    locked project page, 4xx/5xx pages
   16. UTILITIES + PRINT
   ========================================================================== */


/* ===== START: 1. TOKENS ================================================== */
:root {
  /* --- colour: night-sky base (all pairs below checked for WCAG AA+) --- */
  --night-950: #0b0820;
  --night-900: #120d2e;
  --night-800: #1a1342;
  --night-700: #261b5c;
  --night-600: #3a2a85;

  /* --- colour: vivid accents --- */
  --teal:    #3df2d0;   /* primary action */
  --magenta: #ff5cc8;   /* highlights */
  --gold:    #ffd34d;   /* coins, stars */
  --violet:  #a98bff;   /* links on dark, secondary accents */
  --red:     #ff7a93;   /* errors */

  /* --- colour: text --- */
  --ink:     #f5f1ff;   /* 15:1+ on every night colour */
  --ink-dim: #cfc7f2;   /* 9:1+  */
  --muted:   #b3a9e0;   /* 6.9:1+ */
  --on-accent: #0b0820; /* dark text for use on teal / gold / magenta */

  /* --- glass (iOS-style translucent surfaces) --- */
  --glass-bg:     rgba(18, 13, 46, 0.78);
  --glass-bg-hi:  rgba(38, 27, 92, 0.72);
  --glass-line:   rgba(255, 255, 255, 0.20);
  --glass-shine:  rgba(255, 255, 255, 0.28);
  --glass-blur:   blur(18px) saturate(160%);

  /* --- type --- */
  --font-display: "Open Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-body:    "Open Sans", -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui,
                  "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --fs-0:  1rem;        /* body */
  --fs-1:  1.125rem;       /* lead */
  --fs-2:  clamp(1.25rem, 1.15rem + 0.5vw, 1.5rem);        /* h3 */
  --fs-3:  clamp(1.5rem, 1.3rem + 1vw, 2rem);         /* h2 */
  --fs-4:  clamp(1.9rem, 1.4rem + 2vw, 3rem);           /* h1 */
  --lh-body: 1.65;

  /* --- space (4px grid) --- */
  --sp-1: 0.25rem;  --sp-2: 0.5rem;  --sp-3: 0.75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;   --sp-6: 2rem;    --sp-7: 3rem;     --sp-8: 4.5rem;

  /* --- shape --- */
  --r-sm: 8px;  --r-md: 14px;  --r-lg: 24px;
  --pixel-border: 4px;               /* chunky "pixel" outline width */

  /* --- layout --- */
  --container: 70rem;
  --gutter: max(1rem, env(safe-area-inset-left));
  --header-h: 3.5rem;                /* used for scroll-padding */
  --trail-h: 1.5rem;

  /* --- motion --- */
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  --dur: 180ms;
}
/* ===== END: 1. TOKENS ==================================================== */


/* ===== START: 2. RESET + BASE ============================================ */
*, *::before, *::after { box-sizing: border-box; }

html {
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* keep anchor targets clear of the sticky header (WCAG 2.2: focus not obscured) */
  scroll-padding-top: calc(var(--header-h) + var(--trail-h) + 1rem + env(safe-area-inset-top));
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background:
    radial-gradient(60rem 30rem at 85% -5%, rgba(255, 92, 200, 0.16), transparent 70%),
    radial-gradient(50rem 28rem at 0% 15%, rgba(61, 242, 208, 0.10), transparent 70%),
    var(--night-900);
  color: var(--ink);
  font: 400 var(--fs-0) / var(--lh-body) var(--font-body);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
  overflow-wrap: break-word;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
h1, h2, h3, h4 { line-height: 1.15; margin: 0 0 var(--sp-3); text-wrap: balance; }
h1, h2, .display { font-family: var(--font-display); font-weight: 700; letter-spacing: 0.01em; }
h1 { font-size: var(--fs-4); }
h2 { font-size: var(--fs-3); }
h3 { font-size: var(--fs-2); font-weight: 700; }
h4 { font-size: var(--fs-1); font-weight: 700; }
p, ul, ol, dl, figure { margin: 0 0 var(--sp-4); }
p { max-width: 68ch; }               /* comfortable line length */
ul, ol { padding-left: 1.25rem; }
li + li { margin-top: var(--sp-2); }
strong, b { font-weight: 700; }
hr { border: 0; border-top: 2px dashed var(--night-600); margin: var(--sp-6) 0; }

a {
  color: var(--violet);
  text-decoration-thickness: 0.12em;
  text-underline-offset: 0.2em;
}
a:hover { color: var(--teal); }
::selection { background: var(--magenta); color: var(--on-accent); }
/* ===== END: 2. RESET + BASE ============================================== */


/* ===== START: 3. ACCESSIBILITY =========================================== */
/* Skip link: first thing keyboard users reach */
.skip-link {
  position: fixed; top: 0.5rem; left: 0.5rem; z-index: 1000;
  padding: 0.75rem 1rem;
  background: var(--gold); color: var(--on-accent);
  font-weight: 700; border-radius: var(--r-sm);
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

/* Visible focus: a bright ring with a dark inner ring so it works on any bg */
:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 3px;
  box-shadow: 0 0 0 6px var(--night-950);
  border-radius: 4px;
}
:focus:not(:focus-visible) { outline: none; }

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

/* Motion: the user's OS setting OR the on-page toggle (html[data-motion="off"]) */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
html[data-motion="off"] { scroll-behavior: auto; }
html[data-motion="off"] *, html[data-motion="off"] *::before, html[data-motion="off"] *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
}

/* Windows high-contrast / forced colours: keep borders visible */
@media (forced-colors: active) {
  .btn, .card, .chip, .glass { border: 2px solid CanvasText; }
}
/* ===== END: 3. ACCESSIBILITY ============================================= */


/* ===== START: 4. LAYOUT ================================================== */
.container { width: min(100% - 2 * var(--gutter), var(--container)); margin-inline: auto; }
.section { padding-block: var(--sp-7); position: relative; }
.section__eyebrow {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-family: var(--font-display); font-weight: 600;
  color: var(--gold); letter-spacing: 0.08em; text-transform: uppercase;
  font-size: 0.95rem; margin-bottom: var(--sp-2);
}
.section__intro { color: var(--ink-dim); font-size: var(--fs-1); max-width: 60ch; }
/* ===== END: 4. LAYOUT ==================================================== */


/* ===== START: 5. HEADER + NAV ============================================ */
/* The header is a "glass" bar: blurred, translucent, with a lit top edge.
   Fallbacks below keep text readable if blur isn't supported. */
.site-header {
  position: sticky; top: 0; z-index: 100;
  padding-top: env(safe-area-inset-top);
}
.site-header__bar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  min-height: var(--header-h);
  width: min(100% - 1rem, calc(var(--container) + 2rem));
  margin: 0.5rem auto 0;
  padding: 0.4rem 0.6rem 0.4rem 1rem;
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  border-radius: 999px;
  box-shadow: inset 0 1px 0 var(--glass-shine), 0 8px 30px rgba(0, 0, 0, 0.35);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
}
@media (prefers-reduced-transparency: reduce) {
  .site-header__bar, .glass { background: var(--night-800); -webkit-backdrop-filter: none; backdrop-filter: none; }
}

.brand {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  color: var(--ink); text-decoration: none;
  font-family: var(--font-display); font-weight: 700; font-size: 1.15rem;
  min-height: 44px;
}
.brand img { width: 20px; height: 20px; flex: none; }
.brand span { white-space: nowrap; font-size: 1rem; }
@media (min-width: 480px) { .brand span { font-size: 1.15rem; } }
.brand:hover { color: var(--teal); }

.site-nav { display: flex; align-items: center; gap: var(--sp-2); }
.site-nav__list {
  list-style: none; margin: 0; padding: 0;
  display: none;                     /* mobile: hidden until menu opens */
}
.site-nav__list li + li { margin: 0; }
.site-nav a.nav-link {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 0.9rem;
  color: var(--ink); text-decoration: none; font-weight: 600; border-radius: 999px;
}
.site-nav a.nav-link:hover { background: var(--glass-bg-hi); color: var(--teal); }
.site-nav a.nav-link[aria-current="page"],
.site-nav a.nav-link[aria-current="true"] { background: var(--night-600); color: var(--ink); }

/* Mobile menu: opens as a glass sheet under the bar */
.menu-toggle { min-width: 44px; }
.site-nav[data-open="true"] .site-nav__list {
  display: block; position: absolute; left: 0.5rem; right: 0.5rem; top: calc(100% + 0.5rem);
  padding: var(--sp-3);
  background: var(--glass-bg); border: 1px solid var(--glass-line); border-radius: var(--r-lg);
  box-shadow: inset 0 1px 0 var(--glass-shine), 0 18px 40px rgba(0, 0, 0, 0.5);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.site-nav[data-open="true"] .site-nav__list a.nav-link { width: 100%; padding: 0 1rem; }
.site-header { position: sticky; }
.site-header__inner { position: relative; }

/* HUD: coin + star counters (part of the optional game layer) */
.hud {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  margin: 0; padding: 0 0.6rem; min-height: 36px;
  border-radius: 999px; background: rgba(0, 0, 0, 0.28);
  font-family: var(--font-display); font-weight: 700; font-size: 1rem; color: var(--ink);
  white-space: nowrap;
}
.hud__item { display: inline-flex; align-items: center; gap: 0.3rem; }
.hud__item img { width: 16px; height: 16px; image-rendering: pixelated; }
.hud__num.bump { animation: bump 0.4s steps(4); }
@media (max-width: 519px) { .hud__stars { display: none; } }   /* keep the bar uncluttered on phones */
@keyframes bump { 50% { transform: translateY(-4px) scale(1.25); color: var(--gold); } }

/* Walking trail: doubles as a reading-progress indicator */
.trail {
  position: relative; height: var(--trail-h);
  width: min(100% - 1.5rem, calc(var(--container) + 1rem)); margin: 0.15rem auto 0;
  pointer-events: none;
}
.trail__track {
  position: absolute; left: 0; right: 0; bottom: 3px; height: 3px; border-radius: 2px;
  background: repeating-linear-gradient(90deg, var(--night-600) 0 6px, transparent 6px 10px);
}
.trail__fill {
  position: absolute; left: 0; bottom: 3px; height: 3px; width: 0; border-radius: 2px;
  background: repeating-linear-gradient(90deg, var(--teal) 0 6px, transparent 6px 10px);
}
.trail__dee {
  position: absolute; bottom: 4px; left: 0;
  width: 16px; height: 22px; margin-left: -8px;
  background: url("../img/pixel/dee-sheet.svg") 0 0 / 300% 100% no-repeat;
  animation: walk 0.5s steps(1) infinite;
}
@keyframes walk { 0% { background-position: 0 0; } 50% { background-position: 50% 0; } }

/* ≥ 860px: show the nav links inline, hide the menu button */
@media (min-width: 860px) {
  .site-nav .menu-toggle { display: none; }
  .site-nav__list { display: flex; gap: 0.15rem; }
}
/* Fallback when backdrop-filter is unsupported: use a solid surface */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header__bar, .site-nav[data-open="true"] .site-nav__list, .glass { background: var(--night-800); }
}
/* ===== END: 5. HEADER + NAV ============================================== */


/* ===== START: 6. BUTTONS + CHIPS ========================================= */
.btn {
  --btn-bg: var(--teal);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 48px; padding: 0.55rem 1.25rem;
  background: var(--btn-bg); color: var(--on-accent);
  font: 700 1rem/1.2 var(--font-body); text-decoration: none; cursor: pointer;
  border: 0; border-radius: var(--r-sm);
  /* chunky pixel drop-shadow */
  box-shadow: 0 var(--pixel-border) 0 rgba(0, 0, 0, 0.45), inset 0 2px 0 rgba(255, 255, 255, 0.45);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.btn:hover { color: var(--on-accent); transform: translateY(-2px); }
.btn:active { transform: translateY(2px); box-shadow: 0 0 0 rgba(0, 0, 0, 0.45), inset 0 2px 0 rgba(255, 255, 255, 0.45); }
.btn--gold    { --btn-bg: var(--gold); }
.btn--magenta { --btn-bg: var(--magenta); }
.btn--ghost {
  --btn-bg: transparent; color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--violet);
}
.btn--ghost:hover { color: var(--teal); box-shadow: inset 0 0 0 2px var(--teal); }
.btn--icon { padding: 0.4rem; min-width: 44px; min-height: 44px; border-radius: 999px; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-block: var(--sp-5); }

/* Toggle switch-style button (motion on/off) */
.toggle {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: 44px; padding: 0 0.8rem;
  background: rgba(0, 0, 0, 0.28); color: var(--ink);
  border: 1px solid var(--glass-line); border-radius: 999px;
  font: 600 0.9rem var(--font-body); cursor: pointer;
}
.toggle[aria-pressed="true"] { background: var(--night-600); border-color: var(--teal); }
.toggle__dot {
  width: 10px; height: 10px; background: var(--muted); border-radius: 2px;
}
.toggle[aria-pressed="true"] .toggle__dot { background: var(--teal); }

/* Filter chips (project filter) */
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); padding: 0; margin: var(--sp-5) 0; list-style: none; }
.chips li + li { margin: 0; }
.chip {
  min-height: 44px; padding: 0 1rem;
  background: var(--night-800); color: var(--ink);
  border: 2px solid var(--night-600); border-radius: 999px;
  font: 600 0.95rem var(--font-body); cursor: pointer;
}
.chip:hover { border-color: var(--violet); }
.chip[aria-pressed="true"] { background: var(--gold); color: var(--on-accent); border-color: var(--gold); }

.tag {
  display: inline-block; padding: 0.1rem 0.6rem; margin: 0 0.25rem 0.25rem 0;
  background: var(--night-700); color: var(--ink);
  border-radius: 999px; font-size: 0.85rem; font-weight: 600;
}
/* ===== END: 6. BUTTONS + CHIPS =========================================== */


/* ===== START: 7. HERO SCENE ============================================== */
.hero { padding-block: var(--sp-6) var(--sp-7); }
.hero__grid { display: grid; gap: var(--sp-6); align-items: center; }
.hero__kicker { color: var(--gold); font-family: var(--font-display); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; }
.hero h1 .accent { color: var(--teal); }
.hero__lead { font-size: var(--fs-1); color: var(--ink-dim); }

@media (min-width: 900px) {
  .hero__grid { grid-template-columns: 1.05fr 1fr; gap: var(--sp-7); }
}

/* The pixel "stage". --s is the size of one art pixel on screen. */
.scene {
  --s: clamp(3px, 1.1vw, 6px);
  --ground: calc(11 * var(--s));              /* height of grass + soil */
  position: relative; overflow: hidden; isolation: isolate;
  aspect-ratio: 4 / 3; width: 100%;
  border: var(--pixel-border) solid var(--night-600);
  border-radius: var(--r-md);
  box-shadow: 0 var(--pixel-border) 0 rgba(0, 0, 0, 0.5), 0 24px 60px rgba(255, 92, 200, 0.12);
  /* sky: hard colour stops = pixel-art banding instead of a smooth gradient */
  background: linear-gradient(
    var(--night-950) 0 16%, #120d3a 16% 32%, #1c1250 32% 46%,
    #2a1a6e 46% 58%, #43267f 58% 68%, #6a2d8f 68% 76%, #a23a97 76% 82%, #d04b9f 82% 100%);
}
.scene > * { position: absolute; }
.scene__stars {
  inset: 0 0 35% 0; background: url("../img/pixel/stars.svg") 0 0 / calc(96 * var(--s) / 2) auto repeat;
  image-rendering: pixelated; animation: twinkle 3s steps(2) infinite;
}
.scene__stars--b { background-position: 40% 30%; animation-delay: 1.5s; opacity: 0.8; }
@keyframes twinkle { 50% { opacity: 0.35; } }
.scene__moon { top: 8%; right: 10%; width: calc(24 * var(--s)); image-rendering: pixelated; filter: drop-shadow(0 0 22px rgba(245, 241, 255, 0.45)); }
.scene__ridge { left: 0; width: 100%; image-rendering: pixelated; }
.scene__ridge--far  { bottom: calc(var(--ground) - 2 * var(--s)); height: 38%; }
.scene__ridge--near { bottom: calc(var(--ground) - 2 * var(--s)); height: 24%; }
.scene__pine { bottom: calc(var(--ground) - 3 * var(--s)); width: calc(12 * var(--s)); image-rendering: pixelated; }
.scene__pine--1 { left: 6%; }
.scene__pine--2 { left: 17%; width: calc(9 * var(--s)); }
.scene__pine--3 { right: 8%; }
.scene__ground {
  left: 0; right: 0; bottom: -2px; height: calc(var(--ground) + 2px);
  background: url("../img/pixel/grass.svg") 0 0 / calc(16 * var(--s)) calc(8 * var(--s)) repeat-x;
  background-color: #2a1d6e;            /* fills any sub-pixel gap at small sizes */
  image-rendering: pixelated;
}
.scene__ground::after {                      /* soil below the grass tile */
  content: ""; position: absolute; left: 0; right: 0; top: calc(8 * var(--s)); bottom: 0; background: #2a1d6e;
}

/* ---- Dee (sprite sheet: frame 1 stand · 2 walk · 3 cheer) ---- */
.dee {
  --frame: 0;
  display: block; padding: 0; border: 0; cursor: pointer;
  width: calc(16 * var(--s)); height: calc(22 * var(--s));
  background: url("../img/pixel/dee-sheet.svg") calc(var(--frame) * 50%) 0 / 300% 100% no-repeat;
  background-color: transparent;
}
.scene .dee { left: 46%; bottom: calc(var(--ground) - 3 * var(--s)); animation: idle 1.2s steps(1) infinite; }
@keyframes idle { 50% { transform: translateY(calc(var(--s) * -1)); } }
.dee.is-cheering { --frame: 2; animation: hop 0.6s steps(6) 2; }
@keyframes hop { 50% { transform: translateY(calc(var(--s) * -8)); } }
.dee:focus-visible { outline-offset: 6px; }

.speech {
  left: 46%; bottom: calc(var(--ground) + 19 * var(--s) + 0.6rem);
  transform: translateX(-30%);
  max-width: 14rem; padding: 0.5rem 0.75rem;
  background: var(--ink); color: var(--on-accent);
  font: 600 0.9rem/1.35 var(--font-body);
  border-radius: var(--r-sm); border-bottom: 4px solid var(--violet);
}
.speech[hidden] { display: none; }
.speech::after {
  content: ""; position: absolute; left: 36%; bottom: -12px;
  border: 6px solid transparent; border-top-color: var(--violet);
}

/* decorative floating coins in the hero */
.scene .coin { width: calc(8 * var(--s)); height: calc(8 * var(--s)); }
.scene .coin--1 { left: 28%; bottom: 46%; }
.scene .coin--2 { left: 62%; bottom: 52%; animation-delay: 0.4s; }
.scene .coin--3 { left: 76%; bottom: 36%; animation-delay: 0.8s; }
/* ===== END: 7. HERO SCENE ================================================ */


/* ===== START: 8. GAME LAYER ============================================== */
/* A coin is a decorative sprite: spin in place + gentle float */
.coin {
  display: block; flex: none;
  width: 24px; height: 24px;
  background: url("../img/pixel/coin-sheet.svg") 0 0 / 400% 100% no-repeat;
  animation: coin-spin 0.8s steps(1) infinite, coin-float 2.2s ease-in-out infinite;
}
@keyframes coin-spin {
  0% { background-position: 0 0; } 25% { background-position: 33.333% 0; }
  50% { background-position: 66.667% 0; } 75% { background-position: 100% 0; }
}
@keyframes coin-float { 50% { transform: translateY(-6px); } }

/* Section coin: sits next to a section title; "collected" when scrolled to */
.coin-pickup { display: inline-block; vertical-align: middle; margin-right: 0.5rem; }
.coin-pickup.is-collected { animation: coin-pop 0.6s steps(6) forwards; }
@keyframes coin-pop { 40% { transform: translateY(-14px) scale(1.4); } 100% { transform: none; opacity: 0.45; filter: grayscale(1); } }
.game-off .coin-pickup, .game-off .gem, .game-off .hud, .game-off .trail__dee { display: none; }

/* Hidden gems: real buttons, so keyboard + screen-reader users can find them */
.gem {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0; border: 0; cursor: pointer;
  background: transparent;
}
.gem::before {
  content: ""; width: 24px; height: 24px;
  background: url("../img/pixel/gem.svg") center / contain no-repeat;
  animation: coin-float 2.6s ease-in-out infinite; opacity: 0.9;
}
.gem:hover::before { opacity: 1; filter: drop-shadow(0 0 8px var(--teal)); }
.gem.is-found { cursor: default; }
.gem.is-found::before { filter: grayscale(1) brightness(0.8); animation: none; }

/* Toast: small glass notification (role="status") */
.toast {
  position: fixed; z-index: 200; left: 50%; bottom: calc(1rem + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  width: min(100% - 2rem, 26rem); padding: var(--sp-4);
  background: var(--glass-bg); border: 1px solid var(--glass-line); border-radius: var(--r-lg);
  box-shadow: inset 0 1px 0 var(--glass-shine), 0 18px 40px rgba(0, 0, 0, 0.55);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.toast[hidden] { display: none; }
.toast h2 { font-size: 1.25rem; margin-bottom: var(--sp-2); display: flex; align-items: center; gap: var(--sp-2); }
.toast p { margin-bottom: var(--sp-3); color: var(--ink-dim); }
.toast .btn-row { margin: 0; }

/* confetti burst made of coins (created by JS) */
.burst { position: fixed; pointer-events: none; z-index: 300; width: 16px; height: 16px; background: url("../img/pixel/coin.svg") center / contain no-repeat; }
/* ===== END: 8. GAME LAYER ================================================ */


/* ===== START: 9. PROJECT CARDS ("LEVELS") ================================ */
.levels { display: grid; gap: var(--sp-5); grid-template-columns: 1fr; padding: 0; list-style: none; }
.levels > li { margin: 0; }
@media (min-width: 640px) { .levels { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .levels { grid-template-columns: repeat(3, 1fr); } }

.card {
  position: relative; height: 100%; display: flex; flex-direction: column;
  background: var(--night-800); border: var(--pixel-border) solid var(--night-600);
  border-radius: var(--r-md); overflow: hidden;
  box-shadow: 0 var(--pixel-border) 0 rgba(0, 0, 0, 0.45);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.card:hover, .card:focus-within { transform: translateY(-4px); border-color: var(--teal); }
.card__media { position: relative; aspect-ratio: 16 / 10; background: var(--night-700); overflow: hidden; }
.card__media img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.card__body { padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-2); flex: 1; }
.card__level { font-family: var(--font-display); font-weight: 600; color: var(--gold); font-size: 0.9rem; letter-spacing: 0.06em; text-transform: uppercase; margin: 0; }
.card__title { font-size: 1.25rem; margin: 0; }
/* the whole card is one link: the title link stretches over the card */
.card__title a { color: var(--ink); text-decoration: none; }
.card__title a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.card__title a:hover { color: var(--teal); }
.card__title a:focus-visible { outline-offset: -6px; box-shadow: none; }
.card__date { color: var(--muted); font-size: 0.9rem; margin: 0; }
.card__tags { margin-top: auto; padding-top: var(--sp-2); }

/* status badges: visited star + locked padlock */
.badge {
  position: absolute; top: 0.6rem; right: 0.6rem; z-index: 2;
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.2rem 0.6rem; border-radius: 999px;
  background: var(--glass-bg); border: 1px solid var(--glass-line);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  font-size: 0.8rem; font-weight: 700;
}
.badge img { width: 14px; height: 14px; image-rendering: pixelated; }
.badge[hidden] { display: none; }
.badge--visited { left: 0.6rem; right: auto; color: var(--gold); }
.card[hidden], .levels > li[hidden] { display: none; }
.levels__empty { color: var(--ink-dim); }
/* ===== END: 9. PROJECT CARDS ============================================= */


/* ===== START: 10. ABOUT (PLAYER CARD) ==================================== */
.about__grid { display: grid; gap: var(--sp-6); align-items: start; }
@media (min-width: 800px) { .about__grid { grid-template-columns: 1fr 1fr; } }

.player-card {
  background: var(--night-800); border: var(--pixel-border) solid var(--night-600);
  border-radius: var(--r-md); padding: var(--sp-5);
  box-shadow: 0 var(--pixel-border) 0 rgba(0, 0, 0, 0.45);
}
.player-card__head { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-4); }
.player-card__avatar {
  width: 88px; height: 88px; flex: none; border-radius: var(--r-sm);
  border: 3px solid var(--magenta); object-fit: cover; background: var(--night-700);
}
.player-card__name { margin: 0; font-size: 1.5rem; }
.player-card__class { margin: 0; color: var(--gold); font-weight: 700; }
.stats { display: grid; gap: var(--sp-3); margin: 0; }
.stats div { padding: var(--sp-3); background: var(--night-900); border-radius: var(--r-sm); border-left: 4px solid var(--teal); }
.stats dt { color: var(--muted); font-size: 0.85rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
.stats dd { margin: 0.15rem 0 0; color: var(--ink); }
.stats div:nth-child(2n) { border-left-color: var(--magenta); }
.stats div:nth-child(3n) { border-left-color: var(--gold); }
/* ===== END: 10. ABOUT ==================================================== */


/* ===== START: 11. CONTACT FORM =========================================== */
.contact__grid { display: grid; gap: var(--sp-6); }
@media (min-width: 860px) { .contact__grid { grid-template-columns: 0.8fr 1.2fr; } }
.form { display: grid; gap: var(--sp-4); }
.field label { display: block; font-weight: 700; margin-bottom: var(--sp-2); }
.field .hint { color: var(--muted); font-size: 0.9rem; font-weight: 400; }
.field input, .field textarea {
  width: 100%; min-height: 48px; padding: 0.7rem 0.9rem;
  background: var(--night-950); color: var(--ink);
  border: 2px solid var(--violet); border-radius: var(--r-sm);
  font: inherit;                       /* 16px+ stops iOS zooming on focus */
}
.field textarea { min-height: 9rem; resize: vertical; }
.field input:focus-visible, .field textarea:focus-visible { border-color: var(--teal); }
.field [aria-invalid="true"] { border-color: var(--red); }
.field__error { color: var(--red); font-weight: 600; margin: var(--sp-2) 0 0; }
.field__error[hidden] { display: none; }
.form__status { padding: var(--sp-4); border-radius: var(--r-sm); font-weight: 600; margin: 0; }
.form__status[hidden] { display: none; }
.form__status--ok  { background: rgba(61, 242, 208, 0.14); border: 2px solid var(--teal); }
.form__status--err { background: rgba(255, 122, 147, 0.14); border: 2px solid var(--red); }
.hp { position: absolute; left: -9999px; }   /* honeypot: hidden from people */
.contact-list { list-style: none; padding: 0; }
.contact-list li { margin-bottom: var(--sp-3); }
.contact-list strong { display: block; color: var(--gold); font-family: var(--font-display); }
/* ===== END: 11. CONTACT FORM ============================================= */


/* ===== START: 12. FOOTER ================================================= */
.site-footer {
  margin-top: var(--sp-7); padding-block: var(--sp-6);
  border-top: 4px solid var(--night-700); color: var(--muted); text-align: center;
}
.site-footer a { color: var(--ink-dim); }
.site-footer p { margin-inline: auto; }
/* ===== END: 12. FOOTER =================================================== */


/* ===== START: 13. CASE STUDY ============================================= */
.cs-hero { padding-block: var(--sp-6) var(--sp-5); }
.crumbs { margin-bottom: var(--sp-4); font-size: 0.95rem; }
.cs-hero__lead { font-size: var(--fs-1); color: var(--ink-dim); max-width: 60ch; }

/* banner = decorative header image: NOT zoomable */
.banner { margin: var(--sp-5) 0; border: var(--pixel-border) solid var(--night-600); border-radius: var(--r-md); overflow: hidden; background: var(--night-800); }
.banner img { width: 100%; max-height: min(60vh, 32rem); object-fit: cover; }

.meta {
  display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  margin: var(--sp-5) 0; padding: var(--sp-4);
  background: var(--night-800); border-radius: var(--r-md); border-left: 6px solid var(--magenta);
}
.meta dt { color: var(--muted); font-size: 0.85rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }
.meta dd { margin: 0.1rem 0 0; font-weight: 600; }

.cs-layout { display: grid; gap: var(--sp-6); }
@media (min-width: 1000px) { .cs-layout { grid-template-columns: 15rem minmax(0, 1fr); } }

/* "In this level" jump list */
.jump { font-size: 0.95rem; }
@media (min-width: 1000px) { .jump { position: sticky; top: calc(var(--header-h) + var(--trail-h) + 1.5rem); align-self: start; } }
.jump summary { cursor: pointer; font-family: var(--font-display); font-weight: 700; color: var(--gold); min-height: 44px; display: flex; align-items: center; }
@media (min-width: 1000px) { .js .jump summary { pointer-events: none; } .jump summary::-webkit-details-marker { display: none; } }
.jump ol { list-style: none; padding: 0; margin: 0; border-left: 3px solid var(--night-600); }
.jump a { display: block; padding: 0.45rem 0.8rem; color: var(--ink-dim); text-decoration: none; border-left: 3px solid transparent; margin-left: -3px; }
.jump a:hover { color: var(--teal); }
.jump a[aria-current="true"] { color: var(--ink); border-left-color: var(--teal); font-weight: 700; }

.prose > section { margin-bottom: var(--sp-7); }
.prose h2 { padding-top: var(--sp-2); }
.prose h2::before {                       /* pixel bullet before each section title */
  content: ""; display: inline-block; width: 0.55em; height: 0.55em; margin-right: 0.45em;
  background: var(--magenta); box-shadow: 0.2em 0.2em 0 var(--night-600);
}
.prose h3 { color: var(--teal); margin-top: var(--sp-5); }
.prose li { max-width: 68ch; }

/* figures: a gallery of project images, each opens in the lightbox */
.gallery { display: grid; gap: var(--sp-4); margin: var(--sp-5) 0; grid-template-columns: 1fr; }
@media (min-width: 700px) { .gallery[data-cols="2"] { grid-template-columns: repeat(2, 1fr); } .gallery[data-cols="3"] { grid-template-columns: repeat(3, 1fr); } }
.figure { margin: 0; }
.figure figcaption { margin-top: var(--sp-2); color: var(--muted); font-size: 0.9rem; max-width: none; }
.figure img { width: 100%; border-radius: var(--r-sm); background: var(--night-800); }
.zoom {
  position: relative; display: block; width: 100%; padding: 0; border: var(--pixel-border) solid var(--night-600);
  border-radius: var(--r-md); background: var(--night-800); cursor: zoom-in; overflow: hidden;
  transition: border-color var(--dur) var(--ease);
}
.zoom:hover { border-color: var(--teal); }
.zoom img { border-radius: 0; }
.zoom__hint {                              /* little magnifier chip in the corner */
  position: absolute; right: 0.6rem; bottom: 0.6rem; display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.3rem 0.65rem; border-radius: 999px; font-size: 0.8rem; font-weight: 700; color: var(--ink);
  background: var(--glass-bg); border: 1px solid var(--glass-line);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
/* plain (non-zoomable) inline images: store badges, press logos, decor */
.figure--plain img { width: auto; max-height: 4.5rem; }
.badges { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; margin: var(--sp-4) 0; }
.badges img { max-height: 3.25rem; width: auto; }

/* next / previous level navigation */
.pager { display: grid; gap: var(--sp-4); margin-top: var(--sp-7); }
@media (min-width: 640px) { .pager { grid-template-columns: 1fr 1fr; } }
.pager a {
  display: block; padding: var(--sp-4); background: var(--night-800); border: var(--pixel-border) solid var(--night-600);
  border-radius: var(--r-md); text-decoration: none; color: var(--ink); min-height: 44px;
}
.pager a:hover { border-color: var(--teal); }
.pager small { display: block; color: var(--gold); font-family: var(--font-display); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
.pager .next { text-align: right; }
/* ===== END: 13. CASE STUDY =============================================== */


/* ===== START: 14. LIGHTBOX =============================================== */
/* Uses the native <dialog> element: focus is trapped and Esc closes it. */
.lightbox {
  width: 100vw; max-width: none; height: 100vh; height: 100dvh; max-height: none;
  margin: 0; padding: 0; border: 0; color: var(--ink);
  background: rgba(7, 5, 22, 0.94);
}
.lightbox::backdrop { background: rgba(7, 5, 22, 0.8); }
.lightbox[open] { display: flex; flex-direction: column; }
.lightbox__bar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-2);
  padding: calc(0.5rem + env(safe-area-inset-top)) 0.75rem 0.5rem;
  background: var(--glass-bg); border-bottom: 1px solid var(--glass-line);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
}
.lightbox__tools { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.lightbox__count { color: var(--muted); font-size: 0.9rem; margin: 0; }
.lightbox__stage {
  flex: 1; overflow: auto; display: grid; place-items: center; padding: 0.75rem;
  touch-action: pan-x pan-y pinch-zoom; overscroll-behavior: contain;
}
.lightbox__img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; cursor: zoom-in; }
.lightbox[data-zoom="actual"] .lightbox__img { max-width: none; max-height: none; cursor: zoom-out; }
.lightbox__caption {
  margin: 0; padding: 0.6rem 1rem calc(0.6rem + env(safe-area-inset-bottom));
  background: var(--glass-bg); border-top: 1px solid var(--glass-line); text-align: center; max-width: none;
}
.lightbox .btn { min-height: 44px; padding-inline: 0.9rem; }
.gif-toggle { margin-top: var(--sp-2); }
/* ===== END: 14. LIGHTBOX ================================================= */


/* ===== START: 15. UNLOCK + ERROR PAGES =================================== */
.center-page { min-height: 70vh; display: grid; place-items: center; text-align: center; padding-block: var(--sp-7); }
.center-page .panel {
  max-width: 36rem; padding: var(--sp-6); background: var(--night-800);
  border: var(--pixel-border) solid var(--night-600); border-radius: var(--r-md);
  box-shadow: 0 var(--pixel-border) 0 rgba(0, 0, 0, 0.45);
}
.center-page .panel p { margin-inline: auto; }
.error-code { font-family: var(--font-display); font-weight: 700; font-size: clamp(4rem, 3rem + 8vw, 8rem); line-height: 1; margin: 0; color: var(--magenta); text-shadow: 6px 6px 0 var(--night-600); }
.center-page .dee { margin: var(--sp-4) auto; --s: 6px; animation: idle 1.2s steps(1) infinite; cursor: default; }
/* ===== END: 15. UNLOCK + ERROR PAGES ===================================== */


/* ===== START: 16. UTILITIES + PRINT ====================================== */
.text-center { text-align: center; }
.mx-auto { margin-inline: auto; }
.btn-row--center { justify-content: center; }
.dee[data-frame="1"] { --frame: 1; }
.dee[data-frame="2"] { --frame: 2; }
.gallery__caption { margin: calc(-1 * var(--sp-3)) 0 var(--sp-5); color: var(--muted); font-size: 0.9rem; max-width: none; }
.mt-0 { margin-top: 0; }
.nowrap { white-space: nowrap; }
[hidden] { display: none !important; }

@media print {
  body { background: #fff; color: #000; }
  .site-header, .trail, .hud, .toast, .lightbox, .skip-link, .menu-toggle, .zoom__hint, .coin, .gem { display: none !important; }
  a { color: #000; }
  .card, .player-card, .meta { border-color: #999; background: #fff; }
}
/* ===== END: 16. UTILITIES + PRINT ======================================== */

/* ===== START: SMALL-PHONE FIXES (320px) ================================ */
@media (max-width: 380px) {
  .site-header__bar { gap: var(--sp-2); padding-left: 0.75rem; }
  .brand span { font-size: 0.9rem; }
  .brand img { display: none; }
  .hud { display: none; }               /* progress is still shown in the trail */
}
/* Breadcrumb link: comfortable tap target */
.crumbs a { display: inline-flex; align-items: center; min-height: 44px; }
/* ===== END: SMALL-PHONE FIXES ========================================== */

/* ===== START: IMAGE SIZE LIMITS ========================================
   Project images never take over the screen. Click/tap always opens the full-size
   view in the zoom window.
   - normal images: shrink to fit a comfortable height, centered
   - tall images (flow charts, long screens): capped preview showing the top, fading out */
:root { --img-max-h: min(70vh, 36rem); }
.zoom img { display: block; width: auto; max-width: 100%; max-height: var(--img-max-h); height: auto; margin-inline: auto; object-fit: contain; }
.zoom--tall { max-height: var(--img-max-h); }
.zoom--tall img { width: 100%; max-height: none; height: var(--img-max-h); object-fit: cover; object-position: top center; }
.zoom--tall::after {                      /* soft fade so it reads as "there is more" */
  content: ""; position: absolute; inset: auto 0 0 0; height: 5rem; pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--night-800));
}
.zoom--tall .zoom__hint { z-index: 1; }
@media (max-width: 600px) { :root { --img-max-h: min(62vh, 30rem); } }
/* ===== END: IMAGE SIZE LIMITS ========================================== */

/* ===== START: PHONE SCREENS + SMALL IMAGES ==============================
   - phone: a mobile screen is shown at real device width (375px) and its full height,
     never cropped or stretched
   - natural: small images keep their own size (no blurry enlarging) */
.zoom--phone { width: min(100%, 375px); margin-inline: auto; max-height: none; }
.zoom--phone img { width: 100%; height: auto; max-height: none; object-fit: fill; }
.zoom--natural { width: fit-content; max-width: 100%; margin-inline: auto; }
.zoom--natural img { width: auto; max-width: 100%; height: auto; max-height: none; object-fit: fill; }
/* ===== END: PHONE SCREENS + SMALL IMAGES ================================= */

/* small-image galleries: tiles sit side by side and wrap, instead of one tall column */
.gallery:has(.zoom--natural) { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; gap: var(--sp-3); }
.gallery:has(.zoom--natural) .figure { flex: 0 0 auto; max-width: 100%; }
.zoom--natural .zoom__hint { padding: 0.2rem 0.5rem; right: 0.35rem; bottom: 0.35rem; }
/* small images placed one after another (not inside a gallery) flow side by side in a row */
.figure:has(> .zoom--natural) { display: inline-block; vertical-align: top; margin: 0 var(--sp-3) var(--sp-3) 0; max-width: 100%; }
/* ===== END: small images ===== */
