:root {
  --ink: #0b0c0c;
  --grass: #0f7b3e;
  --link: #1453b8;
  --link-hover: #0b3a85;
  --sun: #ffd23f;
  --sky: #cdebff;
  --sand: #f4efdc;
  --font-body: "Atkinson Hyperlegible", system-ui, sans-serif;
  --ink-soft: #4b5157;
  --panel: var(--sky);   /* opaque: the hovering icons never show through */
  --font-fun: "Fredoka", "Atkinson Hyperlegible", system-ui, sans-serif;
  /* Spacing steps from the design system (4, 8, 12, 16, 20, 24 px). */
  --s1: .25rem; --s2: .5rem; --s3: .75rem; --s4: 1rem; --s5: 1.25rem; --s6: 1.5rem;
  /* The information cards: one width, one padding, one radius (cards are 16–20px in the design system).
     Text stays at about 70 characters a line, and the cards line up with the closing section. */
  --card-width: 44rem;
  --card-pad: var(--s6);
  --card-radius: 1rem;
  --gutter: clamp(var(--s4), 5vw, 4rem);
  /* Landscape between cards: about two fifths of the screen, so the playground shows between every pair
     of cards without a long empty stretch. Not in the spacing steps, which are for interface spacing:
     a proposed addition, "scene gap" (13 Nov 2026 handover). */
  --scene-gap: 40svh;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font: 400 1.125rem/1.55 var(--font-body);
  color: var(--ink);
  background: var(--sky);
}

/* The app's focus: the sun ring with an ink edge (docs/design/DESIGN_SYSTEM.md). */
:focus-visible { outline: 3px solid transparent; box-shadow: 0 0 0 4px var(--sun), 0 0 0 7px var(--ink) !important; }

.skip {
  position: absolute; left: .75rem; top: -6.25rem; z-index: 100;
  background: var(--sun); color: var(--ink); padding: .75rem 1rem; font-weight: 700;
  border: 3px solid var(--ink); border-radius: 10px;   /* as the app's skip link */
}
.skip:focus { top: .75rem; }

/* The walk: one fixed canvas behind everything. scene.js steps a pre-rendered camera
   along the path as you scroll. Each scene has its own frames (walk/<name>/NNN.webp). */
/* Canvas and still share one box (the whole viewport) and one fit (cover, centred), so the walk's last
   frame and the arrival still are the same picture in the same place. No zoom, filter or mask on either. */
.walk-canvas, .walk-still { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; background: #64cbf2; }
.walk-canvas { display: none; }
.walk .walk-canvas { display: block; }
.walk .walk-still { display: none; }
.walk-still img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; }
.walk-markers { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.mk { position: absolute; left: 0; top: 0; width: 56px; height: 68px; transform-origin: 0 0; opacity: 0; will-change: transform, opacity; }
.mk img { display: block; width: 56px; height: 68px; filter: drop-shadow(0 4px 6px rgb(11 12 12 / .25)); }
/* Nearby things, drawn like the app's tiles: colour for how far, dashed for not mapped yet. */
.poi { position: absolute; left: 0; top: 0; margin: 0; padding: 0; list-style: none; display: flex; gap: 6px; opacity: 0; will-change: transform, opacity; }
.poi li { width: 40px; height: 40px; box-sizing: border-box; display: grid; place-items: center; border-radius: 11px; border: 3px solid var(--ink); background: #fff; box-shadow: 0 3px 6px rgb(11 12 12 / .2); }
.poi img { display: block; width: 32px; height: auto; }
.poi-near { background: #b9e8c4 !important; }
.poi-short { background: #ffe58a !important; }
.poi-none { border-style: dashed !important; border-width: 2px !important; }
.poi-none img { opacity: .5; }
main, .closing, .site-footer { position: relative; z-index: 1; }

/* Opening: the walk. Tall, so there is path to walk; the slogan and cue stay put while you do. */
.opening { position: relative; min-height: 100svh; }
.walk .opening { height: 170svh; }   /* shorter walk, same 96 frames (12 Nov 2026 review) */
.opening-stage {
  position: sticky; top: 0; height: 100svh;
  display: flex; flex-direction: column; align-items: center; justify-content: space-between;
  padding: clamp(2rem, 5svh, 4rem) 1.25rem clamp(1.5rem, 5svh, 3rem); text-align: center;
}
/* Two parts, each with one job. Top: a smaller logo and its episode line, with no panel: they sit in the
   open sky at the top of every frame, portrait and landscape (founder, 13 Nov 2026). Lower down, on a small,
   flat sky panel that hugs its contents: what it's for and the way into the app, with "Find out more" under
   it. The panel stays because dark text over the path drops to 2.9:1 where it crosses the bench at the
   arrival on phones; it has no shadow so it sits quietly on the scene (founder brief, 13 Nov 2026). */
.opening-brand, .opening-cta { display: flex; flex-direction: column; align-items: center; gap: .5rem; }
.opening-cta { background: var(--panel); border-radius: var(--card-radius); }
.opening-brand { width: min(27rem, 100%); }
.opening-bottom { display: flex; flex-direction: column; align-items: center; gap: .75rem; width: 100%; }
.opening-cta { max-width: 26rem; padding: 1rem; gap: .75rem; }
.opening h1 { display: flex; flex-direction: column; align-items: center; margin: 0; }
/* The opening's own episode line. "Towards" starts with T, O, W: The One With. Left unexplained,
   with no letter highlighting (founder, 12 Nov 2026). */
/* Opening type: the logo leads; the episode line at body size; the purpose line at the site's h3 and lead
   size (1.3rem); the button and "Find out more" at body size, bold. */
.episode { margin: 0; font: 500 1.125rem/1.3 var(--font-fun); }
.purpose { margin: 0; font: 600 1.3rem/1.2 var(--font-fun); text-wrap: balance; }
.logo { display: block; width: min(17rem, 100%); height: auto; }
.opening .logo { width: min(13rem, 100%); }
.logo--footer { width: min(14rem, 100%); margin-bottom: 1rem; padding: .75rem 1rem; background: var(--sand); border-radius: 1rem; box-sizing: content-box; }
.opening .actions { justify-content: center; margin: 0; }
/* A plain link to read on: no bouncing arrow. */
.cue {
  display: inline-flex; align-items: center; gap: .5rem; min-height: 2.75rem; padding: .5rem 1rem;
  color: var(--link); background: var(--panel); border-radius: 1rem;
  font-weight: 700; text-decoration: underline; text-underline-offset: .2em; transition: opacity .4s;
}
.cue:hover { color: var(--link-hover); text-decoration-thickness: 3px; }
.opening.started .cue { opacity: 0; pointer-events: none; }

/* The information sections have no pictures of their own: the walk's arrival view stays behind all of
   them, exactly as the walk left it (no zoom, filter or mask). Only the cards of text move
   (founder, 11 Nov 2026). The closing section fades up out of it.
   Reading rhythm (13 Nov 2026 handover): card, landscape, card, landscape. Every section starts with the
   same stretch of landscape, so the gap between cards is the same whatever each card's length, and the
   last card has the same gap before the closing section. */
.scene { position: relative; padding-top: var(--scene-gap); }
.scene:last-of-type { padding-bottom: var(--scene-gap); }
.closing::before {
  content: ""; position: absolute; left: 0; right: 0; top: -14svh; height: 14svh; pointer-events: none; z-index: 0;
  background: linear-gradient(to bottom, transparent, var(--grass));
}

/* Every card is the same: one width, centred, one padding and radius, flat (soft shadows belong only to
   illustrations in the design system). Every card of text sits on a soft sky panel, so it never crosses
   the artwork (changed 11 Nov 2026). Opaque, so the hovering map icons never show through text or
   screenshots (12 Nov 2026). */
.scene-copy {
  position: relative; z-index: 1;
  width: min(var(--card-width), calc(100% - 2 * var(--gutter)));
  margin: 0 auto;
  padding: var(--card-pad);
  background: var(--panel); border-radius: var(--card-radius);
}
.scene-copy > :last-child { margin-bottom: 0; }

h1, h2, h3 { font-family: var(--font-fun); font-weight: 600; line-height: 1.15; margin: 0 0 var(--s3); text-wrap: balance; }
/* Every "The one with..." line (the opening's episode line and each section title) leans a little, as
   if someone is saying it (founder, 12 Nov 2026: subtle, not full italics). Fredoka has no italic and the
   browser's fake italic is too strong, so a gentle 6 degree skew instead. */
h2, .episode { transform: skewX(-6deg); transform-origin: 0 100%; }
h1 { font-size: clamp(2.2rem, 5.2vw, 3.6rem); }
/* Card type, top to bottom: section label (Fredoka 500, small, softer ink), the "The one with..." title
   (Fredoka 600), the lead line (1.3rem, the site's h3 size), then body text (1.125rem, the app's body size).
   One step of space between each, a bigger step above a sub-heading. */
h2 { font-size: clamp(1.75rem, 1.2rem + 2.2vw, 2.4rem); }
h3 { font-size: 1.3rem; font-weight: 600; line-height: 1.25; margin: var(--s6) 0 var(--s2); }
p { margin: 0 0 var(--s4); }
.lead { font-size: 1.3rem; line-height: 1.4; }
.eyebrow { font: 500 1rem/1.3 var(--font-fun); letter-spacing: .02em; color: var(--ink-soft); margin-bottom: var(--s2); }
.small { font-size: 1rem; }
.note { font-size: 1rem; }

/* Buttons: yellow is kept for the main action, the way into the app. Everything else is a plain link.
   Shape, hard ink shadow and press as the app's buttons (docs/design/DESIGN_SYSTEM.md, web/src/styles/global.css). */
.actions { display: flex; flex-wrap: wrap; gap: .75rem; }
.btn {
  display: inline-flex; align-items: center; justify-content: center; min-height: 52px; padding: .75rem 1.25rem; border-radius: 14px;
  background: var(--sun); color: var(--ink); font: 700 1.125rem/1.25 var(--font-body); text-align: center;
  text-decoration: none; border: 3px solid var(--ink); box-shadow: 0 4px 0 var(--ink);
  transition: transform .15s, box-shadow .15s;
}
.btn:hover { text-decoration: underline; text-underline-offset: .2em; }
.btn:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--ink); }
a.text-link, .scene-copy a:not(.btn) { color: var(--link); font-weight: 700; text-underline-offset: .2em; }
.text-link { display: inline-flex; align-items: center; min-height: 2.75rem; }

/* Screenshots: real captures from the app and the route demo, foreground content inside a panel.
   Phones stack each screen above its caption; wider screens put the pair side by side. No carousel. */
.shots { display: grid; gap: var(--s6); margin: var(--s6) 0; }
/* One frame for every capture, in both sections: the whole picture at its own proportions (the width and
   height attributes reserve the space; never cropped or stretched), one light edge, a radius that sits
   inside the card's, and the caption a step below it. */
.shots figure { margin: 0; }
.shots img {
  display: block; width: 100%; height: auto; object-fit: contain; background: #fff;
  border: 2px solid rgb(11 12 12 / .25); border-radius: .75rem;
}
.shots--phone img { max-width: 20rem; margin-inline: auto; }
.shots figcaption { margin-top: var(--s2); font-weight: 700; line-height: 1.4; text-align: center; text-wrap: balance; }
@media (min-width: 40.0625rem) {
  .shots { grid-template-columns: 1fr 1fr; align-items: start; }
  .shots--single { grid-template-columns: 1fr; }
}
.status { font-weight: 700; border-left: 4px solid var(--ink); padding-left: var(--s3); }

/* Side navigation: dots that expand on hover and focus */
.scene-nav {
  position: fixed; right: 1rem; top: 50%; transform: translateY(-50%);
  z-index: 50; display: flex; flex-direction: column; gap: .5rem; align-items: flex-end;
}
.scene-nav a {
  display: flex; align-items: center; gap: .5rem; min-height: 2.75rem; padding: 0 .5rem;
  color: var(--ink); text-decoration: none; font-weight: 700;
}
.scene-nav a::after {
  content: ""; width: 1rem; height: 1rem; border-radius: 50%;
  background: #fff; border: 3px solid var(--ink); flex: none;
}
.scene-nav a[aria-current="true"]::after { background: var(--ink); }
.scene-nav span {
  background: #fff; border: 2px solid var(--ink); border-radius: 999px; padding: .1rem .7rem;
  opacity: 0; transition: opacity .15s;
}
.scene-nav a:hover span, .scene-nav a:focus-visible span { opacity: 1; }


/* Closing */
.closing { background: var(--grass); color: #fff; }
/* The closing words and the footer line up with the cards' text: same width, same inset. */
.closing-inner { width: min(var(--card-width), calc(100% - 2 * var(--gutter))); margin: 0 auto; padding: 4rem var(--card-pad); }
.closing a:not(.btn) { color: #fff; }
.closing .small { color: #fff; }
.site-footer { background: var(--grass); color: #fff; padding: 0 calc(max(var(--gutter), (100% - var(--card-width)) / 2) + var(--card-pad)) 2rem; }

/* Reveal on scroll (only when JS and motion are allowed) */
.js .scene-copy { opacity: 0; transform: translateY(1.5rem); transition: opacity .6s ease, transform .6s ease; }
.js .scene-copy.in { opacity: 1; transform: none; }

/* Wider screens keep the cards clear of the side dots. */
@media (min-width: 40.0625rem) {
  :root { --gutter: 4rem; }
}
@media (max-width: 40rem) {
  /* No side dots on phones: they overlapped the text (founder approved, 10 Nov 2026). */
  .scene-nav { display: none; }
  /* Phone gutters and card padding from the design system's steps (16 and 20 px). */
  :root { --gutter: var(--s4); --card-pad: var(--s5); }
}

/* Reading mode (13 Nov 2026 handover): while a card fills the reading area, the playground's hovering icons
   fade back so they don't compete with it, and they return when the view is the playground again (scene.js).
   They are decorative and never take clicks, so nothing stops working while they are faded. */
.walk-markers { transition: opacity .4s ease; }
.walk-markers.reading { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .scene-copy { opacity: 1; transform: none; transition: none; }
  .cue, .btn, .walk-markers { transition: none; }
  .btn:active { transform: none; }
}
