/* ==========================================================================
   Shamimeh — site styles
   Visual direction: docs/03-visual-direction.md (Poster × Quiet)
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
  --bg: #F7F6F7;
  --surface: #FFFFFF;
  --ink: #121313;
  --muted: #888989;          /* secondary text */
  --muted-strong: #888989;   /* same grey for small text; note: ~3.3:1 contrast */
  --grid-line: rgba(2, 2, 2, .1);
  --body-ink: #2A2A2B;
  --line: #DEDDDF;
  --accent: var(--ink);      /* overridden per case study */

  --display: "Stack Sans Text", "Helvetica Neue", Arial, sans-serif;
  --text: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;

  --s1: 8px;  --s2: 16px; --s3: 24px; --s4: 32px;
  --s6: 48px; --s8: 64px; --s12: 96px; --s16: 128px;

  --max: none;               /* full width; side margins come from --gutter */
  --gutter: 32px;            /* 16px on phones, see Responsive */
  --nav-h: 72px;

  --ease-out: cubic-bezier(.2, .7, .2, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--bg);
  color: var(--ink);
  font: 400 17px/1.6 var(--text);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
ul, ol { padding: 0; list-style: none; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 2px; }
[tabindex="-1"]:focus { outline: none; } /* headings focused by script after a section jump */
::selection { background: var(--ink); color: var(--bg); }

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.skip-link {
  position: absolute; left: var(--gutter); top: -100px; z-index: 100;
  background: var(--ink); color: var(--bg); padding: var(--s1) var(--s2);
  text-decoration: none; font-size: 14px;
}
.skip-link:focus { top: var(--s2); }

/* ---------- Type ---------- */
.display {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  line-height: .88;
  letter-spacing: 0;
}
.label {
  font: 600 13px/1 var(--display);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted-strong);
}
.lede { font-size: clamp(18px, 1.6vw, 20px); color: var(--body-ink); max-width: 56ch; }
.muted { color: var(--muted); }

/* ---------- Loading line ---------- */
.load-line {
  position: fixed; top: 0; left: var(--gutter); z-index: 60;
  width: 1px; height: 100vh; background: var(--ink);
  transform-origin: top; transform: scaleY(0);
  pointer-events: none;
}
.load-line.is-playing {
  animation: line-draw 1.1s var(--ease-in-out) .1s forwards, line-fade .6s ease 1.4s forwards;
}
@keyframes line-draw { to { transform: scaleY(1); } }
@keyframes line-fade { to { opacity: 0; } }

/* ---------- Reveal on scroll (only when JS is running) ---------- */
.js .reveal { opacity: 0; transform: translateY(16px); transition: opacity .8s ease, transform .8s var(--ease-out); }
.js .reveal.is-in { opacity: 1; transform: none; }

/* Hero text animates straight away, so the first screen is never blank */
.js .intro-in { opacity: 0; transform: translateY(20px); animation: intro .9s var(--ease-out) forwards; }
.js .intro-in:nth-child(2) { animation-delay: .08s; }
.js .intro-in:nth-child(3) { animation-delay: .16s; }
@keyframes intro { to { opacity: 1; transform: none; } }
.js .intro-done .intro-in { opacity: 1; transform: none; animation: none; } /* safety net, see site.js */

/* ---------- Site header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  box-shadow: inset 0 -1px 0 transparent; transition: box-shadow 250ms ease; /* line takes no space */
}
/* A line under the header once the page has scrolled (see site.js) */
.site-header.is-scrolled { box-shadow: inset 0 -1px 0 var(--line); }

/* ---------- Background grid (homepage hero and About intro) ----------
   Three faint lines split the content area into four columns, after
   maxosichka.com. The hero line draws down on the first of them. */
.page-grid {
  position: absolute; top: 0; bottom: 0; left: var(--gutter); right: var(--gutter);
  z-index: -1; pointer-events: none;
}
.page-grid span { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--grid-line); }
.page-grid span:nth-child(1) { left: 25%; }
.page-grid span:nth-child(2) { left: 50%; }
.page-grid span:nth-child(3) { left: 75%; }
@media (max-width: 700px) {
  .page-grid span:nth-child(1), .page-grid span:nth-child(3) { display: none; }
}
.site-header .wrap { height: var(--nav-h); display: flex; align-items: center; justify-content: space-between; }
.logo { display: block; height: 32px; }
.logo svg { display: block; height: 100%; width: auto; }
@media (max-width: 700px) { .logo { height: 16px; } }
.site-nav { margin-left: auto; } /* links sit on the right */
.site-nav ul { display: flex; gap: clamp(var(--s2), 3vw, var(--s4)); }
.site-nav a { text-decoration: none; font-size: 15px; position: relative; padding: 4px 0; }
.site-nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: right; transition: transform .35s var(--ease-out);
}
/* Underline only while hovering (or focused with the keyboard), never resting */
.site-nav a:focus-visible::after { transform: scaleX(1); transform-origin: left; }
@media (hover: hover) and (pointer: fine) {
  .site-nav a:hover::after { transform: scaleX(1); transform-origin: left; }
}

/* ---------- Mobile menu (phones only) ---------- */
.menu-toggle, .menu-close {
  display: none; background: none; border: 0; padding: 8px 0; cursor: pointer;
  font: 400 14px/1 var(--text); letter-spacing: .04em; text-transform: uppercase; color: var(--ink);
}
.mobile-menu {
  position: fixed; inset: 0; z-index: 90; background: var(--bg);
  display: flex; flex-direction: column; padding: 0 var(--gutter) var(--s3);
  opacity: 0; transition: opacity 250ms ease;
}
.mobile-menu[hidden] { display: none; }
.mobile-menu.is-open { opacity: 1; }
.mobile-menu-top { height: var(--nav-h); display: flex; align-items: center; justify-content: space-between; }
.mobile-menu nav { flex: 1; display: flex; flex-direction: column; justify-content: center; }
.mobile-menu li + li { border-top: 1px solid var(--ink); }
.mobile-menu nav a {
  display: block; text-align: center; padding: 26px 0; text-decoration: none;
  font: 400 18px/1 var(--text); letter-spacing: .06em; text-transform: uppercase;
  opacity: 0; transform: translateY(8px);
  transition: opacity 300ms ease, transform 400ms cubic-bezier(.23, 1, .32, 1);
}
.mobile-menu.is-open nav a { opacity: 1; transform: none; }
.mobile-menu.is-open li:nth-child(2) a { transition-delay: 40ms; }
.mobile-menu.is-open li:nth-child(3) a { transition-delay: 80ms; }
.mobile-menu.is-open li:nth-child(4) a { transition-delay: 120ms; }
.mobile-menu nav a:active { opacity: .5; }
.mobile-menu-foot { display: flex; justify-content: space-between; font-size: 14px; letter-spacing: .04em; text-transform: uppercase; }
.mobile-menu-foot a { text-decoration: none; padding: 8px 0; }

@media (max-width: 700px) {
  .site-nav { display: none; }
  .menu-toggle, .menu-close { display: block; }
}
@media (prefers-reduced-motion: reduce) {
  .mobile-menu nav a { transform: none; transition: opacity 200ms ease; }
}

/* ---------- Home: hero ----------
   Fits one screen. Layout and intro after bleibtgleich.dev (line draws down,
   type sharpens out of a blur); name sized after maxosichka.com. */
.hero { position: relative; z-index: 0; padding-block: var(--s3); min-height: calc(100svh - var(--nav-h)); }
.hero-grid {
  display: grid; grid-template-columns: calc(25% - var(--s4)) 1px minmax(0, 1fr); gap: var(--s4);
  align-items: stretch;
}
.hero-side { display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; }
.hero-line { background: var(--ink); width: 1px; transform-origin: top; }
.hero-main { display: flex; flex-direction: column; justify-content: flex-start; padding-top: clamp(80px, 20vh, 220px); min-width: 0; }
.hero-title { font-weight: inherit; }
.hero-hi { display: block; font: 300 16px/1.4 var(--text); color: var(--muted); margin-bottom: var(--s1); }
.hero-name { display: block; }
/* The name and the two text columns under it share the name's width */
.hero-block { width: fit-content; max-width: 100%; }
.hero-meta { display: flex; justify-content: space-between; gap: var(--s2) var(--s4); flex-wrap: wrap; margin-top: var(--s4); }
.hero-meta .hero-small:last-child { text-align: right; }
.hero-small { font: 300 16px/1.4 var(--text); color: var(--muted); }

/* "Sham", large and regular weight, after the name on maxosichka.com */
.hero-name { font-size: clamp(88px, 15vw, 260px); font-weight: 400; text-transform: none; letter-spacing: -.03em; line-height: .9; }
.hero-name .goo { display: block; white-space: nowrap; }
.goo.soft { color: var(--muted); }

.loader {
  position: fixed; left: var(--gutter); bottom: var(--s3); z-index: 70;
  font: 700 clamp(48px, 6vw, 96px)/1 var(--display); pointer-events: none; display: none;
}
.loader.is-on { display: block; }
.loader.is-done { opacity: 0; transition: opacity .4s ease; }

/* Hidden start state, only when the intro script can run */
.js [data-intro] .goo { opacity: 0; }
.js [data-intro] .goo.is-on { opacity: 1; }
.js [data-intro] .hero-line { transform: scaleY(0); transition: transform var(--line-dur, 1.2s) var(--ease-in-out); }
.js [data-intro] .hero-small, .js [data-intro] .hero-hi { opacity: 0; transition: opacity .8s ease; }
.js [data-intro].is-drawn .hero-line { transform: none; }
.js [data-intro].is-drawn .hero-small, .js [data-intro].is-drawn .hero-hi { opacity: 1; }

@media (max-width: 700px) {
  .hero-grid { grid-template-columns: 1px minmax(0, 1fr); gap: var(--s2); }
  .hero-side { display: none; }
  .hero-name { font-size: clamp(72px, 26vw, 140px); }
}

/* ---------- Home: work list ---------- */
.work { padding-bottom: var(--s12); }
.section-head { display: flex; justify-content: space-between; align-items: baseline; padding-bottom: var(--s3); border-bottom: 1px solid var(--ink); }
.work-list li { border-bottom: 1px solid var(--line); }
.work-item {
  display: grid; grid-template-columns: 72px minmax(0, 1fr) auto 40px; column-gap: var(--s3); align-items: center;
  padding: var(--s3) 0; text-decoration: none;
}
.work-item .num { font: 600 16px/1 var(--display); color: var(--muted-strong); }
.work-item .name { font-size: clamp(40px, 6vw, 80px); transition: transform 400ms var(--ease-out); }
.work-item .tags { font-size: 14px; color: var(--muted-strong); text-align: right; }
.work-item .arrow {
  width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--line);
  display: grid; place-items: center;
  transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease, transform 400ms var(--ease-out);
}

/* Hover (or keyboard focus) opens the row to show a thumbnail and the description */
.work-item .more {
  grid-column: 2 / -1; display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 450ms var(--ease-in-out);
}
.work-item .more-inner {
  min-height: 0; overflow: hidden; display: flex; align-items: flex-end; gap: var(--s4);
  opacity: 0; transform: translateY(8px); transition: opacity 250ms ease, transform 400ms var(--ease-out);
}
.work-item .thumb {
  flex: 0 0 auto; width: clamp(220px, 26vw, 400px); aspect-ratio: 16 / 10; margin-top: var(--s3); border-radius: 6px;
  background: var(--c); display: flex; align-items: center; justify-content: center; /* placeholder until real images */
}
.work-item .thumb .phone { width: 18%; aspect-ratio: 9 / 19; border-radius: 12px; border: 4px solid #0b0b0b; background: color-mix(in srgb, var(--c) 40%, #fff); transform: rotate(-5deg); }
.work-item .thumb .phone + .phone { transform: rotate(5deg) translateY(8px); margin-left: -4%; }
.work-item .line { max-width: 44ch; color: var(--body-ink); }

.work-item:focus-visible { outline-offset: -2px; }
.work-item:focus-visible .more { grid-template-rows: 1fr; }
.work-item:focus-visible .more-inner { opacity: 1; transform: none; }
.work-item:focus-visible .arrow { background: var(--ink); color: var(--bg); border-color: var(--ink); transform: rotate(-45deg); }
@media (hover: hover) and (pointer: fine) {
  .work-item:hover .more { grid-template-rows: 1fr; }
  .work-item:hover .more-inner { opacity: 1; transform: none; transition-delay: 80ms; }
  .work-item:hover .name { transform: translateX(8px); }
  .work-item:hover .arrow { background: var(--ink); color: var(--bg); border-color: var(--ink); transform: rotate(-45deg); }
}
@media (prefers-reduced-motion: reduce) {
  .work-item .more, .work-item .more-inner, .work-item .name, .work-item .arrow { transition: none; }
}

/* Case studies still in progress: no link, no hover, a quiet label */
.work-item.is-soon { grid-template-columns: 72px minmax(0, 1fr) auto auto; cursor: default; }
.work-item.is-soon .name { color: var(--muted-strong); }
.work-item .soon {
  font-size: 12px; font-weight: 500; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap;
  padding: 6px 12px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted-strong);
}

/* ---------- Footer / contact ---------- */
/* Dark footer with the animated avatar from the Framer site (Lottie, see site.js) */
.site-footer { background: var(--ink); color: var(--bg); padding: clamp(24px, 6vh, 96px) 0 clamp(16px, 3vh, 32px); }
/* Fills exactly one screen below the header; spacing shrinks on short screens */
.site-footer { min-height: calc(100svh - var(--nav-h)); display: flex; }
.site-footer > .wrap { flex: 1; display: flex; flex-direction: column; justify-content: center; }
.site-footer .footer-avatar, .site-footer .footer-base { margin-top: auto; } /* content centred, bottom row at the bottom */
.site-footer .footer-links { margin-bottom: clamp(24px, 6vh, 96px); }
.footer-avatar { width: clamp(64px, 12vh, 112px); aspect-ratio: 221 / 245; }
.footer-avatar img, .footer-avatar svg { display: block; width: 100%; height: 100%; }
.footer-avatar.is-playing img { display: none; }
.footer-title { font: 400 clamp(40px, min(6vw, 9vh), 104px)/1.05 var(--display); letter-spacing: -.03em; margin: clamp(12px, 3vh, 32px) 0 var(--s2); }
.footer-note { max-width: 46ch; font-weight: 300; color: #A9A9AA; margin-bottom: clamp(16px, 4vh, 48px); }
.footer-links { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); }
.footer-links a { font-size: 18px; text-decoration: none; border-bottom: 1px solid #555; padding-bottom: 2px; transition: border-color .3s; }
.footer-links a:hover { border-color: var(--bg); }
.footer-base { display: flex; justify-content: space-between; gap: var(--s2); flex-wrap: wrap; padding-top: var(--s3); border-top: 1px solid #2A2A2B; font-size: 14px; color: #A9A9AA; }
.site-footer :focus-visible { outline-color: var(--bg); }

/* ---------- About ----------
   After maxosichka.com: the big line sits in the first of four columns,
   intro and roles in the last two, with the same faint grid as the hero. */
.about { position: relative; z-index: 0; min-height: calc(100svh - var(--nav-h)); }
.about-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--s6);
  padding-top: var(--s6); padding-bottom: var(--s12);
}
.about-label { grid-column: 1 / -1; font: 400 12px/1 var(--text); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.about-label b { font-weight: 500; color: var(--ink); margin-right: 12px; }
.about-headline {
  grid-column: 1 / 2; margin-top: var(--s12);
  font: 400 clamp(36px, 3.4vw, 64px)/1.15 var(--display); letter-spacing: -.03em;
}
.about-side { grid-column: 3 / 5; margin-top: var(--s12); padding-top: 12px; }
.about-intro, .about-more p { font-size: 16px; line-height: 1.85; color: var(--body-ink); max-width: 56ch; }
.about-more p { margin-top: var(--s2); }
.see-more {
  background: none; border: 0; padding: 0 0 2px; margin-left: 4px; cursor: pointer;
  font: inherit; color: var(--ink); border-bottom: 1px solid currentColor;
}
.see-more:active { opacity: .6; }
.roles { margin-top: var(--s12); }
.role { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: var(--s4); align-items: baseline; padding: 22px 0; }
.role .when { font: 400 12px/1 var(--text); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.role .what { font: 400 clamp(18px, 1.6vw, 24px)/1.3 var(--display); letter-spacing: -.02em; }
.role .what a { text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: 2px; }

@media (max-width: 900px) {
  .about-grid { grid-template-columns: 1fr; }
  .about-headline, .about-side { grid-column: 1; }
  .about-headline { margin-top: var(--s8); font-size: clamp(36px, 9vw, 56px); }
  .about-side { margin-top: var(--s6); }
  .roles { margin-top: var(--s8); }
  .role { grid-template-columns: 1fr; gap: 8px; padding: 18px 0; }
}

/* ---------- Case study ---------- */
.case-page { --accent: #2F6B4F; }

.panel { padding: var(--s12) var(--gutter); border-bottom: 1px solid var(--line); scroll-margin-top: var(--nav-h); }
.panel-inner { max-width: var(--max); margin: 0 auto; height: 100%; }
.panel .label { display: block; margin-bottom: var(--s2); }
.panel h2 { font: 400 clamp(26px, min(3.4vw, 5.6vh), 54px)/1.1 var(--display); letter-spacing: -.02em; margin-bottom: var(--s3); max-width: 20ch; }
.panel p { color: var(--body-ink); max-width: 52ch; }
.panel p + p { margin-top: var(--s2); }
.panel-split { display: grid; grid-template-columns: 1fr 1.15fr; gap: var(--s8); align-items: center; height: 100%; }

.case-cover { background: var(--accent); color: #fff; }
.case-cover .label, .case-cover p { color: rgba(255,255,255,.82); }
.case-cover h1 { font-size: clamp(44px, 12vw, 200px); margin: var(--s2) 0 var(--s4); }
.case-cover .lede { color: #fff; max-width: 34ch; font-size: clamp(20px, 2vw, 26px); line-height: 1.4; }
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s3); margin-top: var(--s8); padding-top: var(--s3); border-top: 1px solid rgba(255,255,255,.35); }
.facts dt { font: 600 13px/1 var(--display); letter-spacing: .12em; text-transform: uppercase; color: rgba(255,255,255,.7); margin-bottom: 8px; }
.facts dd { font-size: 15px; }
.case-cover :focus-visible { outline-color: #fff; }

.media {
  background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  border-radius: 6px; aspect-ratio: 4 / 3; display: grid; place-items: center;
  color: var(--muted-strong); font: 600 13px/1 var(--display); letter-spacing: .12em; text-transform: uppercase;
}
.media .phone { height: 86%; max-height: 460px; width: auto; aspect-ratio: 9 / 19; border-radius: 32px; border: 8px solid #0b0b0b; background: color-mix(in srgb, var(--accent) 30%, #fff); display: grid; place-items: center; text-align: center; padding: 8px; }

.insights { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); margin-top: var(--s6); }
.insight { border-top: 2px solid var(--accent); padding-top: var(--s2); }
.insight .n { font: 400 44px/1 var(--display); letter-spacing: -.02em; color: var(--accent); }
.insight h3 { font: 400 22px/1.2 var(--display); letter-spacing: -.01em; margin: var(--s2) 0 var(--s1); }
.insight p { font-size: 15px; }

.features { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); margin-top: var(--s6); }
.feature .media { aspect-ratio: 3 / 4; margin-bottom: var(--s2); }
.feature h3 { font: 400 22px/1.2 var(--display); letter-spacing: -.01em; margin-bottom: var(--s1); }
.feature p { font-size: 15px; }

.metrics { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); margin-top: var(--s6); }
.metric { background: var(--surface); border: 1px solid var(--line); border-radius: 6px; padding: var(--s4); }
.metric .v { font: 400 clamp(44px, 4.4vw, 72px)/1 var(--display); letter-spacing: -.03em; }
.metric p { font-size: 15px; margin-top: var(--s2); }
.placeholder-note { display: inline-block; margin-top: var(--s4); font-size: 13px; color: var(--muted-strong); border: 1px dashed var(--muted); padding: 6px 12px; border-radius: 4px; }

.next-project { background: var(--ink); color: var(--bg); }
.next-project a { text-decoration: none; display: block; }
.next-project .label { color: #A9A9AA; }
.next-project .display { font-size: clamp(44px, 9vw, 160px); font-weight: 400; text-transform: none; letter-spacing: -.03em; line-height: 1; margin-top: var(--s2); transition: transform .5s var(--ease-out); }
.next-project a:hover .display, .next-project a:focus-visible .display { transform: translateX(12px); }
.next-project :focus-visible { outline-color: var(--bg); }

/* ---------- Every case-study section fits one screen ---------- */
.case-page .panel {
  min-height: calc(100svh - var(--nav-h)); display: flex; flex-direction: column; justify-content: center;
  scroll-snap-align: start;
}
.case-page .panel-inner { width: 100%; }
html:has(.case-page) { scroll-snap-type: y proximity; scroll-padding-top: var(--nav-h); }

/* ---------- Case study layout: left section menu (after maxosichka.com) ---------- */
.case-body { display: grid; grid-template-columns: 168px minmax(0, 1fr); gap: var(--s6); padding: 0 var(--gutter); }
.case-side { position: sticky; top: calc(var(--nav-h) + var(--s6)); align-self: start; padding-top: var(--s6); }
.case-side a {
  display: block; position: relative; padding: 9px 0 9px 22px; text-decoration: none;
  font: 600 13px/1 var(--display); letter-spacing: .12em; text-transform: uppercase; color: var(--muted-strong);
  transition: color .3s;
}
.case-side a::before {
  content: ""; position: absolute; left: 0; top: 50%; width: 8px; height: 1px; background: var(--muted);
  transition: width .35s var(--ease-out), background .35s;
}
.case-side a:hover { color: var(--ink); }
.case-side a[aria-current="step"] { color: var(--ink); }
.case-side a[aria-current="step"]::before { width: 16px; height: 2px; margin-top: -1px; background: var(--accent); }
.case-page .case-content .panel { padding: clamp(16px, 4vh, 48px) 0; } /* tighter on short screens */
.case-page .case-cover, .case-page .next-project { padding-inline: var(--gutter); }
.case-page .feature .media { aspect-ratio: auto; height: min(42vh, 400px); }
@media (min-width: 901px) { .case-page .case-progress { display: none; } }

/* ---------- Doone, chapter 1: The drop-off ---------- */
.dropoff-grid { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--s8); align-items: end; margin-top: var(--s4); }
.panel h2.scene { font: 400 clamp(32px, 3.8vw, 68px)/1.1 var(--display); letter-spacing: -.03em; max-width: 16ch; margin: 0; }
.dropoff-text { font-size: 16px; line-height: 1.8; max-width: 44ch; margin: 0; }

/* A thin reading-progress line fills, slows and stalls at 38%, then dims */
.stall { margin-top: clamp(48px, 10vh, 128px); padding-bottom: 40px; }
.stall-track { position: relative; height: 1px; background: var(--line); }
.stall-fill {
  position: absolute; left: 0; top: -1px; height: 3px; width: 38%; background: var(--accent);
  transform-origin: left; transition: background-color 900ms ease;
}
.stall-mark { position: absolute; left: 38%; top: -8px; width: 1px; height: 17px; background: var(--ink); }
.stall-mark span {
  position: absolute; top: 26px; left: 0; transform: translateX(-50%); white-space: nowrap;
  font: 400 12px/1 var(--text); letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
}
.js .stall .stall-fill { transform: scaleX(0); transition: transform 2600ms cubic-bezier(.12, .75, .25, 1), background-color 900ms ease; }
.js .stall .stall-mark { opacity: 0; transition: opacity 500ms ease; }
.js .stall.is-playing .stall-fill { transform: none; }
.js .stall.is-playing .stall-mark { opacity: 1; transition-delay: 2200ms; }
.js .stall.is-done .stall-fill { background: var(--muted); }
@media (prefers-reduced-motion: reduce) {
  .js .stall .stall-fill { transform: none; transition: none; }
  .js .stall .stall-mark { opacity: 1; transition: none; }
}
@media (max-width: 900px) {
  .dropoff-grid { grid-template-columns: 1fr; gap: var(--s4); }
}

/* Pump Game: the two research groups as players. The page turns amber while this
   chapter is in view. Sham chose the level map (round 11). */
html.is-amber {
  --bg: #B7791F; --muted: rgba(18, 19, 19, .68); --muted-strong: rgba(18, 19, 19, .68);
  --line: rgba(18, 19, 19, .2); --grid-line: rgba(18, 19, 19, .14);
}
/* Chapter 4: the page turns navy, with the launched game's glow, while the loops are in view */
html.is-navy, html.is-night {
  --bg: #0B1530; --ink: #FFFFFF; --body-ink: rgba(255, 255, 255, .82); --muted: #A9B4D3; --muted-strong: #A9B4D3;
  --line: rgba(255, 255, 255, .14); --grid-line: rgba(255, 255, 255, .08);
}
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none; opacity: 0; transition: opacity 600ms ease;
  background: radial-gradient(70% 60% at 55% 60%, #1D2F63 0%, rgba(29, 47, 99, 0) 70%), linear-gradient(180deg, #1C2846, #0B1530);
}
html.is-navy body::before { opacity: 1; }
/* Chapter 5: a darker, flat night so the screens carry the colour */
html.is-night { --bg: #050914; }
body { transition: background-color 600ms ease, color 600ms ease; }
.site-header { transition: box-shadow 250ms ease, background-color 600ms ease; }
/* Pump Game, chapter 2: a soft light follows the pointer while the page is amber.
   One fixed layer behind the content, moved with transform only. */
.page-light {
  position: fixed; left: 0; top: 0; z-index: -1; width: 720px; height: 720px; margin: -360px 0 0 -360px;
  border-radius: 50%; pointer-events: none; opacity: 0; will-change: transform;
  background: radial-gradient(closest-side, rgba(255, 222, 160, .55), rgba(255, 210, 130, .22) 55%, rgba(255, 210, 130, 0));
  transition: opacity 600ms ease;
}
html.is-amber .page-light.is-on { opacity: 1; }
/* Pump Game, chapter 2: the story, closing on a padlock that opens */
.why { display: grid; gap: var(--s4); max-width: 62ch; margin-top: var(--s4); }
.why p { margin: 0; font-size: 18px; line-height: 1.7; }
.why .why-key { display: flex; align-items: center; gap: 14px; font-size: clamp(20px, 2.2vw, 24px); line-height: 1.35; }
.why-key b { font-weight: 600; transition: opacity 400ms ease; }
.why-lock {
  flex: none; width: 40px; height: 40px; fill: none; stroke: var(--ink); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.why-shut, .why-open { transition: opacity 200ms ease, transform 450ms cubic-bezier(.23, 1, .32, 1); }
.why-open { opacity: 0; }
.why-key.is-open .why-shut { opacity: 0; }
.why-key.is-open .why-open { opacity: 1; transform: translateY(-1.5px); }
html.js .why-key:not(.is-open) b { opacity: .45; }
@media (prefers-reduced-motion: reduce) {
  .why-shut, .why-open, .why-key b { transition: none; }
}
@media (max-width: 800px) {
  .why p { font-size: 17px; }
  .why-lock { width: 34px; height: 34px; }
}

/* Pump Game, chapter 3: the reader makes a call. Ask, wait and done share one grid
   cell, so the card never changes height; the "Play" step lights up after a call. */
.bet-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s6); align-items: center; }
.panel .bet-hmw { margin: var(--s2) 0 var(--s3); color: var(--muted); font-size: 15px; }
.bet-demo { --navy: #0B1530; --navy-2: #1C2846; --gold: #F5B83D; --pg-muted: #A9B4D3; --ease-out: cubic-bezier(.23, 1, .32, 1); }
.call {
  padding: 24px; border-radius: 28px; color: #fff;
  background: radial-gradient(120% 80% at 50% 0%, #22346B 0%, rgba(34, 52, 107, 0) 60%), linear-gradient(180deg, var(--navy-2), var(--navy));
  box-shadow: 0 30px 60px -30px rgba(11, 21, 48, .55);
}
.panel .call-top {
  display: flex; justify-content: space-between; align-items: center; max-width: none;
  font: 600 12px/1 var(--text); letter-spacing: .06em; text-transform: uppercase; color: var(--pg-muted);
}
.call-tag { padding: 5px 9px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, .18); letter-spacing: .04em; }
/* The chart looks like the launched game's: blue area line, price axis on the right,
   a dashed line and blue tag at the current price, a gold line and tag at the start price. */
.call-chart {
  --blue: #2F7BFF; position: relative; display: grid; grid-template-columns: 1fr 72px; height: 200px; margin: 16px -24px 20px 0;
  background-image: linear-gradient(rgba(255, 255, 255, .04) 1px, transparent 1px); background-size: 100% 40px;
}
.cc-plot { position: relative; min-width: 0; }
.cc-plot svg { display: block; width: 100%; height: 100%; overflow: visible; }
.cc-grid line { stroke: rgba(255, 255, 255, .06); stroke-width: 1; vector-effect: non-scaling-stroke; }
.cc-area { fill: url(#cc-fill); }
.cc-line { fill: none; stroke: var(--blue); stroke-width: 2; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.cc-now, .cc-start { stroke-width: 1; vector-effect: non-scaling-stroke; }
.cc-now { stroke: rgba(47, 123, 255, .8); stroke-dasharray: 4 4; }
.cc-start { stroke: var(--gold); visibility: hidden; }
.call[data-state] .cc-start { visibility: visible; }
.cc-axis { position: relative; font: 500 11px/1 var(--text); font-variant-numeric: tabular-nums; color: var(--pg-muted); }
.cc-axis .cc-label, .cc-tag { position: absolute; left: 6px; translate: 0 -50%; white-space: nowrap; }
.cc-tag { left: 0; padding: 4px 6px; border-radius: 4px 0 0 4px; font-weight: 600; color: #fff; z-index: 1; }
.cc-tag--now { background: var(--blue); }
.cc-tag--start { background: var(--gold); color: var(--navy); display: none; }
.call[data-state] .cc-tag--start { display: block; }
.cc-tag:empty { display: none; }
.call-stage { display: grid; min-height: 104px; }
.call-ask, .call-wait, .call-done {
  grid-area: 1 / 1; align-self: center; transition: opacity 200ms ease, transform 300ms var(--ease-out), visibility 0s;
}
.call-wait, .call-done { opacity: 0; visibility: hidden; transform: translateY(6px); }
.call[data-state="running"] .call-ask, .call[data-state="done"] .call-ask { opacity: 0; visibility: hidden; transform: translateY(-6px); }
.call[data-state="running"] .call-wait, .call[data-state="done"] .call-done { opacity: 1; visibility: visible; transform: none; }
.panel .call-q { max-width: none; margin-bottom: 12px; font: 600 18px/1.2 var(--text); color: #fff; }
.call-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.call-btn {
  min-height: 52px; border: 0; border-radius: 16px; font: 700 17px/1 var(--text); color: #fff; cursor: pointer;
  transition: transform 120ms var(--ease-out), box-shadow 120ms var(--ease-out);
}
.call-btn--up { background: #22A565; box-shadow: 0 4px 0 #136B40; }
.call-btn--down { background: #E04848; box-shadow: 0 4px 0 #8E2424; }
.call-btn:active { transform: translateY(3px); box-shadow: 0 1px 0 rgba(0, 0, 0, .35); }
.call-btn:focus-visible, .call-again:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.call-wait { display: flex; align-items: center; gap: 16px; }
.call-wait-text { display: grid; gap: 10px; }
.panel .call-pills { display: flex; flex-wrap: wrap; gap: 8px; font-size: 13px; }
.call-pill { padding: 5px 10px; border-radius: 999px; font-variant-numeric: tabular-nums; }
.call-pill--start { background: var(--gold); color: var(--navy); }
.call-pill--now { background: #2F7BFF; color: #fff; }
.panel .call-outcome { max-width: none; font-size: 14px; color: var(--pg-muted); }
.call-outcome:empty { display: none; }
.panel .call-wait p { max-width: none; color: #fff; font-size: 16px; }
.call-ring { position: relative; flex: none; width: 56px; height: 56px; display: grid; place-items: center; }
.call-ring svg { position: absolute; inset: 0; transform: rotate(-90deg); }
.call-ring circle { fill: none; stroke: rgba(255, 255, 255, .12); stroke-width: 3; }
.call-ring .call-ring-run { stroke: var(--gold); stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 0; }
.call[data-state="running"] .call-ring-run { animation: call-ring 3s linear forwards; }
@keyframes call-ring { to { stroke-dashoffset: 1; } }
.call-num { font: 700 17px/1 var(--text); font-variant-numeric: tabular-nums; }
.call-done { display: grid; gap: 14px; justify-items: start; }
.panel .call-result { max-width: none; font: 600 clamp(20px, 2vw, 24px)/1.25 var(--display); color: var(--gold); }
.call-again {
  padding: 10px 16px; border: 1px solid rgba(255, 255, 255, .25); border-radius: 999px; background: none;
  font: 600 14px/1 var(--text); color: #fff; cursor: pointer; transition: transform 120ms var(--ease-out), background-color 200ms ease;
}
.call-again:active { transform: scale(.97); }
@media (hover: hover) and (pointer: fine) { .call-again:hover { background: rgba(255, 255, 255, .08); } }
.panel .call-note { max-width: none; margin-top: 12px; font-size: 13px; color: var(--muted); }
html:not(.js) .call-btns { display: none; }
html:not(.js) .call-done { opacity: 1; visibility: visible; transform: none; }
html:not(.js) .call-again { display: none; }

.bet-steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s3); margin: var(--s8) 0 0; padding: var(--s3) 0 0; list-style: none; border-top: 1px solid var(--line); }
.bet-step { position: relative; display: grid; gap: 8px; align-content: start; }
.bet-num {
  display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
  border: 1px solid var(--line); font: 600 14px/1 var(--text); color: var(--ink);
  transition: background-color 300ms ease, color 300ms ease, border-color 300ms ease;
}
.bet-step h3 { font: 600 20px/1.2 var(--display); color: var(--ink); }
.panel .bet-step p { font-size: 15px; }
.bet-here {
  justify-self: start; padding: 5px 10px; border-radius: 999px; background: #0B1530; color: #F5B83D;
  font: 600 12px/1 var(--text); opacity: 0; transform: translateY(4px); transition: opacity 300ms ease, transform 300ms cubic-bezier(.23, 1, .32, 1);
}
.bet-steps.is-played .bet-step--2 .bet-num { background: #0B1530; border-color: #0B1530; color: #F5B83D; }
.bet-steps.is-played .bet-here { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .call-ask, .call-wait, .call-done, .bet-here { transform: none !important; }
  .call[data-state="running"] .call-ring-run { animation: none; }
}
@media (max-width: 800px) {
  .bet-grid { grid-template-columns: 1fr; gap: var(--s4); }
  .bet-steps { grid-template-columns: 1fr; gap: var(--s3); margin-top: var(--s6); }
  .call { padding: 20px; border-radius: 22px; }
  .call-chart { margin-right: -20px; height: 180px; }
}

/* Pump Game, chapter 4: the two loops as a figure eight meeting at the ticket, drawn
   straight on the navy page (no frame). A token travels the path as the chapter scrolls by; tap a stop for its line. */
.loops-head { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--s6); align-items: end; }
.lp {
  --navy: #0B1530; --navy-2: #1C2846; --gold: #F5B83D; --blue: #2F7BFF; --pg-muted: #A9B4D3;
  margin: var(--s8) 0 0; color: #fff;
}
.lp-stage { position: relative; max-width: 880px; margin: 0 auto; aspect-ratio: 800 / 360; }
.lp-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.lp-path { fill: none; stroke: rgba(255, 255, 255, .1); stroke-width: 10; stroke-linecap: round; }
.lp-path--a { stroke: var(--blue); stroke-width: 3; }
.lp-path--b { stroke: var(--gold); stroke-width: 3; }
.lp-exit { stroke: rgba(255, 255, 255, .35); stroke-width: 2; stroke-dasharray: 4 6; }
.lp-token { fill: #fff; filter: drop-shadow(0 0 8px rgba(245, 184, 61, .9)); }
.lp-name, .lp-ticket, .lp-wallet, .lp-stop { position: absolute; translate: -50% -50%; }
.lp-name { font: 600 12px/1 var(--text); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
.lp-name--a { color: #8FB4FF; }
.lp-name--b { color: var(--gold); }
.lp-ticket {
  display: grid; justify-items: center; gap: 4px; padding: 10px 12px; border-radius: 16px; background: var(--navy);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .14); font: 600 12px/1 var(--text);
}
.lp-ticket svg { width: 26px; height: 26px; fill: none; stroke: var(--gold); stroke-width: 1.6; stroke-linejoin: round; }
.lp-wallet {
  padding: 8px 14px; border-radius: 999px; background: #22A565; box-shadow: 0 3px 0 #136B40;
  font: 600 13px/1 var(--text); white-space: nowrap;
}
.lp-stop {
  display: flex; align-items: center; gap: 8px; padding: 0; border: 0; background: none; color: #fff; cursor: pointer;
  font: 600 14px/1.2 var(--text); white-space: nowrap;
}
.lp-stop .lp-label { position: absolute; transition: color 200ms ease; }
.lp-stop--above .lp-label { bottom: calc(100% + 8px); left: 50%; translate: -50% 0; }
.lp-stop--below .lp-label { top: calc(100% + 8px); left: 50%; translate: -50% 0; }
.lp-stop--left .lp-label { right: calc(100% + 10px); }
.lp-stop--right .lp-label { left: calc(100% + 10px); }
.lp-dot {
  display: grid; place-items: center; flex: none; width: 30px; height: 30px; border-radius: 50%;
  background: var(--navy); box-shadow: inset 0 0 0 2px var(--blue); font: 700 13px/1 var(--text); color: #fff;
  transition: transform 200ms cubic-bezier(.23, 1, .32, 1), background-color 200ms ease;
}
.lp-stop--b .lp-dot, .lp-dot--b { box-shadow: inset 0 0 0 2px var(--gold); }
.lp-stop:active .lp-dot { transform: scale(.94); }
.lp-stop.is-hit .lp-dot, .lp-stop[aria-pressed="true"] .lp-dot { background: var(--blue); transform: scale(1.12); }
.lp-stop--b.is-hit .lp-dot, .lp-stop--b[aria-pressed="true"] .lp-dot { background: var(--gold); color: var(--navy); }
.lp-stop:focus-visible { outline: none; }
.lp-stop:focus-visible .lp-dot { outline: 2px solid #fff; outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) { .lp-stop:hover .lp-label { color: var(--gold); } }
.panel .lp-caption { max-width: 52ch; min-height: 1.5em; margin: var(--s4) auto 0; text-align: center; font-size: 16px; color: var(--pg-muted); }
.lp-caption.is-set { color: #fff; }
.lp-list { display: none; }
@media (prefers-reduced-motion: reduce) {
  .lp-token { display: none; }
  .lp-dot { transition: none; }
}
@media (max-width: 800px) {
  .loops-head { grid-template-columns: 1fr; gap: var(--s3); }
  .lp { margin-top: var(--s6); }
  .lp-stage { margin: 0 -4px; }
  .lp-label, .lp-name, .lp-caption { display: none; }
  .lp-dot { width: 24px; height: 24px; font-size: 11px; }
  .lp-ticket { padding: 6px 8px; font-size: 10px; }
  .lp-ticket svg { width: 18px; height: 18px; }
  .lp-wallet { font-size: 11px; padding: 6px 10px; }
  .lp-list { display: grid; gap: 12px; margin: var(--s3) 0 0; padding: 0; list-style: none; }
  .lp-list li { display: flex; gap: 12px; align-items: flex-start; font-size: 15px; line-height: 1.4; color: var(--pg-muted); }
  .lp-list b { color: #fff; }
}

/* Pump Game, chapter 5: three problems from version one. Picking one shows the
   Wallex-style screen with the problem pinned, then the game screen wipes up over it. */
.fx {
  --fx-ease: cubic-bezier(.77, 0, .175, 1);
  display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--s12);
  grid-template-areas: "head head" "list phone"; align-items: center;
}
.fx-head { grid-area: head; display: grid; gap: var(--s3); }
.fx-head h2 { max-width: 30ch; }
.fx-head p { max-width: 60ch; }
.fx-phone, .fx-list { margin-top: var(--s8); }
.fx-list { grid-area: list; display: grid; gap: 4px; max-width: 600px; padding: 0; list-style: none; }
.fx-item {
  display: grid; gap: 6px; width: 100%; padding: 18px 20px; border: 0; border-radius: 18px; background: none;
  color: var(--ink); font: inherit; text-align: left; cursor: pointer;
  transition: background-color 200ms ease, transform 160ms cubic-bezier(.23, 1, .32, 1);
}
.fx-saw { font-size: 19px; font-weight: 600; line-height: 1.3; }
.fx-changed { font-size: 16px; line-height: 1.5; color: var(--muted); transition: color 200ms ease; }
.fx-item[aria-pressed="true"] { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.fx-item[aria-pressed="true"] .fx-changed { color: var(--ink); }
.fx-item:active { transform: scale(.985); }
.fx-item:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .fx-item:hover { background: color-mix(in srgb, var(--ink) 4%, transparent); } }

.fx-phone { grid-area: phone; justify-self: center; display: grid; justify-items: center; gap: var(--s3); margin-inline: 0; margin-bottom: 0; }
.fx-screen { display: grid; width: min(300px, 72vw); }
.fx-track { grid-area: 1 / 1; position: relative; isolation: isolate; display: grid; aspect-ratio: 390 / 844; }
/* Screens settle in: a short fade with a touch of scale and blur, so the swap reads as one
   screen changing rather than two images crossing */
.fx-img {
  grid-area: 1 / 1; width: 100%; height: 100%; object-fit: cover; object-position: top; border-radius: 24px;
  opacity: 0; transform: scale(1.02); filter: blur(4px);
  transition: opacity 280ms cubic-bezier(.23, 1, .32, 1), transform 380ms cubic-bezier(.23, 1, .32, 1), filter 280ms ease;
}
.fx-img.is-on { opacity: 1; transform: none; filter: none; }
.fx-track--game { clip-path: inset(0 0 0 0 round 24px); transition: clip-path 700ms var(--fx-ease); }
.fx-track--game { overflow: hidden; border-radius: 24px; background: #0A1430; }
/* The coded prototype keeps its own 390x844 size and is scaled to the screen */
.fx-frame { position: absolute; top: 0; left: 0; width: 390px; height: 844px; border: 0; transform-origin: 0 0; }
.fx[data-v="v1"] .fx-track--game { clip-path: inset(100% 0 0 0 round 24px); transition-duration: 450ms; }
/* Tap areas over the real buttons: invisible until pressed, or flashed as a hint
   when someone taps the screen where there is no button */
.fx-hot {
  position: absolute; z-index: 1; padding: 0; border: 0; border-radius: 14px; background: transparent;
  color: transparent; font-size: 0; cursor: pointer;
  transition: transform 160ms cubic-bezier(.23, 1, .32, 1), background-color 200ms ease, box-shadow 200ms ease;
}
.fx-hot[hidden] { display: none; }
.fx-hot:active { transform: scale(.97); background: rgba(255, 255, 255, .18); }
.fx-hot:focus-visible { outline: 2px solid #F5B83D; outline-offset: 3px; }
.fx.is-hinting .fx-hot { background: rgba(47, 123, 255, .22); box-shadow: inset 0 0 0 2px rgba(91, 151, 255, .9); }
.fx-hint { font-size: 14px; color: var(--muted); text-align: center; }
.fx-toggle { display: inline-grid; grid-auto-flow: column; padding: 4px; border-radius: 999px; background: color-mix(in srgb, var(--ink) 7%, transparent); }
.fx-toggle button {
  padding: 10px 18px; border: 0; border-radius: 999px; background: none; color: var(--muted);
  font: 600 15px/1 var(--text); cursor: pointer; transition: background-color 200ms ease, color 200ms ease;
}
.fx-toggle button[aria-pressed="true"] { background: var(--ink); color: var(--bg); }
.fx-toggle button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
html:not(.js) .fx-toggle, html:not(.js) .fx-hint, html:not(.js) .fx-hot { display: none; }
@media (prefers-reduced-motion: reduce) {
  .fx-img { transform: none; filter: none; transition: opacity 200ms ease; }
  .fx-track--game, .fx-item, .fx-hot { transition: none; }
}
@media (max-width: 800px) {
  .fx { grid-template-columns: 1fr; grid-template-areas: "head" "phone" "list"; }
  .fx-phone { margin-top: var(--s6); }
  .fx-list { margin-top: var(--s4); }
  .fx-item { padding: 14px 16px; }
  .fx-saw { font-size: 17px; }
}

/* Pump Game, chapter 6: the reflection as the game's ladder. A rung is won (green
   tick) as it scrolls past the middle of the screen, and a green rail climbs to it;
   the last rung banks the launch with a Tether coin. Without JS every rung shows won. */
.lad {
  --won: #22A565; --ease-out: cubic-bezier(.23, 1, .32, 1);
  position: relative; display: grid; gap: var(--s6); max-width: 760px; margin: var(--s8) 0 0; padding: 0; list-style: none;
}
.lad::before, .lad::after {
  content: ""; position: absolute; left: 21px; top: 22px; bottom: 22px; width: 2px; border-radius: 2px;
}
.lad::before { background: var(--line); }
.lad::after { background: var(--won); transform-origin: top; transform: scaleY(var(--lad-fill, 1)); transition: transform 600ms var(--ease-out); }
.lad-rung { position: relative; display: grid; grid-template-columns: 44px minmax(0, 1fr); column-gap: var(--s3); align-items: start; }
.lad-rung > div { padding-top: 8px; transition: opacity 400ms ease; }
.lad-rung h3 { margin: 0 0 8px; font-size: 22px; line-height: 1.25; font-weight: 600; }
.lad-rung p { margin: 0; max-width: 60ch; }
.lad-dot {
  position: relative; z-index: 1; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
  background: var(--won); color: #fff; font-weight: 600;
  transition: background-color 250ms ease, box-shadow 250ms ease, color 250ms ease, transform 320ms var(--ease-out);
}
.lad-dot > * { grid-area: 1 / 1; transition: opacity 200ms ease, transform 320ms var(--ease-out); }
.lad-dot b { opacity: 0; }
.lad-dot svg { width: 20px; height: 20px; fill: none; stroke: #fff; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.lad-dot--bank { background: none; }
.lad-dot--bank svg { width: 44px; height: 44px; stroke-width: 1.6; }
.lad-dot--bank circle { fill: #26A17B; stroke: none; }
.lad-dot--bank path { stroke-width: 2.2; }
.lad-bank { font-size: clamp(24px, 3vw, 34px); line-height: 1.2; font-weight: 600; letter-spacing: -.01em; }
.lad-rung .lad-note { margin-top: var(--s2); font-size: 15px; color: var(--muted); }
.lad-note a { color: inherit; text-underline-offset: 3px; }

/* Climbing, only with JS: rungs ahead are plain rings with their number */
html.js .lad-rung:not(.is-won) > div { opacity: .5; }
html.js .lad-rung:not(.is-won) .lad-dot { background: var(--bg); box-shadow: inset 0 0 0 2px var(--line); color: var(--muted); transform: scale(.92); }
html.js .lad-rung:not(.is-won) .lad-dot b { opacity: 1; }
html.js .lad-rung:not(.is-won) .lad-dot svg { opacity: 0; transform: scale(.8); }
html.js .lad-rung.is-current .lad-dot { box-shadow: inset 0 0 0 2px var(--ink); color: var(--ink); transform: none; }
html.js .lad-rung--bank:not(.is-won) .lad-dot svg { opacity: .35; transform: scale(.8); filter: grayscale(1); }
@media (prefers-reduced-motion: reduce) {
  .lad::after, .lad-dot, .lad-dot > *, .lad-rung > div { transition: none; }
}
@media (max-width: 800px) {
  .lad { gap: var(--s4); margin-top: var(--s6); }
  .lad::before, .lad::after { left: 17px; top: 18px; bottom: 18px; }
  .lad-rung { grid-template-columns: 36px minmax(0, 1fr); column-gap: var(--s2); }
  .lad-dot { width: 36px; height: 36px; }
  .lad-dot--bank svg { width: 36px; height: 36px; }
  .lad-rung > div { padding-top: 5px; }
  .lad-rung h3 { font-size: 19px; }
}

/* Pump Game, chapter 1: a Buy button that backs away from the reader's pointer (or
   jumps away when tapped), while Ben's fears from research appear under it. It pulses
   gently until someone tries it. Without JS it is a plain button and caption. */
.flee { margin-top: clamp(48px, 10vh, 128px); margin-bottom: 40px; }
.flee-stage {
  position: relative; height: 280px; overflow: hidden; border-radius: 24px;
  background: color-mix(in srgb, var(--ink) 4%, transparent); touch-action: manipulation;
}
.flee-buy {
  position: absolute; left: 50%; top: 50%; margin: -32px 0 0 -72px; width: 144px; height: 64px;
  border: 0; border-radius: 999px; background: var(--accent); color: #fff; font: 600 20px/1 var(--text); cursor: pointer;
  transition: transform 450ms cubic-bezier(.23, 1, .32, 1), background-color 200ms ease;
}
.flee-buy::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: 0 0 0 2px var(--accent);
  opacity: 0; pointer-events: none;
}
.js .flee:not(.is-tried) .flee-buy::after { animation: flee-pulse 2600ms cubic-bezier(.23, 1, .32, 1) 800ms infinite; }
@keyframes flee-pulse { 0% { opacity: .6; transform: scale(1); } 60%, 100% { opacity: 0; transform: scale(1.35); } }
.flee-buy:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.flee-thought { margin: var(--s3) 0 0; font-size: clamp(20px, 2.4vw, 26px); line-height: 1.3; font-weight: 600; transition: opacity 200ms ease, filter 200ms ease; }
.flee-thought.is-swapping { opacity: 0; filter: blur(2px); }
.flee-hint { margin: 6px 0 0; font-size: 15px; color: var(--muted); }
html:not(.js) .flee-hint { display: none; }
@media (prefers-reduced-motion: reduce) {
  .flee-buy, .flee-thought { transition: none; }
  .js .flee:not(.is-tried) .flee-buy::after { animation: none; }
}
@media (max-width: 600px) {
  .flee-stage { height: 220px; }
  .flee-buy { width: 128px; height: 56px; margin: -28px 0 0 -64px; font-size: 18px; }
}

/* ---------- Musō, chapter 1: The wall ----------
   The Sadeghi story beside Sham's photo of his poetry, fitted to one screen. */
.wall-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s8); align-items: center; margin-top: var(--s4); }
.wall-text { max-width: 46ch; margin-top: var(--s4); }
.wall-text p { font-size: 16px; line-height: 1.8; margin: 0; }
.wall-text p + p { margin-top: var(--s2); }
.wall-photo { margin: 0; justify-self: end; width: min(100%, calc((100svh - var(--nav-h) - 160px) * 1338 / 1400)); }
.wall-photo img { display: block; width: 100%; height: auto; border-radius: 16px; }
.wall-photo figcaption { margin-top: var(--s1); font-size: 13px; line-height: 1.4; color: var(--muted-strong); }
@media (max-width: 900px) {
  .wall-grid { grid-template-columns: 1fr; gap: var(--s4); }
  .wall-photo { justify-self: stretch; width: auto; }
}

/* ---------- Musō, chapter 2: What's really in the way ----------
   Screen 1: the literature mind map, zoomable through pins (Doone's .amap).
   Screen 2: the affinity board as a game. Notes scatter, then settle into their
   themes; the two lenses light up the notes behind each insight. Without JS the
   notes simply sit in their themes. */
.way-head { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: var(--s6); align-items: end; margin: var(--s2) 0 clamp(16px, 3vh, 32px); }
.way-head h2 { margin: 0; max-width: 20ch; }
.way-head p { margin: 0; font-size: 16px; line-height: 1.7; max-width: 46ch; }
.amap--lit { --mh: 46vh; }
.way-grid { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); gap: var(--s8); align-items: center; margin-top: var(--s4); }
.way-sub { font: 400 clamp(28px, 3vw, 48px)/1.1 var(--display); letter-spacing: -.02em; margin: 0 0 var(--s3); max-width: 14ch; }
.way-grid > div:first-child p { font-size: 16px; line-height: 1.75; max-width: 44ch; margin: 0 0 var(--s2); }
.way-link { color: var(--accent); text-underline-offset: 3px; }

.sort { --sort-ease: cubic-bezier(.77, 0, .175, 1); min-width: 0; }
.sort-board {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; padding: 16px;
  border-radius: 20px; background: color-mix(in srgb, var(--ink) 4%, var(--bg)); min-height: 240px; align-items: start;
}
.sort-theme {
  display: inline-block; padding: 6px 8px; border-radius: 6px; background: var(--ink); color: var(--bg);
  font: 600 11px/1.2 var(--text); letter-spacing: .06em; text-transform: uppercase;
  transition: opacity 300ms ease, transform 400ms cubic-bezier(.23, 1, .32, 1);
}
.sort-notes { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 12px; }
.note {
  display: block; width: 18px; height: 18px; border-radius: 3px; box-shadow: 0 1px 2px rgba(18, 19, 19, .12);
  transition: transform 800ms var(--sort-ease), opacity 250ms ease, box-shadow 250ms ease;
}
.note--blue { background: #9AA8F4; }
.note--pink { background: #F29AD8; }
.note--teal { background: #8EE0DA; }
.note--orange { background: #F9AE6E; }
.note--green { background: #7FD98A; }
.js .sort:not(.is-sorted) .sort-theme { opacity: 0; transform: translateY(4px); }
.sort[data-lens] .note { opacity: .16; }
.sort[data-lens="fear"] .note.is-fear,
.sort[data-lens="alone"] .note.is-alone { opacity: 1; transform: scale(1.3); box-shadow: 0 0 0 2px var(--ink); transition-duration: 300ms; }

.sort-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: var(--s2); }
.sort-lenses { display: flex; flex-wrap: wrap; gap: 8px; }
html:not(.js) .sort-bar { display: none; }
.sort-go, .sort-lens {
  min-height: 44px; padding: 0 18px; border-radius: 999px; border: 1px solid var(--line); background: var(--surface);
  color: var(--ink); font: 500 14px/1 var(--text); cursor: pointer;
  transition: transform 160ms cubic-bezier(.23, 1, .32, 1), background-color 200ms ease, color 200ms ease, border-color 200ms ease, opacity 200ms ease;
}
.sort-go { border-color: transparent; background: transparent; color: var(--muted-strong); padding: 0 10px; }
.sort-lens[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.sort-go:active, .sort-lens:active { transform: scale(.97); }
.sort-lens:disabled { opacity: .4; cursor: default; }
.sort-go:focus-visible, .sort-lens:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) {
  .sort-lens:not(:disabled):not([aria-pressed="true"]):hover { border-color: var(--ink); }
  .sort-go:hover { color: var(--ink); }
}
.sort-card { min-height: 128px; margin-top: var(--s2); transition: opacity 200ms ease, filter 200ms ease; }
.sort-card.is-swapping { opacity: 0; filter: blur(2px); }
.sort-card-hint { margin: 0; font-size: 14px; color: var(--muted-strong); }
.sort-card-title { margin: 0; font: 400 12px/1.3 var(--text); letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.sort-card blockquote { margin: 6px 0 10px; font: 400 clamp(18px, 1.7vw, 22px)/1.35 var(--display); letter-spacing: -.01em; }
.sort-card ul { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.sort-card li { padding: 4px 10px; border-radius: 999px; background: color-mix(in srgb, var(--ink) 5%, var(--bg)); font-size: 12px; line-height: 1.4; color: var(--muted-strong); }
.sort-card-src { margin: 10px 0 0; font: 400 11px/1.4 var(--text); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
@media (prefers-reduced-motion: reduce) {
  .note, .sort-theme, .sort-card { transition: opacity 200ms ease; }
}
@media (max-width: 900px) {
  .way-head, .way-grid { grid-template-columns: 1fr; gap: var(--s3); }
  .amap--lit { --mh: 40vh; }
}
@media (max-width: 600px) {
  .sort-board { gap: 8px; padding: 12px; }
  .sort-theme { font-size: 10px; padding: 5px 6px; }
  .note { width: 15px; height: 15px; }
  .sort-notes { gap: 4px; }
}

/* ---------- Musō, chapter 3: Inside the app ----------
   Screen and text are pinned together in one stage, like Doone: scrolling
   through the track only changes what they show (blur crossfades). The screen is
   frameless, 24px corners. The page takes Musō's orange (#EB5925) for the J3
   part and sky (#D2EBF3) for sharing and teams (600ms fade, set by the script).
   Ink on orange is about 5.2:1, so on orange the accent turns ink. */
html.is-ember {
  --bg: #EB5925; --muted: rgba(18, 19, 19, .7); --muted-strong: rgba(18, 19, 19, .7);
  --line: rgba(18, 19, 19, .22); --grid-line: rgba(18, 19, 19, .14); --body-ink: #121313;
}
/* the page accent is set inline on body, so this needs !important to win */
html.is-ember body.case-page { --accent: #121313 !important; }
html.is-sky { --bg: #D2EBF3; --line: rgba(18, 19, 19, .16); }
/* J6 + J7 part: dusk, #35322F. Text turns sand; the accent becomes the lighter
   Musō orange from the app's dark theme (#F58A66, about 5:1 on dusk). */
html.is-dusk {
  --bg: #35322F; --surface: #45413D; --ink: #F3F0E9; --body-ink: rgba(243, 240, 233, .86); --muted: rgba(243, 240, 233, .66); --muted-strong: rgba(243, 240, 233, .66);
  --line: rgba(243, 240, 233, .16); --grid-line: rgba(243, 240, 233, .08);
}
html.is-dusk body.case-page { --accent: #F58A66 !important; }
.case-page .panel.app { scroll-snap-align: none; }
/* The track sets how far you scroll; the stage inside it stays pinned. */
.js .app-track { height: calc(100svh - var(--nav-h) + var(--n) * 55svh); }
.app-stage { --sh: min(640px, calc(100svh - var(--nav-h) - 120px)); display: grid; grid-template-columns: auto minmax(0, 60ch); gap: var(--s6); align-items: center; margin-top: var(--s3); }
.js .app-stage { position: sticky; top: var(--nav-h); height: calc(100svh - var(--nav-h)); margin-top: 0; }
.app-screen { position: relative; margin: 0; height: var(--sh); aspect-ratio: 1170 / 2532; }
html:not(.js) .app-screen { position: sticky; top: calc(var(--nav-h) + 24px); align-self: start; }
.app-screen video {
  position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 24px; object-fit: cover; background: #F3F0E9;
  transition: opacity 400ms cubic-bezier(.23, 1, .32, 1), filter 400ms ease, transform 400ms cubic-bezier(.23, 1, .32, 1);
}
.js .app-screen video[hidden] { display: block; opacity: 0; filter: blur(4px); transform: scale(.985); }
.app-play {
  position: absolute; z-index: 1; left: 12px; bottom: 12px; padding: 8px 14px; border: 0; border-radius: 999px;
  background: rgba(37, 36, 34, .82); color: #F3F0E9; font: 400 13px/1 var(--text); cursor: pointer;
  transition: transform 160ms cubic-bezier(.23, 1, .32, 1);
}
.app-play:active { transform: scale(.97); }
.app-play:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
html:not(.js) .app-play { display: none; }
/* Panels share one place: stacked in the same grid cell, one shown at a time */
.app-panels { display: grid; gap: var(--s8); }
.js .app-panels { gap: 0; }
.js .app-panel {
  grid-area: 1 / 1; align-self: center; opacity: 0; transform: translateY(12px); filter: blur(3px); pointer-events: none;
  transition: opacity 400ms cubic-bezier(.23, 1, .32, 1), transform 400ms cubic-bezier(.23, 1, .32, 1), filter 400ms ease;
}
.js .app-panel.is-on { opacity: 1; transform: none; filter: none; pointer-events: auto; }
.app-part h2 { margin: 0 0 var(--s2); max-width: 18ch; }
.app-intro { margin: 0 0 var(--s3); font-size: 16px; line-height: 1.6; max-width: 54ch; }
.app-part:not(:first-child) .app-intro { margin-bottom: 0; }
.app-notes { margin: 0; padding: var(--s3) 0 0; list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3) var(--s4); border-top: 1px solid var(--line); }
.app-notes h3 { margin: 0 0 6px; font: 500 16px/1.3 var(--text); color: var(--ink); }
.app-notes h3::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 8px; border-radius: 50%; background: var(--accent); vertical-align: 2px; }
.app-notes p { margin: 0; font-size: 14px; line-height: 1.6; }
.app-feature h3 { margin: 0 0 var(--s2); font: 400 clamp(28px, 3vw, 44px)/1.1 var(--display); letter-spacing: -.02em; }
.app-feature p { margin: 0; font-size: 17px; line-height: 1.7; max-width: 46ch; }
@media (prefers-reduced-motion: reduce) {
  .app-screen video, .js .app-panel { transition: opacity 200ms ease; }
  .js .app-screen video[hidden], .js .app-panel { filter: none; transform: none; }
}
@media (max-width: 900px) {
  /* Phones: the screen pins under the header and the panels scroll beneath it */
  .js .app-track { height: auto; }
  .app-stage, .js .app-stage { --sh: 46svh; position: static; height: auto; display: block; }
  .app-screen { position: sticky; top: calc(var(--nav-h) + 8px); z-index: 1; margin: 0 auto; }
  .app-screen::before { content: ""; position: absolute; z-index: -1; inset: -8px 0 -16px; background: var(--bg); box-shadow: 0 0 0 100vmax var(--bg); clip-path: inset(0 -100vmax); transition: background-color 600ms ease, box-shadow 600ms ease; }
  .js .app-panels { gap: 0; }
  .js .app-panel { grid-area: auto; min-height: 52vh; display: flex; flex-direction: column; justify-content: center; opacity: .3; transform: none; filter: none; pointer-events: auto; }
  .js .app-panel.is-on { opacity: 1; }
  .app-part { padding: var(--s4) 0; }
  .app-notes { grid-template-columns: 1fr; }
}

/* ---------- Musō, chapter 4: Did it help? ----------
   Sham's finding from testing as a wall of notes (the sort game's colours).
   They drop in scattered and settle into a slight tilt as the wall comes into
   view, 80ms apart. Paraphrases, not quotes. */
.heard-head { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: var(--s6); align-items: end; margin-top: var(--s2); }
.heard-head h2 { margin: 0; max-width: 20ch; }
.heard-head p { margin: 0; font-size: 16px; line-height: 1.7; max-width: 46ch; }
.heard-wall { --ease: cubic-bezier(.23, 1, .32, 1); margin: var(--s6) 0 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); }
.heard-note {
  --tilt: -2deg; min-height: 200px; padding: var(--s3); border-radius: 4px; color: #121313;
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--s3);
  box-shadow: 0 1px 0 rgba(18, 19, 19, .06), 0 14px 24px -14px rgba(18, 19, 19, .35);
  transform: rotate(var(--tilt));
  transition: transform 700ms var(--ease) calc(var(--i) * 80ms), opacity 500ms ease calc(var(--i) * 80ms);
}
.heard-note:nth-child(2) { --tilt: 1.5deg; }
.heard-note:nth-child(3) { --tilt: -1deg; }
.heard-note:nth-child(4) { --tilt: 2deg; }
.heard-note--blue { background: #9AA8F4; }
.heard-note--pink { background: #F29AD8; }
.heard-note--orange { background: #F9AE6E; }
.heard-note--teal { background: #8EE0DA; }
.heard-note span { font: 400 12px/1 var(--text); letter-spacing: .08em; text-transform: uppercase; }
.heard-note p { margin: 0; font: 400 clamp(19px, 1.7vw, 24px)/1.25 var(--display); letter-spacing: -.01em; }
.js .heard-wall:not(.is-settled) .heard-note { opacity: 0; transform: translateY(48px) rotate(calc(var(--tilt) * 5)); }
@media (hover: hover) and (pointer: fine) {
  .heard-wall.is-settled .heard-note:hover { transform: translateY(-6px) rotate(0deg); transition-delay: 0ms; transition-duration: 250ms; }
}
.heard-foot { margin: var(--s6) 0 0; font-size: 16px; }
@media (prefers-reduced-motion: reduce) {
  .heard-note { transition: opacity 300ms ease; }
  .js .heard-wall:not(.is-settled) .heard-note { transform: rotate(var(--tilt)); }
}
@media (max-width: 900px) {
  .heard-head { grid-template-columns: 1fr; gap: var(--s3); }
  .heard-wall { grid-template-columns: 1fr 1fr; gap: var(--s3); }
  .heard-note { min-height: 160px; padding: var(--s2); }
  .heard-note p { font-size: 18px; }
}

/* ---------- Musō, chapter 5: What I'd test next ----------
   Sham's idea as a loop. The line draws from the top as the loop moves up the
   view (--p, set by the script, 0 to 1); each step lights up when the line
   reaches it. Without JS, or with reduced motion, the loop is drawn in full. */
.next-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 460px); gap: var(--s8); align-items: center; margin-top: var(--s3); }
.next-text h2 { margin: 0 0 var(--s3); max-width: 18ch; }
.next-text p { margin: 0 0 var(--s2); font-size: 16px; line-height: 1.7; max-width: 50ch; }
.next-text .next-take { margin-top: var(--s4); padding-top: var(--s3); border-top: 1px solid var(--line); font: 400 clamp(20px, 1.8vw, 24px)/1.35 var(--display); letter-spacing: -.01em; color: var(--ink); }
.loop { --p: 1; position: relative; width: 100%; aspect-ratio: 1; }
.js .loop { --p: 0; }
.loop svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.loop-track { fill: none; stroke: var(--line); stroke-width: 2; }
.loop-line { fill: none; stroke: var(--accent); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--p)); }
.loop-steps { margin: 0; padding: 0; list-style: none; }
.loop-step {
  position: absolute; left: var(--x); top: var(--y); transform: translate(-50%, -50%);
  width: max-content; max-width: 150px; padding: 8px 12px; border-radius: 12px; text-align: center;
  background: var(--bg); border: 1px solid var(--line); font-size: 14px; line-height: 1.3; color: var(--muted);
  transition: color 300ms ease, border-color 300ms ease, background-color 300ms ease;
}
.loop-step b { display: block; margin-bottom: 2px; font: 400 11px/1 var(--text); letter-spacing: .08em; color: inherit; }
.loop-step.is-hit, html:not(.js) .loop-step { color: var(--ink); border-color: var(--accent); }
.loop-step.is-hit b { color: var(--accent); }
@media (max-width: 900px) {
  .next-grid { grid-template-columns: 1fr; gap: var(--s6); }
  .loop { width: min(100%, 360px); justify-self: center; }
  .loop-step { max-width: 112px; padding: 6px 8px; font-size: 12px; }
}

/* ---------- Doone, chapter 2: zoomable affinity map ---------- */
.method-line { font: 400 12px/1.4 var(--text); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin: calc(-1 * var(--s2)) 0 clamp(12px, 2.5vh, 24px); }
.amap { position: relative; max-width: calc(var(--mh, 44vh) * var(--ar-w) / var(--ar-h)); margin-inline: auto; } /* card stays inside the frame */
.amap { --mh: 38vh; }
.amap--sketch { --mh: 32vh; }
.amap-view {
  position: relative; overflow: hidden; border-radius: 8px; background: #EFEEF0;
  aspect-ratio: var(--ar-w) / var(--ar-h); max-height: var(--mh, 44vh); margin-inline: auto;
}
.amap-stage { position: absolute; inset: 0; transform-origin: 0 0; transition: transform 900ms var(--ease-in-out); will-change: transform; }
.amap-stage img { display: block; width: 100%; height: 100%; }

/* Numbered pins with a soft pulse */
.pin {
  position: absolute; width: 30px; height: 30px; margin: -15px 0 0 -15px; border-radius: 50%; border: 0; cursor: pointer;
  background: var(--accent); color: #fff; font: 500 13px/30px var(--text); text-align: center; padding: 0;
  box-shadow: 0 4px 14px rgba(0,0,0,.18); transition: opacity 250ms ease, transform 200ms var(--ease-out);
}
.pin::after {
  content: ""; position: absolute; inset: -6px; border-radius: 50%; border: 2px solid var(--accent);
  opacity: 0; animation: pin-pulse 2.4s ease-out infinite;
}
@keyframes pin-pulse { 0% { transform: scale(.7); opacity: .6; } 100% { transform: scale(1.5); opacity: 0; } }
.pin:active { transform: scale(.94); }
.pin:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) { .pin:hover { transform: scale(1.08); } }
.amap.is-zoomed .pin { opacity: 0; pointer-events: none; }

.amap-back {
  position: absolute; top: 12px; left: 12px; z-index: 2; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); padding: 8px 14px; font: 400 13px/1 var(--text); color: var(--ink); cursor: pointer;
}
.amap-back:active { transform: scale(.97); }

/* Readable quotes card for the zoomed insight */
.amap-card {
  position: absolute; right: 16px; bottom: 16px; z-index: 2; width: min(380px, calc(100% - 32px));
  background: var(--surface); border-radius: 8px; padding: 18px 20px; box-shadow: 0 18px 48px rgba(0,0,0,.14);
  opacity: 0; transform: translateY(8px); pointer-events: none;
  transition: opacity 250ms ease, transform 350ms var(--ease-out);
}
.amap.is-zoomed .amap-card { opacity: 1; transform: none; pointer-events: auto; transition-delay: 550ms; }
.amap-card-title { font: 400 18px/1.25 var(--display); letter-spacing: -.01em; margin: 0 0 10px; }
.amap-card-title span { color: var(--accent); margin-right: 6px; }
.amap-quotes { display: grid; gap: 10px; margin: 0; }
.amap-quotes li { font-size: 14px; line-height: 1.5; color: var(--body-ink); padding-left: 12px; border-left: 2px solid var(--accent); }
.amap-quotes li.code { color: var(--muted); border-left-color: var(--line); }
.panel h2.bet-title { max-width: 26ch; }
.bet-text { max-width: 60ch; margin-bottom: clamp(12px, 3vh, 32px); }
.amap-hint { font: 400 12px/1.4 var(--text); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); text-align: center; margin-top: 12px; }
.amap-card-src { font: 400 11px/1.4 var(--text); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin: 12px 0 0; }

/* The three insights double as zoom controls */
.amap-insights { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); margin-top: var(--s3); }
.amap-item {
  display: block; width: 100%; text-align: left; background: none; border: 0; border-top: 2px solid var(--line);
  padding: 14px 0 0; cursor: pointer; color: inherit; font: inherit; transition: border-color 250ms ease;
}
.amap-item .n { font: 400 13px/1 var(--text); color: var(--accent); }
.amap-item .t { display: block; font: 400 20px/1.2 var(--display); letter-spacing: -.01em; margin: 8px 0 6px; }
.amap-item .l { display: block; font-size: 14px; line-height: 1.55; color: var(--body-ink); }
.amap-item[aria-pressed="true"] { border-top-color: var(--accent); }
@media (hover: hover) and (pointer: fine) { .amap-item:hover { border-top-color: var(--ink); } }
.amap-item:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

@media (max-width: 900px) {
  .amap { max-width: none; }
  .amap-view { max-height: none; }
  .amap-card { position: static; width: auto; margin-top: 12px; box-shadow: none; border: 1px solid var(--line); display: none; }
  .amap.is-zoomed .amap-card { display: block; }
  .amap-insights { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .amap-stage { transition: none; }
  .pin::after { animation: none; }
}

/* ---------- Case study progress nav ---------- */
.case-progress {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid var(--line);
  transition: transform .4s var(--ease-out);
}
.case-progress.is-hidden { transform: translateY(100%); }
.case-progress .wrap { display: flex; align-items: center; gap: var(--s3); height: 64px; }
.case-progress .current { display: none; }
.case-progress ol { flex: 1; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 6px; }
.case-progress a {
  display: block; text-decoration: none; font-size: 13px; color: var(--muted-strong);
  padding-top: 12px; position: relative; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.case-progress a::before, .case-progress a::after { content: ""; position: absolute; left: 0; top: 0; height: 2px; }
.case-progress a::before { right: 0; background: var(--line); }
.case-progress a::after { width: calc(var(--fill, 0) * 100%); background: var(--accent); }
.case-progress a[aria-current="step"] { color: var(--ink); font-weight: 500; }
.case-progress a:hover { color: var(--ink); }
@media (max-width: 900px) { .case-page main { padding-bottom: 56px; } } /* room for the bottom bar */

/* ---------- Responsive ---------- */
@media (max-width: 700px) { :root { --gutter: 16px; } }
/* phones: the research boards run edge to edge, so they read as large as they can */
@media (max-width: 700px) {
  .amap { margin-inline: calc(-1 * var(--gutter)); max-width: none; }
  .amap-view { border-radius: 0; max-height: none; }
  .pin { width: 34px; height: 34px; margin: -17px 0 0 -17px; line-height: 34px; }
}
@media (max-width: 900px) {
  .case-body { grid-template-columns: 1fr; padding: 0 var(--gutter); }
  .case-side { display: none; }
  .work-item { grid-template-columns: 40px minmax(0, 1fr) 36px; column-gap: var(--s2); }
  .work-item .num { grid-row: 1 / span 2; }
  .work-item .tags { grid-column: 2; grid-row: 2; text-align: left; margin-top: 6px; }
  .work-item .arrow { grid-column: 3; grid-row: 1 / span 2; width: 36px; height: 36px; }
  .work-item.is-soon { grid-template-columns: 40px minmax(0, 1fr); }
  .work-item.is-soon .num { grid-row: 1 / span 3; }
  .work-item .soon { grid-column: 2; grid-row: 3; justify-self: start; margin-top: var(--s2); }
  .panel-split { grid-template-columns: 1fr; gap: var(--s6); }
  .insights, .features, .metrics { grid-template-columns: 1fr; }
  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .case-progress .wrap { height: 56px; }
  .case-progress .current { display: block; flex: 1; font-size: 14px; font-weight: 500; }
  .case-progress ol { display: none; }
  .case-progress.is-open ol {
    display: grid; grid-auto-flow: row; position: absolute; left: 0; right: 0; bottom: 100%;
    background: var(--bg); border-top: 1px solid var(--line); padding: var(--s2) var(--gutter); gap: 0;
  }
  .case-progress.is-open a { padding: 12px 0; font-size: 16px; }
  .case-progress.is-open a::before, .case-progress.is-open a::after { display: none; }
  .case-progress .bar { position: absolute; left: 0; top: -1px; height: 2px; width: calc(var(--total, 0) * 100%); background: var(--accent); }
}
.case-progress .toggle {
  display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line); background: var(--surface);
  border-radius: 999px; padding: 6px 14px; font: 500 14px/1 var(--text); color: var(--ink); cursor: pointer;
}
@media (min-width: 901px) { .case-progress .bar, .case-progress .toggle { display: none; } }

/* ---------- Smooth scroll (Lenis) and text motion ---------- */
html.has-lenis { scroll-snap-type: none !important; scroll-behavior: auto !important; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-stopped { overflow: hidden; }
.case-page .launch { scroll-snap-align: start; }
.lines .w {
  display: inline-block; opacity: 0; translate: 0 .5em; filter: blur(5px);
  transition: opacity 600ms ease, translate 750ms var(--ease-out), filter 600ms ease;
  transition-delay: calc(var(--l, 0) * 90ms);
}
.lines.is-in .w { opacity: 1; translate: 0 0; filter: none; }
.tx { opacity: 0; translate: 0 12px; transition: opacity 700ms ease 250ms, translate 800ms var(--ease-out) 250ms; }
.tx.is-in { opacity: 1; translate: 0 0; }

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  .load-line { display: none; }
  .js .reveal, .js .intro-in { opacity: 1; transform: none; animation: none; }
  .js [data-intro] .goo, .js [data-intro] .hero-small, .js [data-intro] .hero-hi { opacity: 1; }
  .js [data-intro] .hero-line { transform: none; }
  .loader { display: none !important; }
}
