/* Hallmark · check · built: the project · redesign: polish · genre: editorial · pages: / , /about, /cave · signature: the drawn portrait with its role doodles, the folder wall · labels: body face, untracked */
/* Hallmark · pre-emit critique: P4 H4 E4 S5 R4 V4 · weakest: E, content waited at opacity 0 for a scroll observer; reveals now move it, never hide it */
/* Hallmark · dismissed 41 · the hero roles bar is a 2px underline with no text on it, so it needs no text colour */
/* Hallmark · dismissed 25 · project folder copy is a two-line caption under a folder, not running prose */
/* Hallmark · dismissed 29 · the lightbox blur sits over the page photographs it frames, not over a flat field */
/* Hallmark · dismissed 30b · the second glyph set is the hand-drawn doodle art in the hero, not an icon library */
/* Hallmark · dismissed F24 · the mixtape shell is lab-only markup and never renders on a live page */
/* Hallmark · note · cassette j-card on /about keeps its printed caps: it is the object's own label, the user's illustration */
/* Hallmark · note · mixtape, deck, lcd, tldr and spec selectors are lab leftovers with no markup on any live page */

/* ============================================================
   DERRICK LIONARDY — PORTFOLIO
   Aesthetic: Retrofuturist Skeuomorphism
   Concept: physical analog electronics rendered on screen
   (Sony Walkman era, late-80s / early-90s consumer hardware)

   Every asset here is native SVG / CSS — no external image URLs,
   so nothing can 403 or go missing. The physical world is built,
   not linked.
   ============================================================ */

/* ---------- 1. TOKENS ---------- */
:root {
  /* ground — warm bone-grey plastic, like sun-aged device housing */
  --bg: #d9d6d0;
  --bg-deep: #cbc8c1;

  /* ink — warm near-black, never pure #000 */
  --ink: #181512;
  /* Both of these were too light to read. On the page ground (#d9d6d0)
     the old muted grey measured 3.71:1 and the faint one 2.13:1 — under
     the 4.5:1 that 13-20px body text needs, and the faint value was
     carrying real copy (captions, colophons, the footer line) at 13px.
     Darkened just enough to clear the bar on every surface here — the
     page, the footer's deeper floor, and the cream cassette shell —
     while staying clearly secondary to --ink. */
  --ink-muted: #524c42;
  --ink-faint: #625c51;

  /* the only colour on the page comes from the tapes */
  --cream: #d8d2ba;
  --dark: #1d1c1a;
  --green: #5d7c70;
  --tosca: #5fa79a;

  /* paper sticker */
  --paper: #f7efdf;
  --paper-edge: rgba(138, 112, 78, 0.18);
  --paper-rule: rgba(138, 112, 78, 0.14);

  /* hardware surfaces */
  --metal-1: #d2d4d3;
  --metal-2: #bfc3c2;
  --metal-3: #b2b8b8;
  --metal-dark-1: #a4a4a4;
  --metal-dark-2: #757575;

  /* LED / glow accents — warm phosphor amber, lights not links */
  --led: #ffd57e;
  --led-glow: rgba(255, 188, 92, 0.55);
  --vu-amber: #fae46f;
  --vu-amber-glow: rgba(250, 228, 111, 0.82);
  --chat-blue-1: #1d91ff;
  --chat-blue-2: #0475f2;

  /* the universal three-part physical shadow */
  --lift-1: 0 2px 4px rgba(0,0,0,0.10), 0 8px 16px rgba(0,0,0,0.10),
            inset 0 1px 0 rgba(255,255,255,0.70), inset 0 -2px 4px rgba(0,0,0,0.08);
  --lift-2: 0 10px 24px rgba(0,0,0,0.16),
            inset 0 1px 0 rgba(255,255,255,0.75), inset 0 -3px 6px rgba(0,0,0,0.10);
  --press: inset 0 2px 5px rgba(0,0,0,0.28), inset 0 -1px 0 rgba(255,255,255,0.35);

  /* motion — one decelerating spring curve governs the world */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);        /* strong ease-out for UI */
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);    /* strong ease-in-out for on-screen movement */
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);     /* iOS-like drawer curve */
  --dur: 220ms;
  --dur-sweep: 240ms;

  /* type */
  --font-screen: "Plus Jakarta Sans", system-ui, sans-serif;
  /* labels speak in the body face, a step smaller; a second grotesque
     beside Plus Jakarta Sans read as two voices arguing */
  --font-label: "Plus Jakarta Sans", system-ui, sans-serif;
  /* No script/handwriting webfont at all now — that whole category
     (Caveat, Homemade Apple, every "cute note" Google Font) reads as
     a costume the moment it carries real UI, not just a decorative
     flourish. The "personal annotation" feel now comes from the
     site's own display face set in italic (see every consumer of
     this variable, which also sets font-style: italic) plus the
     existing rotation/color treatment — considered emphasis instead
     of a font pretending to be a pen. */
  --font-hand: var(--font-screen);
}

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

html { scroll-behavior: smooth; overflow-x: clip; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-screen);
  letter-spacing: -0.01em;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* clip, not hidden: hidden makes body a scroll container and quietly
     breaks every position: sticky beneath it */
  overflow-x: clip;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button { font-family: inherit; cursor: pointer; }
/* tracking is size-specific, not one value for every heading level — the
   big display sizes (h1/h2) want negative tracking, but h3/h4 render as
   small as 16-18px in practice (.prose h3, .card h4) where that same
   -0.02em reads too tight; they get a near-zero value instead. */
h1, h2, h3, h4 { margin: 0; font-weight: 700; overflow-wrap: break-word; }
h1, h2 { letter-spacing: -0.02em; }
h3, h4 { letter-spacing: -0.006em; }
p { margin: 0; }

::selection { background: #2b2b2b; color: var(--bg); }

:focus-visible {
  outline: 2px solid #2b2b2b;
  outline-offset: 4px;
  border-radius: 4px;
}

/* ---------- 3. MATERIAL ATMOSPHERE ---------- */
/* soft vignette — the page is lit from above like a desk lamp */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: 1999; pointer-events: none;
  background: radial-gradient(120% 95% at 50% 6%, transparent 56%, rgba(45,37,26,0.14) 100%);
}
/* film grain — kills the flat digital-gradient look on every surface */
body::after {
  content: "";
  position: fixed; inset: 0; z-index: 2000; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  background-size: 180px 180px;
  opacity: 0.085;
}

/* engineering graph-paper grid — felt, not seen */
.bg-grid {
  position: fixed;
  inset: 0 0 auto 0;
  height: 560px;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(62,52,38,0.065) 1px, transparent 1px),
    linear-gradient(90deg, rgba(62,52,38,0.065) 1px, transparent 1px),
    linear-gradient(rgba(62,52,38,0.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(62,52,38,0.03) 1px, transparent 1px);
  background-size: 80px 80px, 80px 80px, 16px 16px, 16px 16px;
  -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
}

/* ---------- 4. LAYOUT ---------- */
.wrap { width: min(1120px, 92vw); margin-inline: auto; position: relative; z-index: 1; }
.section { padding-block: clamp(64px, 11vw, 140px); }
.section--tight { padding-block: clamp(40px, 6vw, 72px); }

/* ---------- 5. FLOATING NAV PILL ---------- */
.nav {
  position: sticky;
  top: 12px;
  z-index: 50;
  width: min(497px, 94vw);
  margin: 12px auto 0;
  height: 64px;
  padding: 8px;
  display: flex;
  align-items: center;
  gap: 4px;
  border-radius: 200px;
  background: linear-gradient(180deg, #e6e3dd, #d0cdc6);
  box-shadow:
    0 8px 16px rgba(40,32,20,0.14),
    inset 0 1px 0 rgba(255,255,255,0.85),
    inset 0 -2px 4px rgba(0,0,0,0.10);
}
.nav__brand {
  display: flex; align-items: center; gap: 9px;
  padding: 0 12px 0 8px;
  margin-right: auto;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: -0.02em;
}
.nav__brand .logo-dot {
  width: 26px; height: 26px; border-radius: 8px;
  display: grid; place-items: center;
  background: linear-gradient(160deg, var(--dark), #000);
  color: var(--bg);
  font-family: var(--font-hand); font-style: italic;
  font-size: 19px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.25), 0 1px 2px rgba(0,0,0,0.3);
}
.nav__links { display: flex; align-items: center; gap: 2px; }
.nav a.nav__link {
  padding: 9px 16px;
  border-radius: 200px;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-muted);
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.nav a.nav__link:hover { color: var(--ink); }
.nav a.nav__link[aria-current="page"],
.nav a.nav__link.is-active {
  color: var(--ink);
  background: var(--bg-deep);
  box-shadow: var(--press);
}

/* ---------- 6. HERO ----------
   The headline spans the full measure above the two columns rather than
   sitting in a left-hand text stack beside a panel. Two reasons: at the
   old 603px column the sentence broke into a four-line staircase, and
   the text-column-plus-object-column skeleton is the single most-shipped
   hero arrangement there is. Full-width headline, then supporting copy
   beside the camera, is a composition instead of a stack. */
.hero {
  /* the floor clears the sticky nav's blur band: at rest the masthead
     reaches ~100px down the viewport, and a smaller pad left the first
     line of the headline sitting washed-out underneath it */
  padding-top: clamp(56px, 4vw, 60px);
  padding-bottom: clamp(32px, 4vw, 44px);
}
/* Own the first screen. Without this the composition floated in the top
   two thirds and left ~190px of dead ground at the bottom of the fold. */
@media (min-width: 881px) {
  .hero {
    min-height: calc(100svh - 104px);
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 445px);
  gap: clamp(28px, 5vw, 64px);
  /* The camera column runs ~550px while the supporting copy is only ~170px,
     so any single alignment (centre, top, bottom) strands a ~400px hole in
     the left column and the hero reads as two clusters marooned apart.
     Instead the copy column stretches the full row and anchors at BOTH
     ends: lede and meta sit up under the headline, the scroll cue is pinned
     to the bottom edge alongside the print's caption. The space between
     them is then framed negative space rather than a gap. */
  align-items: stretch;
  margin-top: clamp(20px, 2.6vw, 34px);
}
.hero__copy {
  display: flex;
  flex-direction: column;
  /* matches .hero__device's bottom padding so both columns end on the
     same line rather than missing it by a few px */
  padding-bottom: 14px;
}
.hero__meta { margin-bottom: 0; }
/* ---------- the hero portrait — just the avatar ----------
   The instant camera is gone (obituary in docs/hero-living-portrait.md):
   the same portrait SVG, presented plainly in a paper card instead of
   manufactured by a machine. Eyes follow the cursor and a click blinks —
   the honest version of the shutter's promise. The wire-up is the HERO
   PORTRAIT IIFE in audit-main.js and reuses the global
   .avatar-shell / .avatar-features / .avatar-pupils motion rules; only
   the frame below is hero-specific. */
.hero__device {
  position: relative;
  padding: 6px 0 14px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.hero-avatar {
  display: inline-block;
  width: min(300px, 100%);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.hero-avatar__art {
  position: relative;
  display: block;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 36px;
  border: 5px solid #e9e7e2;
  /* warm paper backing — the line-art reads as printed ink */
  background:
    radial-gradient(130% 120% at 28% 18%, #fbf9f4, #ece9e2 70%, #e2dfd7);
  box-shadow:
    0 18px 38px rgba(40, 32, 20, 0.22),
    inset 0 0 0 1px rgba(0, 0, 0, 0.06),
    inset 0 1px 0 rgba(255, 255, 255, 0.7);
  transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);
}
.hero-avatar:hover .hero-avatar__art {
  transform: translateY(-3px) rotate(-0.6deg);
  box-shadow:
    0 26px 48px rgba(40, 32, 20, 0.26),
    inset 0 0 0 1px rgba(0, 0, 0, 0.06),
    inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
.hero-avatar:active .hero-avatar__art {
  transform: translateY(0) scale(0.985);
  transition-duration: 80ms;
}
.hero-avatar:focus-visible { outline: none; }
.hero-avatar:focus-visible .hero-avatar__art {
  box-shadow:
    0 0 0 3px var(--bg),
    0 0 0 6px var(--ink),
    0 18px 38px rgba(40, 32, 20, 0.22);
}
.hero-avatar__art svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* transform-box lives on `.avatar svg g` only — same need here, or the
   cursor-follow translates compute against the wrong box. */
.hero-avatar svg g { transform-box: fill-box; transform-origin: center; }
/* Sits a touch right of centre in its column on desktop, clear of the
   copy measure. The offset lives on the wrap (not the button) so the
   doodle orbit follows the card. */
@media (min-width: 881px) {
  .hero-avatar { margin-left: 0; }
  /* The device column centers the card vertically, so the copy column
     centers its own mass the same way — both sit on one shared
     horizontal axis at any viewport width instead of the copy hanging
     off the top while the card floats mid-row. */
  .hero__copy { justify-content: center; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-avatar .hero-avatar__art,
  .hero-avatar:hover .hero-avatar__art { transform: none; transition: none; }
}
/* ---------- hero roles + doodle orbit ----------
   The handwritten line is four roles, each one a real control: hover,
   focus or tap it and the ink scattered around the portrait changes to
   match. Each doodle is a pre-sliced transparent PNG (see
   assets/doodles/, cut from the landing-page sheets), placed by
   --x/--y/--w so nothing hides under the card. The ink reads black in
   daylight and near-white in the dark room via the --lit-driven
   invert. Content is never gated: the baseline orbit is in the markup
   and visible with no script at all. */
/* The roles read as one handwritten sentence; the controls hide inside
   it. No per-role decoration — a single indicator bar glides between
   them on a spring (see HERO DOODLES in audit-main.js), so rapid
   hovering re-targets mid-flight instead of jumping. Feedback starts
   on press-down, never on release. */
.hero-roles { position: relative; }
.hero-roles .hero-role {
  font: inherit;
  color: var(--ink-muted);
  padding: 6px 8px;
  margin: -6px -2px;
  border: 0;
  border-radius: 8px;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 180ms var(--ease), transform 100ms ease-out;
}
.hero-roles .hero-role:hover { color: var(--ink); }
.hero-roles .hero-role:active { transform: scale(0.96); }
.hero-roles .hero-role:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.hero-roles .hero-role.is-active { color: var(--ink); }
.hero-roles__bar {
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
  opacity: 0;
  pointer-events: none;
  transform-origin: 0 0;
  transition: opacity 200ms var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .hero-roles .hero-role { transition: none; }
  .hero-roles .hero-role:active { transform: none; }
}
.hero__device { isolation: isolate; }
/* shrink-wraps the portrait so the orbit centres on the card, not the column */
.hero-avatar-wrap {
  position: relative;
  display: inline-block;
  width: min(300px, 100%);
  line-height: 0;
}
.hero-avatar-wrap .hero-avatar { width: 100%; }
.hero-avatar { position: relative; z-index: 1; }
.hero-doodles {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(380px, 90vw);
  aspect-ratio: 1;
  translate: -50% -50%;
  z-index: 0;
  pointer-events: none;
}
/* the orbit runs wider than the card and leans into the empty space
   down-right of it, clear of the copy column */
@media (min-width: 881px) {
  .hero-avatar-wrap { margin-left: clamp(0px, 4vw, 56px); }
  .hero-doodles {
    width: clamp(420px, 44vw, 620px);
    translate: calc(-50% + 5%) calc(-50% + 2%);
  }
}
/* One orbit per role; each doodle is a pre-sliced transparent PNG placed
   by --x/--y/--w so nothing ever sits under the card. The PNGs carry
   black ink on transparency, so no blend mode is needed — the ink
   follows the room through the --lit-driven invert. */
.hero-orbit {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 320ms var(--ease), visibility 0s 320ms;
}
.hero-orbit.is-active {
  opacity: 1;
  visibility: visible;
  transition: opacity 320ms var(--ease);
}
.doodle {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w);
  height: auto;
  opacity: 0;
  filter: invert(calc(1 - var(--lit)));
  transition: opacity 280ms var(--ease), scale 150ms ease-out;
  /* the drift animation owns `transform`, so the hover pop rides the
     independent `scale` property instead — the two compose rather than
     fight, and the pop answers on pointer-enter, never on release */
  pointer-events: auto;
}
.hero-orbit.is-active .doodle { opacity: 1; }
.hero-orbit.is-active .doodle:hover { scale: 1.28; z-index: 2; }
.hero-orbit.is-active:has(.doodle:hover) .doodle:not(:hover) { opacity: 0.3; transition-duration: 150ms; }
@media (prefers-reduced-motion: no-preference) {
  /* Entrance runs once as an animation (staggered fade per doodle) while
     the idle float loops forever beside it — keeping the stagger out of
     `transition-delay` means hover feedback never inherits the wait. */
  .hero-orbit.is-active .doodle {
    --in: 0ms;
    --drift-delay: 0s;
    --drift-dur: 7s;
    animation-name: doodle-in, doodle-drift;
    animation-duration: 320ms, var(--drift-dur);
    animation-timing-function: ease-out, ease-in-out;
    animation-delay: var(--in), var(--drift-delay);
    animation-fill-mode: backwards, none;
    animation-iteration-count: 1, infinite;
    animation-direction: normal, alternate;
  }
  .hero-orbit.is-active .doodle:nth-child(1) { --in: 0ms; }
  .hero-orbit.is-active .doodle:nth-child(2) { --in: 45ms; }
  .hero-orbit.is-active .doodle:nth-child(3) { --in: 90ms; }
  .hero-orbit.is-active .doodle:nth-child(4) { --in: 135ms; }
  .hero-orbit.is-active .doodle:nth-child(5) { --in: 180ms; }
  .hero-orbit.is-active .doodle:nth-child(6) { --in: 225ms; }
  .hero-orbit.is-active .doodle:nth-child(7) { --in: 270ms; }
  .hero-orbit.is-active .doodle:nth-child(8) { --in: 315ms; }
  .hero-orbit.is-active .doodle:nth-child(9) { --in: 360ms; }
  .hero-orbit.is-active .doodle:nth-child(10) { --in: 405ms; }
  .hero-orbit.is-active .doodle:nth-child(11) { --in: 450ms; }
  /* idle float: each doodle bobs on its own clock so the orbit shimmers
     rather than marching in step */
  .hero-orbit.is-active .doodle:nth-child(2n) { --drift-delay: -2.3s; --drift-dur: 8.6s; }
  .hero-orbit.is-active .doodle:nth-child(3n) { --drift-delay: -4.1s; --drift-dur: 6.1s; }
  .hero-orbit.is-active .doodle:nth-child(4n) { --drift-delay: -1.2s; --drift-dur: 7.4s; }
  .hero-orbit.is-active .doodle:nth-child(5n) { --drift-delay: -5.3s; --drift-dur: 9.2s; }
  @keyframes doodle-in {
    from { opacity: 0; }
    to { opacity: 1; }
  }
  @keyframes doodle-drift {
    from { transform: rotate(-2.2deg) translateY(-5px); }
    to { transform: rotate(2.2deg) translateY(5px); }
  }
}
@media (max-width: 880px) {
  /* Small screens can't fit side rings beside a full-width card, so the
     composition shrinks instead: a 240px card inside a 400px orbit
     leaves an 80px ring on every side, and the device gains headroom
     top and bottom so the orbit never collides with the copy or the
     section below. */
  .hero-avatar-wrap { width: min(240px, 72%); }
  .hero-doodles { width: min(400px, 108vw); opacity: 1; }
  .hero__device { margin-top: 64px; padding-bottom: 84px; }
  /* the pencil rides highest in the baseline orbit and grazes the meta
     line on narrow screens — tuck it a touch lower and inward */
  .hero-orbit[data-doodle="baseline"] .doodle[src*="baseline-pencil"] { --y: 7% !important; --x: 34% !important; }
  /* each orbit has one tall rider at its top that would pierce the meta
     line on narrow screens — shrink and lower them so the ring starts
     below the copy instead of inside it */
  .hero-orbit[data-doodle="tech"] .doodle[src*="tech-laptop"] { --w: 11% !important; --y: 9% !important; }
  .hero-orbit[data-doodle="designer"] .doodle[src*="designer-wire-doc"] { --w: 10% !important; --y: 6% !important; }
  .hero-orbit[data-doodle="gamer"] .doodle[src*="gamer-trophy"] { --w: 10% !important; --y: 6% !important; }
  .hero-orbit[data-doodle="illustrator"] .doodle[src*="illustrator-sketchbook"] { --w: 9% !important; --y: 7% !important; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-orbit, .doodle { transition: none; }
}



/* Eyebrow + giant name + handwritten aside: a mono kick, the name
   set huge in the site's own 800, one Caveat flourish with a marker
   stroke, then the mono body. Caveat is the single exception to the
   no-handwriting rule above, and it stays one — a decorative aside,
   never UI. */
.hero__name {
  margin: 0;
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(40px, 8.5vw, 92px);
  line-height: 0.94;
  letter-spacing: -0.01em;
}
.hero__name span { display: block; }
.hero__hand {
  margin: 26px 0 0;
  font-family: "Caveat", "Plus Jakarta Sans", cursive;
  font-weight: 600;
  font-size: clamp(27px, 3vw, 35px);
  line-height: 1.15;
  color: var(--ink);
}
.hero__lede {
  margin: 22px 0 0;
  font-size: clamp(17px, 1.5vw, 20px);
  line-height: 1.55;
  color: var(--ink-muted);
  max-width: 46ch;
}
.hero__meta {
  margin-top: 30px;
  display: flex; flex-wrap: wrap; gap: 10px 22px;
  font-family: var(--font-label);
  font-size: 13px; color: var(--ink-muted);
}
.hero__meta b { color: var(--ink); font-weight: 600; margin-right: .4em; }
/* (the "slide one out of the case" cue lived here — removed with the
   case metaphor it pointed at) */

.section-head { margin-bottom: clamp(28px, 4vw, 48px); }
.section-head h2 {
  font-size: clamp(28px, 4.4vw, 46px);
  line-height: 1.08;
  margin-top: 18px;
  max-width: 22ch;
  text-wrap: balance;
}
.section-head p { margin-top: 14px; color: var(--ink-muted); max-width: 52ch; font-size: clamp(15px,1.8vw,18px); }

/* ============================================================
   8. PROJECT FOLDERS
   Continuous vector silhouettes keep the tabs and pockets seamless.
   Original transparent hero canvases are retained for page transitions;
   their visible artwork occupies roughly 40–55% of the folder width.
   ============================================================ */
.project-folders {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(36px, 6vw, 84px);
  row-gap: clamp(64px, 8vw, 104px);
}
.project-folder {
  display: block;
  min-width: 0;
  color: var(--ink);
  text-align: center;
  -webkit-tap-highlight-color: transparent;
}
.project-folder:nth-child(2) { transition-delay: 70ms; }
.project-folder:nth-child(3) { transition-delay: 120ms; }
.project-folder:nth-child(4) { transition-delay: 170ms; }
.project-folder:nth-child(5) {
  grid-column: 1 / -1;
  justify-self: center;
  width: calc((100% - clamp(36px, 6vw, 84px)) / 2);
  transition-delay: 220ms;
}
.project-folder--weather {
  --folder-back: linear-gradient(160deg, #b2e9ff, #42b3ec);
  --folder-face: linear-gradient(155deg, #cef1ff 18%, #7ccdf4 48%, #249be0 100%);
  --folder-glow: 40 149 213;
  --folder-ink: #124b6d;
  --folder-cut: url("assets/folders/weather.svg");
}
.project-folder--wallet {
  --folder-back: linear-gradient(155deg, #5577eb, #263da0);
  --folder-face: linear-gradient(160deg, #ffecad 22%, #ffda69 65%, #ffc438);
  --folder-glow: 200 135 30;
  --folder-ink: #67460a;
  --folder-cut: url("assets/folders/wallet.svg");
}
.project-folder--gate {
  --folder-back: linear-gradient(155deg, #ffa916, #ed5614);
  --folder-face: linear-gradient(155deg, #781c3b 18%, #4a1028 65%, #31091b);
  --folder-glow: 115 31 54;
  --folder-ink: #ffe49b;
  --folder-cut: url("assets/folders/gate.svg");
}
.project-folder--onboarding {
  --folder-back: linear-gradient(150deg, #d0b29d, #a3846d);
  --folder-face: linear-gradient(155deg, #e1caba 25%, #c3a48f 65%, #a78874);
  --folder-glow: 135 103 78;
  --folder-ink: #51392c;
  --folder-cut: url("assets/folders/onboarding.svg");
}
.project-folder--foreign {
  --folder-back: linear-gradient(150deg, #d797fb, #a447e0);
  --folder-face: linear-gradient(150deg, #d69cf9 20%, #b66be8 60%, #903bd0);
  --folder-glow: 144 60 195;
  --folder-ink: #3e155c;
  --folder-cut: url("assets/folders/foreign.svg");
}
.project-folder__stage {
  position: relative;
  isolation: isolate;
  aspect-ratio: 1 / 1;
  overflow: visible;
  transform: translateZ(0);
  transition: transform 180ms ease-out;
  filter: brightness(calc(0.94 + 0.06 * var(--lit, 1)));
}
.project-folder__stage::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 85% 8% -4%;
  border-radius: 50%;
  background: rgb(var(--folder-glow) / 0.23);
  filter: blur(20px);
  pointer-events: none;
}
.project-folder__back,
.project-folder__divider,
.project-folder__front,
.project-folder__tabs i {
  position: absolute;
  inset: 0;
  mask-repeat: no-repeat;
  mask-size: 100% 100%;
}
.project-folder__back {
  z-index: 1;
  inset: 0 3% 2%;
  background: var(--folder-back);
  mask-image: url("assets/folders/back.svg");
}
.project-folder__divider {
  z-index: 2;
  inset: 0 1% 1%;
  background: linear-gradient(145deg, #edfaff 20%, #a6dcf3);
  mask-image: url("assets/folders/weather.svg");
  transform: translateY(-5%);
}
.project-folder--wallet .project-folder__divider {
  background: linear-gradient(145deg, #a2a2ff, #6566eb);
  mask-image: url("assets/folders/divider.svg");
  transform: none;
}
.project-folder--gate .project-folder__divider {
  background: linear-gradient(145deg, #f17b20, #c83416);
  mask-image: url("assets/folders/gate.svg");
  transform: translateY(-5%);
}
.project-folder--onboarding .project-folder__divider {
  background: linear-gradient(150deg, #fffaf2, #eadbc9);
  mask-image: url("assets/folders/onboarding.svg");
  transform: translateY(-4%);
}
.project-folder--foreign .project-folder__divider {
  background: linear-gradient(145deg, #edc7ff, #c68ced);
  mask-image: url("assets/folders/foreign.svg");
  transform: translateY(-4%);
}
.project-folder__tabs { position: absolute; z-index: 1; inset: 0 2%; }
.project-folder__tabs i {
  mask-image: url("assets/folders/gate.svg");
  background: #ffc33e;
  transform: translateY(-12%);
}
.project-folder__tabs i:nth-child(2) { background: #ff961f; transform: translateY(-9%); }
.project-folder__tabs i:nth-child(3) { background: #ee5819; transform: translateY(-6%); }
.project-folder__media {
  position: absolute;
  z-index: 3;
  inset: 0;
  /* Oversized portrait sheets end inside the pocket, above its curved base. */
  overflow: clip;
  overflow-clip-margin: 18px;
  clip-path: inset(-5% -5% 9% -5%);
  pointer-events: none;
}
.project-folder__media img {
  --folder-pointer-x: 0px;
  --folder-pointer-y: 0px;
  position: absolute;
  display: block;
  max-width: none;
  filter: drop-shadow(0 9px 9px rgba(25, 28, 40, 0.18));
  transform-origin: 50% 80%;
  translate: var(--folder-pointer-x) var(--folder-pointer-y);
  transition: transform 420ms cubic-bezier(0.2, 0.82, 0.2, 1);
}
.project-folder__sheet--back { z-index: 1; --rest: rotate(-12deg); transform: var(--rest); }
.project-folder__sheet--middle { z-index: 2; --rest: rotate(11deg); transform: var(--rest); }
.project-folder__sheet { border-radius: 9px; }
.project-folder__hero { z-index: 3; left: -5%; top: -12%; width: 110%; }
.project-folder--weather .project-folder__sheet--back { left: 5%; top: 27%; width: 44%; }
.project-folder--weather .project-folder__sheet--middle { right: 4%; top: 33%; width: 44%; }
.project-folder--wallet .project-folder__sheet--back { left: 12%; top: 24%; width: 30%; }
.project-folder--wallet .project-folder__sheet--middle { right: 12%; top: 29%; width: 30%; }
.project-folder--gate .project-folder__hero { left: 3%; top: -9%; width: 94%; }
.project-folder--gate .project-folder__sheet--back { left: 12%; top: 25%; width: 28%; }
.project-folder--gate .project-folder__sheet--middle { right: 12%; top: 28%; width: 28%; }
.project-folder--onboarding .project-folder__hero { left: -7%; top: -9%; width: 114%; }
.project-folder--onboarding .project-folder__sheet--back { left: 11%; top: 28%; width: 28%; }
.project-folder--onboarding .project-folder__sheet--middle { right: 8%; top: 34%; width: 38%; --rest: rotate(9deg); }
.project-folder--foreign .project-folder__hero { top: -7%; }
.project-folder--foreign .project-folder__sheet--back { left: 12%; top: 24%; width: 30%; }
.project-folder--foreign .project-folder__sheet--middle { right: 12%; top: 29%; width: 30%; }
.project-folder__front {
  z-index: 4;
  background: var(--folder-face);
  mask-image: var(--folder-cut);
  color: var(--folder-ink);
}
.project-folder__front::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, rgba(255,255,255,.18), transparent 52%);
  opacity: 0.4;
  transition: opacity 250ms ease;
  pointer-events: none;
}
.project-folder__label {
  position: absolute;
  left: 8%;
  bottom: 9%;
  display: grid;
  gap: 6px;
  text-align: left;
}
.project-folder__label strong { font-size: clamp(19px, 2.2vw, 28px); font-weight: 600; letter-spacing: -0.04em; }
.project-folder__label small { font-size: clamp(11px, 1.1vw, 14px); font-weight: 500; }
.project-folder__open {
  position: absolute;
  right: 8%;
  bottom: 10%;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid currentColor;
  border-radius: 50%;
  font-size: 23px;
  opacity: 0.7;
  transition: transform 250ms ease, opacity 250ms ease;
}
.project-folder__title {
  position: relative;
  z-index: 10;
  display: block;
  margin-top: clamp(26px, 3vw, 34px);
  font-size: clamp(25px, 3vw, 34px);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
.project-folder__copy {
  position: relative;
  z-index: 10;
  display: grid;
  max-width: 43ch;
  margin: 12px auto 0;
  /* Stacked swap: the tallest layer sets the height, so the card
     never jumps when the copy crossfades. */
  align-items: start;
  justify-items: center;
}
.project-folder__description {
  grid-area: 1 / 1;
  display: block;
  font-size: clamp(15px, 1.65vw, 18px);
  line-height: 1.55;
  color: var(--ink-muted);
  text-wrap: pretty;
  opacity: 1;
  transform: translateY(0);
  transition: opacity 220ms var(--ease), transform 220ms var(--ease);
}
.project-folder__logic {
  grid-area: 1 / 1;
  display: block;
  font-size: clamp(15px, 1.65vw, 18px);
  line-height: 1.45;
  text-wrap: pretty;
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
  transition: opacity 220ms var(--ease), transform 220ms var(--ease), visibility 0s 220ms;
}
/* Problem → intervention → evidence: plain tonal type, no pills,
   no kickers, no gradient. The arrows are quiet punctuation. */
.logic-line { display: block; }
.logic-problem { color: var(--ink-muted); }
.logic-middle { color: var(--ink); font-weight: 650; }
.logic-evidence { color: var(--ink); font-weight: 750; }
.project-folder:focus-visible { outline: 3px solid var(--ink); outline-offset: 12px; border-radius: 12px; }
.project-folder:focus-visible .project-folder__open { opacity: 1; transform: translate(2px, -2px); }
@media (hover: hover) and (pointer: fine) {
  /* The copy explains the decision while the screens converge:
     the fanned sheets straighten toward 0deg and slide inward,
     the hero settles into the pocket instead of lifting. */
  .project-folder:hover .project-folder__hero,
  .project-folder:focus-within .project-folder__hero { transform: translateY(-1%) scale(0.99); }
  .project-folder:hover .project-folder__sheet--back,
  .project-folder:focus-within .project-folder__sheet--back { transform: translate(5%, -5%) rotate(-4deg); }
  .project-folder:hover .project-folder__sheet--middle,
  .project-folder:focus-within .project-folder__sheet--middle { transform: translate(-5%, -5%) rotate(4deg); }
  .project-folder:hover .project-folder__front::before,
  .project-folder:focus-within .project-folder__front::before { opacity: 1; }
  .project-folder:hover .project-folder__open,
  .project-folder:focus-within .project-folder__open { opacity: 1; transform: translate(2px, -2px); }
  .project-folder:hover .project-folder__description,
  .project-folder:focus-within .project-folder__description,
  .project-folder:focus-visible .project-folder__description {
    opacity: 0;
    transform: translateY(-4px);
  }
  .project-folder:hover .project-folder__logic,
  .project-folder:focus-within .project-folder__logic,
  .project-folder:focus-visible .project-folder__logic {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity 240ms var(--ease) 40ms, transform 240ms var(--ease) 40ms, visibility 0s 0s;
  }
}
/* Touch / coarse pointers: no hover to discover, so the story stays
   visible in flow instead of hidden behind an interaction. */
@media (hover: none) {
  .project-folder__copy { display: block; min-height: 0; }
  .project-folder__logic {
    opacity: 1;
    visibility: visible;
    transform: none;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(24, 21, 18, 0.14);
  }
}
.project-folder:active .project-folder__stage { transform: scale(0.985); }
@media (max-width: 620px) {
  .project-folders { grid-template-columns: minmax(0, 1fr); row-gap: 64px; }
  .project-folder { width: 100%; max-width: 440px; justify-self: center; }
  .project-folder:nth-child(5) { grid-column: auto; width: 100%; }
  .project-folder__media { overflow-clip-margin: 0px; }
  .project-folder__label strong { font-size: clamp(21px, 6vw, 28px); }
  .project-folder__label small { font-size: 12px; }
  .project-folder__copy { max-width: 38ch; }
}
@media (prefers-reduced-motion: reduce) {
  .project-folder__media img,
  .project-folder__stage,
  .project-folder__front::before,
  .project-folder__open,
  .project-folder__description,
  .project-folder__logic { transition: none !important; }
  .project-folder:active .project-folder__stage,
  .project-folder:hover .project-folder__hero { transform: none; }
  .project-folder__media img { translate: 0 0; }
  .project-folder:hover .project-folder__sheet { transform: var(--rest); }
  .project-folder:hover .project-folder__open,
  .project-folder:focus-visible .project-folder__open { transform: none; }
}

/* ============================================================
   8. THE SIGNATURE ELEMENT — CASSETTE TAPE PROJECT CARDS
   ============================================================ */
.mixtapes {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(22px, 3vw, 38px);
}
/* hand-placed tilts + a staggered cascade as the wall reveals.
   Tilt rides a custom property so it composes with the reveal
   transform instead of being clobbered by it. */
.mixtapes .mixtape:nth-child(1) { --tilt: -0.65deg; }
.mixtapes .mixtape:nth-child(2) { --tilt: 0.5deg;  transition-delay: 70ms; }
.mixtapes .mixtape:nth-child(3) { --tilt: 0.45deg; transition-delay: 140ms; }
.mixtapes .mixtape:nth-child(4) { --tilt: -0.55deg; transition-delay: 210ms; }
.mixtapes .mixtape:nth-child(5) { --tilt: -0.6deg; transition-delay: 280ms; }
.mixtapes .recorder { --tilt: 0.35deg; transition-delay: 350ms; }

.mixtape {
  display: block;
  perspective: 900px;
  border: 0; background: none;
  text-align: left;
}
.mixtape:active { --s: 0.982; } /* tactile press before the page morph */

.mixtape__shell {
  position: relative;
  aspect-ratio: 1.58 / 1;
  border-radius: 11px;
  padding: 14px;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) scale(var(--s, 1));
  /* transform is driven per-frame by a JS spring — a CSS transition here
     would fight the input and judder */
  transition: box-shadow var(--dur) var(--ease);
  /* will-change is set inline by JS only while the tilt spring is
     actually running (pointer over the card / still easing back to
     rest) — see the cassette IIFE in audit-main.js — not left on
     permanently for a shell that mostly just sits still */
  /* directional beveled edges — light from top-left */
  border-top: 1px solid var(--edge-light);
  border-left: 1px solid var(--edge-light);
  border-right: 1px solid var(--edge-dark);
  border-bottom: 2px solid var(--edge-dark);
  background:
    radial-gradient(130% 90% at 16% 4%, color-mix(in srgb, var(--shell) 70%, #fff 30%), transparent 44%),
    linear-gradient(158deg,
      color-mix(in srgb, var(--shell) 90%, #fff 10%) 0%,
      var(--shell) 46%,
      color-mix(in srgb, var(--shell) 82%, #000 18%) 100%);
  box-shadow:
    0 18px 34px rgba(0,0,0,0.26),
    0 5px 12px rgba(0,0,0,0.18),
    inset 0 1px 0 rgba(255,255,255,0.55),
    inset 0 -6px 12px rgba(0,0,0,0.20),
    inset 0 0 0 1px rgba(0,0,0,0.05);
}
.mixtape:hover .mixtape__shell {
  box-shadow:
    0 28px 52px rgba(0,0,0,0.30),
    0 8px 16px rgba(0,0,0,0.20),
    inset 0 1px 0 rgba(255,255,255,0.60),
    inset 0 -6px 12px rgba(0,0,0,0.22),
    inset 0 0 0 1px rgba(0,0,0,0.05);
}
/* glossy plastic specular sweep (paints behind the raised parts) */
.mixtape__shell::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  /* no blend mode — blending inside a preserve-3d stack can force
     flattening and z-order glitches; plain alpha reads identically here */
  background: linear-gradient(122deg,
    rgba(255,255,255,0.30) 0%, rgba(255,255,255,0.09) 15%,
    rgba(255,255,255,0) 32%, rgba(255,255,255,0) 72%, rgba(255,255,255,0.06) 100%);
}
/* the fifth screw — center, just above the transport trapezoid,
   exactly where real cassettes have it */
.mixtape__shell::after {
  content: ""; position: absolute; left: 50%; bottom: 8.5%;
  width: 11px; height: 11px; margin-left: -5.5px; border-radius: 50%;
  background:
    linear-gradient(90deg, transparent 42%, rgba(0,0,0,0.5) 42% 58%, transparent 58%),
    linear-gradient(0deg, transparent 42%, rgba(0,0,0,0.5) 42% 58%, transparent 58%),
    radial-gradient(circle at 38% 30%, #f0f0ee 0 12%, #cfcfcd 32%, #9f9f9d 60%, #7c7c7a 82%, #5c5c5a 100%);
  box-shadow: 0 0 0 2px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.4), inset 0 0 2px rgba(0,0,0,0.5);
  z-index: 3;
}

/* ribbed shell texture — the fine molded groove grid on the bare plastic
   around the label, just like the real housing */
.mixtape__texture {
  position: absolute; inset: 0; border-radius: 10px; pointer-events: none;
  transform: translate(var(--px-far, 0px), var(--py-far, 0px));
  background-image:
    repeating-linear-gradient(0deg, rgba(0,0,0,0.06) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(90deg, rgba(0,0,0,0.05) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(0deg, rgba(255,255,255,0.035) 0 1px, transparent 1px 4px);
  background-position: 0 0, 0 0, 0 1px;
}

/* recessed Phillips screws — pure radial-gradient hardware */
.screw {
  position: absolute; width: 13px; height: 13px; border-radius: 50%;
  transform: translateZ(28px);
  background:
    radial-gradient(circle at 38% 30%, #f5f5f5 0 12%, #d2d2d2 32%, #a3a3a3 60%, #808080 82%, #5f5f5f 100%);
  box-shadow:
    0 0 0 2px rgba(0,0,0,0.07),
    0 1px 2px rgba(0,0,0,0.45),
    inset 0 0 2px rgba(0,0,0,0.55),
    inset 0 1px 0 rgba(255,255,255,0.6);
  filter: saturate(0.85) contrast(0.95);
}
.screw::before { /* countersink shadow well */
  content: ""; position: absolute; inset: -4px; border-radius: 50%; z-index: -1;
  background: radial-gradient(circle, rgba(0,0,0,0.20), transparent 68%);
}
.screw::after { /* phillips cross-head */
  content: ""; position: absolute; inset: 20%;
  background:
    linear-gradient(90deg, transparent 41%, rgba(0,0,0,0.55) 41% 59%, transparent 59%),
    linear-gradient(0deg, transparent 41%, rgba(0,0,0,0.55) 41% 59%, transparent 59%);
}
.screw--tl { top: 8px; left: 8px; }
.screw--tr { top: 8px; right: 8px; }
.screw--bl { bottom: 8px; left: 8px; }
.screw--br { bottom: 8px; right: 8px; }

/* the paper label — glued flat, covering most of the face, exactly like
   a factory cassette label. The hub plate punches through it below. */
.mixtape__sticker {
  position: absolute; z-index: 1;
  left: 6%; right: 6%; top: 7.5%; height: 54.5%;
  border-radius: 4px;
  /* Flow layout, not stacked absolute offsets. The kicker used to be
     absolutely positioned at top:9% while the title relied on a 17%
     right padding to clear it. Below ~620px the sticker shrinks but the
     title's font-size hits its clamp floor, so the title's first line
     rose into the kicker's band and the two strings overlapped on every
     tape. Laying them out in order makes the clearance structural
     instead of a percentage that only happens to work at one width. */
  display: flex;
  flex-direction: column;
  /* Left padding clears the printed A/B side badge, which stays absolute.
     The vertical values are clamped rather than left as bare percentages:
     percentage padding and margin resolve against the container's WIDTH,
     not its height, so on a 1.58:1 shell a "5%" top pad is ~1.6x taller
     than it looks and the block overran the hub plate below it. Text has
     to live in roughly the top half of the label — the deck starts at
     50.5% of the sticker's height — so these stay deliberately small. */
  padding: clamp(6px, 1.6%, 14px) 5.5% 0 17%;
  transform: translate(var(--px-near, 0px), var(--py-near, 0px));
  background:
    radial-gradient(120% 100% at 88% 8%, rgba(120,95,55,0.08), transparent 50%),
    linear-gradient(180deg, color-mix(in srgb, var(--label-bg) 96%, #fff 4%), var(--label-bg));
  box-shadow:
    0 1px 2px rgba(0,0,0,0.30),
    inset 0 0 0 1px rgba(0,0,0,0.07),
    inset 0 0 22px rgba(140,110,60,0.07);
}
/* ruled writing lines on the upper half + brand stripes running across
   the lower band (they disappear behind the hub plate, like the photos) */
.mixtape__sticker::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background:
    repeating-linear-gradient(0deg, transparent 0 17px, rgba(110,90,60,0.22) 17px 18px) 0 14% / 100% 44% no-repeat,
    linear-gradient(180deg, var(--stripe-1) 0 38%, transparent 38% 54%, var(--stripe-2) 54% 100%) 0 92% / 100% 22% no-repeat;
}
/* the printed side-letter box, top-left — "A" in a black square */
.mixtape__sticker::after {
  content: var(--side, "A");
  position: absolute; top: 8%; left: 4%;
  width: clamp(17px, 12%, 24px); aspect-ratio: 1;
  display: grid; place-items: center;
  font-family: var(--font-label); font-weight: 800;
  font-size: clamp(10px, 1.3vw, 14px);
  color: #f1ecdf;
  background: #1d1812;
  border-radius: 2.5px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14), 0 1px 1px rgba(0,0,0,0.22);
}
/* printed meta, top-right of the label — like "60 MIN PER SIDE" */
.mixtape__kicker {
  align-self: flex-end;
  font-family: var(--font-label);
  font-size: clamp(9px, 0.86vw, 10px); font-weight: 700;
  letter-spacing: 0.07em; text-transform: uppercase;
  line-height: 1;
  color: #6b6150;
  text-align: right;
  white-space: nowrap;
}
/* the title, handwritten in pen on the ruled lines */
.mixtape__title {
  display: block;
  margin-top: clamp(3px, 0.9%, 9px);
  font-family: var(--font-hand); font-style: italic;
  font-size: clamp(20px, 2.7vw, 30px);
  line-height: 0.98;
  color: #34302a;
  transform: rotate(-0.9deg);
  transform-origin: left center;
}
.mixtape__sub {
  display: block;
  margin-top: 2px;
  font-family: var(--font-hand); font-style: italic;
  font-size: clamp(12px, 1.5vw, 16px);
  line-height: 1.2;
  color: #5d564a;
  transform: rotate(-0.9deg);
  transform-origin: left center;
}

/* the hub plate — the dark molded assembly punched through the label,
   holding both drive hubs with the tape-view window between them */
.mixtape__deck {
  position: absolute; z-index: 2;
  left: 19%; right: 19%; top: 35%; height: 27%;
  display: flex; align-items: center; justify-content: space-between;
  padding-inline: 4%;
  border-radius: clamp(9px, 1.6vw, 15px);
  transform: translate(var(--px-mid, 0px), var(--py-mid, 0px));
  background: linear-gradient(180deg, #211c16 0%, #0d0a07 55%, #070504 100%);
  box-shadow:
    0 1px 2px rgba(0,0,0,0.45),
    0 0 0 1px rgba(0,0,0,0.55),
    inset 0 1px 0 rgba(255,255,255,0.10),
    inset 0 -2px 5px rgba(0,0,0,0.65);
  overflow: hidden;
}
/* the tape-view window between the hubs — dark glass, faint guide posts */
.mixtape__deck::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 34%; height: 58%;
  transform: translate(-50%, -50%);
  border-radius: 3px;
  background:
    repeating-linear-gradient(90deg, rgba(235,228,210,0.09) 0 2px, transparent 2px 24%),
    linear-gradient(180deg, #221a12 0%, #32261a 48%, #15100a 100%);
  box-shadow:
    inset 0 1px 3px rgba(0,0,0,0.8),
    0 1px 0 rgba(255,255,255,0.07);
}
/* glass window light-sweep on hover */
.mixtape__deck::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 55%;
  left: -75%; z-index: 4;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,0.42), transparent);
  /* travels by transform: 205% of the deck is ~373% of its own 55% width */
  transition: transform var(--dur-sweep) var(--ease);
  pointer-events: none;
}
.mixtape:hover .mixtape__deck::after { transform: translateX(373%); }

/* the drive hubs (toothed SVG injected by JS) */
.reel {
  position: relative; z-index: 2;
  height: 86%; aspect-ratio: 1; border-radius: 50%;
  transform: rotate(var(--reel-rot, 0deg));
  /* will-change is set inline by JS for the spring-driven reels (see
     the cassette IIFE), and by CSS below for the idle ones — those spin
     continuously via a CSS animation for the life of the page, so the
     hint genuinely belongs there permanently */
}
.reel__art { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.reel--right { --reel-rot: 0deg; }

/* idle playback — the hero tape and case-study tapes turn on their own;
   the take-up reel (less tape on the pack) spins faster, like real life */
.mixtape[data-idle] .reel--left  { animation: reel-turn 5.6s linear infinite; will-change: transform; }
.mixtape[data-idle] .reel--right { animation: reel-turn 3.8s linear infinite; will-change: transform; }
@keyframes reel-turn { to { transform: rotate(360deg); } }

/* the molded bottom transport section — that iconic trapezoid, flush with
   the bottom edge, with the capstan and head openings punched into it */
.mixtape__base {
  position: absolute; left: 17%; right: 17%; bottom: 0; height: 21%;
  display: flex; align-items: center; justify-content: space-between;
  padding-inline: 16%;
  clip-path: polygon(7% 0, 93% 0, 100% 100%, 0 100%);
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,0.10) 0 1px, transparent 1px 4px),
    linear-gradient(180deg, var(--band), color-mix(in srgb, var(--band) 75%, #000 25%));
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.35), inset 0 -1px 0 rgba(255,255,255,0.08);
}
.mixtape__base i {
  background: radial-gradient(circle at 50% 35%, #2c2a27, #050403 80%);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.9), 0 1px 0 rgba(255,255,255,0.16);
}
.mixtape__base i:nth-child(1), .mixtape__base i:nth-child(5) { width: 9%; aspect-ratio: 1; border-radius: 50%; }
.mixtape__base i:nth-child(2), .mixtape__base i:nth-child(4) { width: 6.5%; height: 38%; border-radius: 2px; }
.mixtape__base i:nth-child(3) { display: none; }
/* top write-protect tab recesses */
.mixtape__foot {
  position: absolute; top: 7px; width: 14px; height: 7px; border-radius: 2px;
  background: radial-gradient(circle at 50% 30%, #232323, #000 85%);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.9), 0 1px 0 rgba(255,255,255,0.3);
  transform: translateZ(6px);
}
.mixtape__foot--l { left: 18%; }
.mixtape__foot--r { right: 18%; }

.mixtape__cta {
  position: absolute; bottom: 7.5%; right: 4.5%;
  font-family: var(--font-label); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-on-shell, var(--ink));
  opacity: 0; transform: translateX(-4px) translateZ(24px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.mixtape:hover .mixtape__cta { opacity: 0.85; transform: translateX(0) translateZ(24px); }

/* THEMES */
/* THEMES — each tape is a different "brand" of blank cassette:
   shell plastic + label stock + the two printed stripe colors */
.mixtape--cream {
  --shell: var(--cream); --edge-light: #e6e1d0; --edge-dark: #aaa189;
  --band: #8f886f; --ink-on-shell: #3a3322;
  --label-bg: #ece6d3; --stripe-1: #8a5a32; --stripe-2: #c98f4e;
}
.mixtape--dark {
  --shell: var(--dark); --edge-light: #3a3936; --edge-dark: #090908;
  --band: #161514; --ink-on-shell: #e9e9e9;
  --label-bg: #ebe5d6; --stripe-1: #9aa3a6; --stripe-2: #4f9b94;
}
.mixtape--green {
  --shell: var(--green); --edge-light: #79948a; --edge-dark: #455c52;
  --band: #41544b; --ink-on-shell: #eef2ef;
  --label-bg: #efe9d8; --stripe-1: #d9a23c; --stripe-2: #c9572e;
}
.mixtape--tosca {
  --shell: var(--tosca); --edge-light: #86c2b8; --edge-dark: #47857b;
  --band: #3d7168; --ink-on-shell: #f1f8f6;
  --label-bg: #e9e3d0; --stripe-1: #2e6f66; --stripe-2: #5fa79a;
}
/* ============================================================
   THE RECORDER — the portable the next mixtape is being taped on.

   The previous attempt reused the cassettes' parts so faithfully that
   it stopped being a machine: a dark rectangle at the cassettes' exact
   1.58:1 footprint whose largest shape was a cassette label running
   wall to wall. The eye read "cassette in a frame", not "recorder",
   and an object with no identity of its own cannot sit in a set.

   What actually says recorder is hardware the tapes do not have: a
   big perforated speaker grille, a cassette compartment that reads as
   a door in a body rather than a window cut through it, a bank of
   piano keys that stand proud of the front, a tape counter, a mic
   port. Those are here now. The shared language stays where it
   belongs — the same shell recipe, screws, moulded texture, warm
   palette, and the same drive hubs turning behind the door — so the
   recorder belongs to the set by material, and is legible as its own
   thing by shape.
   ============================================================ */
.recorder { display: block; }

.recorder__unit {
  /* warm graphite, so it anchors the bottom of the wall against the
     cream tape beside it and never reads as the one cool-toned object */
  --shell: #322c26;
  --edge-light: #524a40;
  --edge-dark: #18140f;

  position: relative;
  aspect-ratio: 1.58 / 1;
  border-radius: 11px;
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 4.5%;
  padding: 7% 5.5% 6.5%;

  /* the shell recipe from .mixtape__shell: directional bevels lit from
     the top left, the same layered plastic gradient, the same inset lip */
  border-top: 1px solid var(--edge-light);
  border-left: 1px solid var(--edge-light);
  border-right: 1px solid var(--edge-dark);
  border-bottom: 2px solid var(--edge-dark);
  background:
    radial-gradient(130% 90% at 16% 4%, color-mix(in srgb, var(--shell) 72%, #fff 28%), transparent 44%),
    linear-gradient(158deg,
      color-mix(in srgb, var(--shell) 90%, #fff 10%) 0%,
      var(--shell) 46%,
      color-mix(in srgb, var(--shell) 82%, #000 18%) 100%);
  box-shadow:
    0 18px 34px rgba(0,0,0,0.26),
    0 5px 12px rgba(0,0,0,0.18),
    inset 0 1px 0 rgba(255,255,255,0.16),
    inset 0 -6px 12px rgba(0,0,0,0.22),
    inset 0 0 0 1px rgba(0,0,0,0.05);
}
/* the same glossy plastic sweep the tapes get */
.recorder__unit::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 4;
  background: linear-gradient(122deg,
    rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.05) 15%,
    rgba(255,255,255,0) 32%, rgba(255,255,255,0) 72%, rgba(255,255,255,0.04) 100%);
}
/* No hover state: nothing here is a link, and a card that answers the
   pointer promises a click it cannot honour. */

/* ---------- the face: speaker on the left, tape bay on the right ---------- */
.recorder__face {
  position: relative; z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
  gap: 5%;
  align-items: center;
}

/* The single most legible thing on a portable recorder, and the piece the
   old version had none of. A well sunk into the body, drilled with a real
   grid of holes, ringed by the moulded lip the drilling leaves behind. */
.recorder__speaker {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  max-height: 100%;
  margin-inline: auto;
  border-radius: 50%;
  background:
    /* the drilling: two offset lattices, so the holes stagger the way a
       real punched grille does instead of lining up in a coarse square grid */
    radial-gradient(circle, rgba(0,0,0,0.85) 0.85px, transparent 1.3px) 0 0 / 4.2px 4.2px,
    radial-gradient(circle, rgba(0,0,0,0.85) 0.85px, transparent 1.3px) 2.1px 2.1px / 4.2px 4.2px,
    /* the recess behind it, lit from the top left like everything else */
    radial-gradient(120% 120% at 30% 22%, #5d544a 0%, #3a342c 52%, #241f19 100%);
  box-shadow:
    /* the moulded rim standing proud of the drilled area */
    0 0 0 2px color-mix(in srgb, var(--shell) 80%, #000 20%),
    0 0 0 3px rgba(255,255,255,0.07),
    inset 0 2px 6px rgba(0,0,0,0.62),
    inset 0 -1px 0 rgba(255,255,255,0.07);
}
/* one soft rake of light across the top of the cone, so the grille reads
   as a dished surface rather than a flat disc of dots */
.recorder__speaker::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  pointer-events: none;
  background: linear-gradient(158deg, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0.02) 26%, rgba(255,255,255,0) 48%);
}

/* ---------- the cassette compartment ---------- */
/* A door set INTO the body — it keeps a frame on all four sides, so you
   read a compartment with a lid. The old version ran the tape wall to
   wall, which is exactly why it looked like a picture frame around a
   label instead of a machine holding a cassette. */
.recorder__bay {
  position: relative;
  border-radius: 5px;
  padding: 6.5% 6% 5.5%;
  background: linear-gradient(172deg,
    color-mix(in srgb, var(--shell) 84%, #fff 16%) 0%,
    color-mix(in srgb, var(--shell) 96%, #fff 4%) 46%,
    color-mix(in srgb, var(--shell) 88%, #000 12%) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.20),
    inset 0 -1px 0 rgba(0,0,0,0.35),
    0 1px 2px rgba(0,0,0,0.32),
    0 0 0 1px rgba(0,0,0,0.22);
}
/* the hinge, along the top edge of the lid */
.recorder__bay::before {
  content: ""; position: absolute;
  left: 14%; right: 14%; top: 2.5%;
  height: 2px; border-radius: 1px;
  background: linear-gradient(180deg, rgba(0,0,0,0.42), rgba(255,255,255,0.14));
}

/* the window in the lid, and the tape behind it */
.recorder__window {
  position: relative;
  aspect-ratio: 2.55 / 1;
  border-radius: 3px;
  overflow: hidden;
  background: linear-gradient(180deg, #17130f 0%, #0b0806 100%);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,0.8),
    0 1px 0 rgba(255,255,255,0.09);
}
/* the cassette itself: the tapes' own label stock, its title line still
   unwritten — which is the whole point of this slot, said more quietly
   than a caption could */
.recorder__tape {
  position: absolute;
  left: 4%; right: 4%; top: 9%; bottom: 9%;
  border-radius: 1.5px;
  background:
    repeating-linear-gradient(0deg, transparent 0 8px, rgba(110,90,60,0.18) 8px 9px) 0 14% / 100% 34% no-repeat,
    linear-gradient(180deg, #ece5d2, #ded6bf);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.5),
    inset 0 -1px 0 rgba(0,0,0,0.18),
    0 1px 2px rgba(0,0,0,0.5);
}
/* the moulded hub plate punched through the label — the same assembly,
   tape window and drive hubs every cassette on the wall carries */
.recorder__hubs {
  position: absolute; z-index: 2;
  left: 9%; right: 9%; top: 50%;
  transform: translateY(-50%);
  height: 62%;
  display: flex; align-items: center; justify-content: space-between;
  padding-inline: 4%;
  border-radius: clamp(5px, 1vw, 9px);
  background: linear-gradient(180deg, #211c16 0%, #0d0a07 55%, #070504 100%);
  box-shadow:
    0 1px 2px rgba(0,0,0,0.45),
    0 0 0 1px rgba(0,0,0,0.55),
    inset 0 1px 0 rgba(255,255,255,0.10),
    inset 0 -2px 5px rgba(0,0,0,0.65);
  overflow: hidden;
}
.recorder__hubs::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 32%; height: 56%;
  transform: translate(-50%, -50%);
  border-radius: 2px;
  background:
    repeating-linear-gradient(90deg, rgba(235,228,210,0.09) 0 2px, transparent 2px 24%),
    linear-gradient(180deg, #221a12 0%, #32261a 48%, #15100a 100%);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.8);
}
/* the window glass: one rake across the top lip. No resting halo, no bloom. */
.recorder__glass {
  position: absolute; inset: 0; z-index: 3;
  border-radius: 3px;
  pointer-events: none;
  background: linear-gradient(162deg,
    rgba(255,255,255,0.16) 0%,
    rgba(255,255,255,0.05) 16%,
    rgba(255,255,255,0) 38%);
}
/* the deck is running, so its hubs turn; the take-up side carries less
   tape and turns faster, as it does in life */
.recorder .reel--left  { animation: reel-turn 5.6s linear infinite; }
.recorder .reel--right { animation: reel-turn 3.8s linear infinite; }

/* ---------- the strip under the window: model plate + tape counter ---------- */
.recorder__strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8%;
  margin-top: 6%;
}
.recorder__model {
  font-family: var(--font-label);
  font-size: clamp(6.5px, 0.82vw, 9px);
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  /* printed on the plastic rather than painted onto it: just off the
     shell's own value instead of in a contrasting colour */
  color: rgba(238, 231, 216, 0.58);
  white-space: nowrap;
}
/* A real four-digit tape counter, in its own little sunk window. The last
   wheel turns, because the tape is running — motion that reports
   something true rather than motion for its own sake. */
.recorder__counter {
  display: flex;
  gap: 1.5px;
  padding: 2px;
  border-radius: 2px;
  background: #100d0a;
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.85), 0 1px 0 rgba(255,255,255,0.07);
}
.recorder__counter i,
.recorder__roll {
  --digit-h: clamp(10px, 1.35vw, 15px);
  display: block;
  width: clamp(8px, 1vw, 11.5px);
  height: var(--digit-h);
  overflow: hidden;
  border-radius: 1px;
  background: linear-gradient(180deg, #d9d1bb, #b6ad97);
  font-family: var(--font-label);
  font-size: clamp(8px, 1vw, 11px);
  font-weight: 700;
  line-height: var(--digit-h);
  text-align: center;
  color: #24201a;
  box-shadow: inset 0 -1px 1px rgba(0,0,0,0.32), inset 0 1px 0 rgba(255,255,255,0.4);
}
.recorder__roll b {
  display: block;
  height: var(--digit-h);
  line-height: var(--digit-h);
  font-weight: 700;
}
/* steps(10), so the wheel clicks from one digit to the next the way a
   mechanical counter does, instead of sliding smoothly between them */
@media (prefers-reduced-motion: no-preference) {
  .recorder__roll b { animation: counter-roll 14s steps(10) infinite; }
}
@keyframes counter-roll {
  to { transform: translateY(-1000%); }
}

/* ---------- the transport: piano keys that stand proud of the front ---------- */
.recorder__transport {
  position: relative; z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 5%;
}
.recorder__keys {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 3.4%;
  padding: 5% 3.4%;
  border-radius: 4px;
  /* the recessed rail the key bank sits in */
  background: linear-gradient(180deg, rgba(0,0,0,0.40), rgba(0,0,0,0.18));
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.6), 0 1px 0 rgba(255,255,255,0.07);
}
.recorder__key {
  position: relative;
  height: clamp(13px, 2.1vw, 20px);
  border-radius: 2px 2px 3.5px 3.5px;
  background: linear-gradient(180deg, #ded7c8 0%, #c6bdac 44%, #a79e8d 76%, #918879 100%);
  /* `0 3px 0` is the key's own front face, not a shadow — it is what
     makes the key stand proud of the rail rather than sit flush in it */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.78),
    inset 0 -2px 0 rgba(0,0,0,0.18),
    0 3px 0 #6a6357,
    0 4px 4px rgba(0,0,0,0.45);
}
/* the moulded ridge across a transport key's face */
.recorder__key::after {
  content: "";
  position: absolute;
  left: 26%; right: 26%; bottom: 24%;
  height: 1.5px;
  border-radius: 1px;
  background: linear-gradient(180deg, rgba(0,0,0,0.20), rgba(255,255,255,0.34));
}
/* record is held down: it sits at the rail, loses its front face, and
   takes the recess's shadow across it */
.recorder__key--rec {
  display: grid;
  place-items: center;
  transform: translateY(3px);
  background: linear-gradient(180deg, #9a9184 0%, #877f72 60%, #6f695d 100%);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,0.55),
    inset 0 -1px 0 rgba(255,255,255,0.14);
}
.recorder__key--rec::after { display: none; }
.recorder__lamp {
  display: block;
  width: clamp(5px, 0.8vw, 8px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #ff8a6e 0%, #e0472f 46%, #a82a19 100%);
  box-shadow:
    /* the housing it sits in, then a tight lamp glow — never a bloom */
    0 0 0 1.5px rgba(28, 20, 14, 0.6),
    inset 0 -1px 1px rgba(90, 15, 5, 0.55),
    0 0 4px rgba(216, 64, 44, 0.5);
  animation: recorder-led-blink 1.3s ease-in-out infinite;
}
@keyframes recorder-led-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}
/* the external mic jack, at the end of the front edge */
.recorder__port {
  position: relative;
  display: block;
  width: clamp(11px, 1.7vw, 16px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 34%, #2a251f 0%, #120f0b 62%, #080605 100%);
  box-shadow:
    0 0 0 1.5px color-mix(in srgb, var(--shell) 78%, #000 22%),
    0 0 0 2.5px rgba(255,255,255,0.06),
    inset 0 1px 2px rgba(0,0,0,0.9),
    inset 0 -1px 0 rgba(255,255,255,0.06);
}

.recorder__caption {
  margin: 14px 0 0;
  /* the site's own annotation voice — the same pen-italic as the print
     captions on the about page and the note under the hero camera */
  font-family: var(--font-hand); font-style: italic;
  font-size: clamp(13px, 1.5vw, 16px);
  color: var(--ink-muted);
  text-align: center;
  transform: rotate(-0.6deg);
}

@media (prefers-reduced-motion: reduce) {
  .recorder__lamp { animation: none; opacity: 0.9; }
  .recorder .reel--left, .recorder .reel--right { animation: none; }
}

/* ============================================================
   9. THE ABOUT CONSOLE — vintage electronics panel
   ============================================================ */
.about-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
.about-copy h3.chip { margin-bottom: 16px; }
.about-copy p { color: var(--ink-muted); font-size: clamp(15px, 1.9vw, 18px); margin-top: 14px; max-width: 46ch; }
.about-copy p b { color: var(--ink); font-weight: 600; }

/* career timeline */
.timeline { margin-top: 28px; display: grid; gap: 2px; }
.timeline__row {
  display: grid; grid-template-columns: 92px 1fr; gap: 14px; align-items: baseline;
  padding: 12px 0; border-top: 1px solid rgba(0,0,0,0.08);
}
.timeline__row:last-child { border-bottom: 1px solid rgba(0,0,0,0.08); }
.timeline__yr { font-family: var(--font-label); font-size: 12px; font-weight: 600; color: var(--ink-muted); }
.timeline__role b { display: block; font-weight: 600; }
.timeline__role span { font-size: 14px; color: var(--ink-muted); }

/* the device housing */
.console {
  position: relative;
  border-radius: 30px;
  padding: 22px;
  display: grid;
  gap: 18px;
  background:
    radial-gradient(120% 90% at 14% 8%, rgba(255,255,255,0.48), transparent 52%),
    linear-gradient(160deg, var(--metal-1) 0%, var(--metal-2) 40%, var(--metal-3) 100%);
  box-shadow:
    0 24px 48px rgba(0,0,0,0.20),
    inset 0 1px 0 rgba(255,255,255,0.8),
    inset 0 -3px 8px rgba(0,0,0,0.14);
}
/* panel grid texture, layered */
.console::before {
  content: ""; position: absolute; inset: 0; border-radius: 30px; pointer-events: none;
  background-image:
    repeating-linear-gradient(0deg, rgba(0,0,0,0.04) 0 1px, transparent 1px 11px),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.05) 0 1px, transparent 1px 11px);
  opacity: 0.9;
}
.console > * { position: relative; z-index: 1; }
.console .screw { position: absolute; z-index: 2; transform: none; }
.console .screw--tl { top: 12px; left: 12px; }
.console .screw--tr { top: 12px; right: 12px; }
.console .screw--bl { bottom: 12px; left: 12px; }
.console .screw--br { bottom: 12px; right: 12px; }

/* --- Now Playing player --- */
.player {
  border-radius: 16px;
  padding: 16px 18px;
  background:
    repeating-linear-gradient(0deg, rgba(255,255,255,0.03) 0 1px, transparent 1px 3px),
    linear-gradient(180deg, var(--metal-dark-1), var(--metal-dark-2));
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.2), 0 2px 4px rgba(0,0,0,0.2);
  color: #f1f1f1;
}
.player__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.player__np { font-family: var(--font-label); font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: #d7d7d7; display: flex; align-items: center; gap: 7px; }
.player__np .led { width: 7px; height: 7px; }
.player__title { font-weight: 700; font-size: 15px; letter-spacing: -0.01em; }
.player__artist { font-size: 12px; color: #c4c4c4; }
.player__track { display: flex; flex-direction: column; gap: 2px; margin-bottom: 14px; }

.progress {
  position: relative; height: 14px; border-radius: 999px; cursor: pointer;
  background: linear-gradient(180deg, #4a4a4a, #5e5e5e);
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.12);
}
.progress__fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 38%;
  border-radius: 999px;
  background: linear-gradient(180deg, #fdf2a8, var(--vu-amber));
  box-shadow: 0 0 9px var(--vu-amber-glow), inset 0 1px 0 rgba(255,255,255,0.6);
}
.progress__thumb {
  position: absolute; top: 50%; left: 38%; width: 16px; height: 16px; border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle at 35% 30%, #fff, #d9d9d9 60%, #aeaeae);
  box-shadow: 0 1px 3px rgba(0,0,0,0.5), inset 0 0 2px rgba(0,0,0,0.2);
}
.player__time { display: flex; justify-content: space-between; font-family: var(--font-label); font-size: 10px; color: #c4c4c4; margin-top: 6px; }

.player__controls { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 12px; }
.ctrl {
  width: 40px; height: 40px; border-radius: 50%; border: 0;
  display: grid; place-items: center;
  color: #2a2a2a;
  background: linear-gradient(180deg, #e9e9e9, #cfcfcf);
  box-shadow: 0 2px 4px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.8), inset 0 -2px 3px rgba(0,0,0,0.15);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ctrl:active { transform: translateY(1px) scale(0.985); box-shadow: var(--press); }
.ctrl--play { width: 50px; height: 50px; }
.ctrl svg { width: 16px; height: 16px; fill: currentColor; }
.ctrl--play svg { width: 18px; height: 18px; }

/* --- Walkman illustration (inline SVG sits here) --- */
.walkman { display: grid; place-items: center; padding: 6px 0; }
.walkman svg { width: 100%; max-width: 320px; height: auto; filter: drop-shadow(0 6px 10px rgba(0,0,0,0.22)); }

/* --- Chat panel --- */
.chat {
  border-radius: 16px;
  padding: 14px;
  background: linear-gradient(180deg, #ececec, #e0e0e0);
  box-shadow: inset 0 2px 5px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.7), 0 2px 4px rgba(0,0,0,0.12);
}
.chat__log { display: flex; flex-direction: column; gap: 8px; max-height: 210px; overflow-y: auto; padding: 4px; }
.bubble {
  max-width: 78%; padding: 9px 13px; border-radius: 18px; font-size: 14px; line-height: 1.35;
  animation: bubble-pop-in 320ms var(--ease) both;
}
.bubble--in { align-self: flex-start; background: #dfe2e7; color: #111; border-bottom-left-radius: 5px; }
.bubble--out { align-self: flex-end; color: #fff; border-bottom-right-radius: 5px;
  background: linear-gradient(165deg, var(--chat-blue-1) 0%, var(--chat-blue-2) 100%); }
.bubble--typing { display: inline-flex; gap: 4px; align-items: center; }
.bubble--typing i { width: 6px; height: 6px; border-radius: 50%; background: #9aa0a8; animation: typing 1.2s var(--ease) infinite; }
.bubble--typing i:nth-child(2) { animation-delay: 0.15s; }
.bubble--typing i:nth-child(3) { animation-delay: 0.3s; }
@keyframes typing { 0%,60%,100% { transform: translateY(0); opacity: 0.5; } 30% { transform: translateY(-4px); opacity: 1; } }
@keyframes bubble-pop-in { from { opacity: 0; transform: translateY(8px) scale(0.92); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes bubble-pop-out { to { opacity: 0; transform: translateY(6px) scale(0.95); } }

.chat__form { display: flex; gap: 8px; margin-top: 10px; align-items: center; }
.chat__input {
  flex: 1; height: 40px; padding: 0 14px; border-radius: 999px; border: 0;
  font-family: inherit; font-size: 14px; color: #111;
  background: #fff;
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.12), inset 0 0 0 1px rgba(0,0,0,0.06);
}
.chat__input:focus { outline: none; box-shadow: inset 0 2px 4px rgba(0,0,0,0.12), inset 0 0 0 2px var(--chat-blue-1); }
.chat__send {
  width: 40px; height: 40px; border-radius: 50%; border: 0; display: grid; place-items: center;
  background: #c3c6cb; color: #fff; transition: background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.chat__send.is-active { background: linear-gradient(165deg, var(--chat-blue-1), var(--chat-blue-2)); }
.chat__send:active { transform: scale(0.92); }
.chat__send svg { width: 16px; height: 16px; fill: currentColor; }

/* ============================================================
   9a. THE POLAROID WALL — instant photos of Derrick's world
   (the hero camera's output, pinned to the wall; hover straightens)
   ============================================================ */
.about-aside { align-self: start; }
.about-aside > .chip { margin-bottom: 14px; }
.about-aside__hint {
  font-family: var(--font-hand); font-style: italic; font-size: 16px; color: var(--ink-faint);
  margin: 0 0 4px 2px;
}
/* loose photos scattered on a surface — JS positions + drags them freely */
.pwall {
  /* min-height only: layout() in audit-main.js measures the prints and sets
     the real height, so the wall fits its contents (rotated bounding boxes
     included) at one column, two, or three instead of at one fixed width. */
  position: relative; min-height: 320px; margin-top: 6px;
  touch-action: none;
}
/* Without JS, layout() never runs and every print keeps its absolute
   left:0/top:0 — all nine land in one pile in the corner. The wall falls back
   to an ordinary grid until the script confirms it can place them. */
html:not(.js) .pwall {
  height: auto !important;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 22px;
}
html:not(.js) .pol {
  position: relative;
  width: 100%;
  transform: none;
}

.pol {
  position: absolute; left: 0; top: 0; margin: 0;
  width: clamp(228px, 66%, 296px);
  padding: 14px 14px 33px; border-radius: 5px;
  background: linear-gradient(177deg, #fffffe 0%, #f6f3ec 70%, #efe9dd 100%);
  box-shadow:
    0 14px 26px rgba(20,16,10,0.22), 0 4px 8px rgba(0,0,0,0.16),
    inset 0 1px 0 rgba(255,255,255,0.9), inset 0 0 0 1px rgba(0,0,0,0.05);
  cursor: grab;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  touch-action: none;
  transition: box-shadow 200ms var(--ease);
  /* will-change is set inline by JS only for the duration of an actual
     drag + its momentum settle (see the polaroid-wall IIFE) — nine
     photos sitting motionless don't need a standing GPU layer each */
}
.pol__img {
  position: relative; aspect-ratio: 1 / 1; border-radius: 2px; overflow: hidden;
  box-shadow:
    inset 0 0 0 1px rgba(0,0,0,0.12),
    inset 0 3px 10px rgba(0,0,0,0.28),
    inset 0 1px 3px rgba(0,0,0,0.18),
    inset 3px 0 8px rgba(0,0,0,0.10),
    inset -3px 0 8px rgba(0,0,0,0.10),
    inset 0 -2px 6px rgba(0,0,0,0.10);
}
.pol__img svg, .pol__img img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* instant-film grain — cheap static dot texture (no feTurbulence / blend-mode,
   which choke software rasterizers and low-end GPUs) */
.pol__img::before {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; opacity: 0.5;
  background-image:
    radial-gradient(rgba(255,255,255,0.16) 0.5px, transparent 0.7px),
    radial-gradient(rgba(0,0,0,0.16) 0.5px, transparent 0.7px);
  background-size: 3px 3px, 3px 3px;
  background-position: 0 0, 1.5px 1.5px;
}
/* vignette + corner light-leak + faded film colour cast */
.pol__img::after {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background:
    radial-gradient(126% 120% at 50% 42%, transparent 50%, rgba(0,0,0,0.22) 100%),
    radial-gradient(70% 55% at 80% 6%, rgba(255,238,200,0.26), transparent 62%),
    linear-gradient(180deg, rgba(255,228,180,0.05), rgba(118,162,202,0.07));
}
.pol__cap {
  font-family: var(--font-hand); font-style: italic; font-size: 19px; line-height: 1.05; color: #534d43;
  text-align: center; padding: 9px 4px 13px;
}
.pol.is-grab { cursor: grabbing; }
.pol.is-grab {
  box-shadow:
    0 34px 56px rgba(20,16,10,0.32), 0 12px 22px rgba(0,0,0,0.22),
    inset 0 1px 0 rgba(255,255,255,0.95), inset 0 0 0 1px rgba(0,0,0,0.05);
}
.pol:focus-visible { outline: 2px solid var(--led); outline-offset: 3px; }

/* ============================================================
   9b. THE DECK — (retired on homepage; styles kept for reference)
   ============================================================ */
.deck {
  --deck-amber: #f6c463;
  --deck-amber-soft: rgba(246,196,99,0.55);
  position: relative;
  border-radius: 28px;
  padding: 20px 20px 22px;
  display: grid;
  gap: 16px;
  isolation: isolate;
  background:
    linear-gradient(157deg, #3a3a40 0%, #27272c 44%, #1b1b20 100%);
  box-shadow:
    0 32px 60px rgba(0,0,0,0.40),
    0 8px 18px rgba(0,0,0,0.28),
    inset 0 1px 0 rgba(255,255,255,0.16),
    inset 0 0 0 1px rgba(0,0,0,0.5),
    inset 0 -5px 12px rgba(0,0,0,0.55);
}
/* fine vertical brushed-metal texture + soft top sheen */
.deck::before {
  content: ""; position: absolute; inset: 0; border-radius: 28px; pointer-events: none; z-index: -1;
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,0.035) 0 1px, transparent 1px 3px),
    radial-gradient(130% 70% at 50% -8%, rgba(255,255,255,0.10), transparent 60%);
}
.deck > * { position: relative; }
.deck .screw {
  position: absolute; z-index: 3; width: 11px; height: 11px; border-radius: 50%;
  background: radial-gradient(circle at 38% 30%, #54545a, #1d1d20 72%);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.6), inset 0 1px 1px rgba(255,255,255,0.25), 0 1px 1px rgba(0,0,0,0.4);
}
.deck .screw::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 7px; height: 1.4px; border-radius: 1px;
  background: rgba(0,0,0,0.55); transform: rotate(42deg);
}
.deck .screw--tl { top: 12px; left: 12px; }
.deck .screw--tr { top: 12px; right: 12px; }
.deck .screw--bl { bottom: 12px; left: 12px; }
.deck .screw--br { bottom: 12px; right: 12px; }

.deck__brand { display: flex; align-items: baseline; justify-content: space-between; padding: 2px 14px 0; }
.deck__logo {
  font-family: var(--font-label); font-weight: 800; font-size: 13px; letter-spacing: 0.26em; color: #e7e6e2;
  text-shadow: 0 1px 0 rgba(0,0,0,0.6), 0 0 1px rgba(255,255,255,0.2);
}
.deck__model { font-family: var(--font-label); font-weight: 700; font-size: 8.5px; letter-spacing: 0.16em; color: #85858b; }

/* ---- backlit LCD ---- */
.lcd {
  position: relative; overflow: hidden;
  border-radius: 12px; padding: 13px 15px 14px;
  background:
    radial-gradient(120% 150% at 50% -10%, rgba(246,196,99,0.16), transparent 62%),
    linear-gradient(180deg, #16140c 0%, #0d0c07 100%);
  box-shadow:
    inset 0 2px 9px rgba(0,0,0,0.85), inset 0 0 0 1px rgba(246,196,99,0.10),
    0 1px 0 rgba(255,255,255,0.06);
  color: var(--deck-amber);
}
.lcd__scan {
  position: absolute; inset: 0; pointer-events: none; opacity: 0.5;
  background: repeating-linear-gradient(0deg, rgba(0,0,0,0.22) 0 1px, transparent 1px 3px);
}
.lcd__row { display: flex; align-items: center; justify-content: space-between; }
.lcd__np {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-label); font-size: 9.5px; font-weight: 700; letter-spacing: 0.16em;
  color: #e0b873;
}
.lcd__np .led { width: 7px; height: 7px; box-shadow: 0 0 7px var(--deck-amber-soft); }
/* Named `deck-led-pulse`, not `led-pulse`: this used to redeclare the same
   keyframe name as the hero/section LED at the top of the file, and a later
   @keyframes of the same name silently replaces the earlier one document-wide.
   The hero LED was quietly running this 0.45 curve instead of its own 0.55. */
.deck.is-playing .lcd__np .led { animation: deck-led-pulse 1.6s var(--ease) infinite; }
@keyframes deck-led-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.45; } }
.lcd__side { font-family: var(--font-label); font-size: 9px; font-weight: 700; letter-spacing: 0.14em; color: #9c7f4e; }
.lcd__marquee { overflow: hidden; white-space: nowrap; margin-top: 9px; }
.lcd__title {
  display: inline-block;
  font-weight: 800; font-size: 17px; letter-spacing: 0.01em; color: #fcd684;
  text-shadow: 0 0 8px rgba(246,196,99,0.45);
}
.lcd__artist {
  font-family: var(--font-label); font-size: 11px; color: #b08f57; margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.seek {
  position: relative; height: 7px; margin-top: 12px; border-radius: 999px; cursor: pointer;
  background: linear-gradient(180deg, #07060333, #0000 60%), #251f10;
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.9), inset 0 -1px 0 rgba(246,196,99,0.10);
}
.seek__fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0%;
  border-radius: 999px;
  background: linear-gradient(180deg, #ffe6a0, var(--deck-amber));
  box-shadow: 0 0 8px var(--deck-amber-soft), inset 0 1px 0 rgba(255,255,255,0.55);
}
.seek__thumb {
  position: absolute; top: 50%; left: 0%; width: 13px; height: 13px; border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle at 36% 30%, #fff, #f0dcab 55%, #caa657);
  box-shadow: 0 1px 3px rgba(0,0,0,0.6);
}
.lcd__time {
  display: flex; justify-content: space-between; margin-top: 7px;
  font-family: var(--font-label); font-size: 9.5px; letter-spacing: 0.06em; color: #9c7f4e;
}

/* ---- cassette window with live reels ---- */
.deck__window {
  position: relative; overflow: hidden;
  border-radius: 12px; padding: 13px;
  background: linear-gradient(180deg, #0a0a0d, #121216);
  box-shadow: inset 0 2px 8px rgba(0,0,0,0.85), inset 0 0 0 1px rgba(255,255,255,0.05);
}
.deck__window::after { /* angled glass glare across the smoked window */
  content: ""; position: absolute; top: -20%; left: -10%; width: 55%; height: 150%;
  background: linear-gradient(105deg, rgba(255,255,255,0.10), rgba(255,255,255,0) 70%);
  transform: rotate(8deg); pointer-events: none;
}
.cass {
  position: relative; height: 118px; border-radius: 7px;
  background: linear-gradient(180deg, #e2dcc5, #cfc8ad);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.5), 0 2px 5px rgba(0,0,0,0.45), inset 0 0 0 1px rgba(120,108,82,0.5);
}
.cass__label {
  position: absolute; top: 9px; left: 10px; right: 10px; height: 38px;
  border-radius: 4px; padding: 6px 8px;
  background: linear-gradient(180deg, #f3eedc, #e7e0c8);
  box-shadow: inset 0 0 0 1px rgba(138,112,78,0.22);
}
.cass__side {
  position: absolute; top: 5px; left: 6px; width: 14px; height: 14px; border-radius: 3px;
  display: grid; place-items: center;
  font-family: var(--font-label); font-size: 9px; font-weight: 800; color: #f1ecdf; background: #1d1812;
}
.cass__label i { position: absolute; left: 26px; right: 8px; height: 1px; background: rgba(138,112,78,0.4); }
.cass__label i:nth-child(2) { top: 14px; } .cass__label i:nth-child(3) { top: 22px; }
.cass__tape {
  position: absolute; left: 14px; right: 14px; top: 56px; height: 46px; border-radius: 22px;
  background: radial-gradient(120% 120% at 50% 50%, #1a140d, #0c0907);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.8), inset 0 0 0 1px rgba(0,0,0,0.5);
}
.cass__hub {
  position: absolute; top: 58px; width: 40px; height: 40px; border-radius: 50%; z-index: 2;
  background:
    repeating-conic-gradient(from 0deg, #efeade 0deg 11deg, #2a2018 11deg 22deg);
  box-shadow: 0 0 0 4px #0c0907, inset 0 0 0 6px #0c0907, 0 1px 2px rgba(0,0,0,0.6);
}
.cass__hub::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 9px; height: 9px; border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #efeade, #b9b29c);
}
.cass__hub--l { left: 40px; }
.cass__hub--r { right: 40px; }
.deck.is-playing .cass__hub { animation: reel-spin 2.6s linear infinite; }
@keyframes reel-spin { to { transform: rotate(360deg); } }

/* ---- stereo VU meters (scoped to .deck so it can't touch case-study .vu) ---- */
.deck .vu { display: grid; gap: 7px; padding: 2px 2px 0; }
.vu__ch { display: flex; align-items: center; gap: 9px; }
.vu__lbl {
  width: 12px; font-family: var(--font-label); font-size: 9px; font-weight: 800; letter-spacing: 0.05em;
  color: #8a8a90; text-align: center;
}
.vu__bars { flex: 1; display: flex; align-items: flex-end; gap: 3px; height: 20px; }
.vu__bars i {
  flex: 1; height: 100%; border-radius: 1.5px; transform-origin: bottom; transform: scaleY(0.22);
  background: linear-gradient(180deg, #ffe39a 0%, var(--deck-amber) 55%, #b9772e 100%);
  box-shadow: 0 0 4px rgba(246,196,99,0.35);
  transition: transform 240ms var(--ease);
}
.deck.is-playing .vu__bars i { animation: vu-bounce 900ms ease-in-out infinite; }
.vu__bars i:nth-child(7n+1) { animation-duration: 760ms; }
.vu__bars i:nth-child(7n+2) { animation-duration: 1080ms; animation-delay: -120ms; }
.vu__bars i:nth-child(7n+3) { animation-duration: 880ms;  animation-delay: -300ms; }
.vu__bars i:nth-child(7n+4) { animation-duration: 1180ms; animation-delay: -90ms; }
.vu__bars i:nth-child(7n+5) { animation-duration: 700ms;  animation-delay: -240ms; }
.vu__bars i:nth-child(7n+6) { animation-duration: 1000ms; animation-delay: -420ms; }
.vu__bars i:nth-child(7n+7) { animation-duration: 820ms;  animation-delay: -160ms; }
.vu__ch:last-child .vu__bars i { animation-direction: alternate-reverse; }
@keyframes vu-bounce {
  0%   { transform: scaleY(0.18); }
  25%  { transform: scaleY(0.62); }
  50%  { transform: scaleY(0.95); }
  72%  { transform: scaleY(0.4); }
  100% { transform: scaleY(0.74); }
}

/* ---- transport keys + volume knob ---- */
.deck__foot { display: flex; align-items: center; gap: 12px; }
.transport { flex: 1; display: flex; gap: 8px; }
.tkey {
  flex: 1; height: 38px; border: 0; border-radius: 8px; cursor: pointer;
  display: grid; place-items: center; color: #2a2723;
  background: linear-gradient(180deg, #ecebe6 0%, #cbc9c2 100%);
  box-shadow:
    0 2px 4px rgba(0,0,0,0.4), 0 4px 9px rgba(0,0,0,0.28),
    inset 0 1px 0 rgba(255,255,255,0.9), inset 0 -2px 3px rgba(0,0,0,0.18);
  transition: transform 90ms var(--ease), box-shadow 90ms var(--ease);
}
.tkey svg { width: 17px; height: 17px; fill: currentColor; }
.tkey:active { transform: translateY(2px); box-shadow: inset 0 2px 5px rgba(0,0,0,0.4), inset 0 -1px 0 rgba(255,255,255,0.3); }
.tkey--play {
  flex: 1.4; color: #3a2c08;
  background: linear-gradient(180deg, #ffd982 0%, var(--deck-amber) 60%, #cf9a39 100%);
  box-shadow:
    0 2px 5px rgba(0,0,0,0.4), 0 5px 12px rgba(180,120,30,0.35),
    inset 0 1px 0 rgba(255,255,255,0.7), inset 0 -2px 4px rgba(120,80,15,0.4);
}
.tkey--play .ic-pause { display: none; }
.deck.is-playing .tkey--play .ic-play { display: none; }
.deck.is-playing .tkey--play .ic-pause { display: block; }
.knob {
  position: relative; width: 44px; height: 44px; border-radius: 50%; flex: none;
  background:
    repeating-conic-gradient(from 0deg, #3a3a40 0deg 7deg, #222226 7deg 14deg);
  box-shadow: 0 3px 7px rgba(0,0,0,0.5), inset 0 0 0 1px rgba(255,255,255,0.12), inset 0 -2px 4px rgba(0,0,0,0.6);
}
.knob::before {
  content: ""; position: absolute; inset: 7px; border-radius: 50%;
  background: radial-gradient(circle at 38% 30%, #44444a, #1c1c20 72%);
  box-shadow: inset 0 1px 1px rgba(255,255,255,0.18);
}
.knob i {
  position: absolute; left: 50%; top: 8px; width: 2.5px; height: 11px; border-radius: 2px;
  background: var(--deck-amber); transform: translateX(-50%);
  box-shadow: 0 0 5px var(--deck-amber-soft); z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
  .deck.is-playing .cass__hub,
  .deck.is-playing .vu__bars i,
  .deck.is-playing .lcd__np .led { animation: none; }
}

/* ============================================================
   10. ANIMATED AVATAR
   ============================================================ */
.avatar {
  position: relative;
  width: 214px; height: 214px; max-width: 100%;
  border-radius: 32px;
  border: 5px solid #e9e7e2;
  overflow: hidden;
  /* warm paper backing — the line-art portrait reads as printed ink */
  background:
    radial-gradient(130% 120% at 28% 18%, #fbf9f4, #ece9e2 70%, #e2dfd7);
  box-shadow: 0 12px 28px rgba(40,32,20,0.20), inset 0 0 0 1px rgba(0,0,0,0.06), inset 0 1px 0 rgba(255,255,255,0.7);
}
.avatar svg g { transform-box: fill-box; transform-origin: center; }
.avatar::before { /* light source that follows the mouse */
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: radial-gradient(120px 120px at calc(50% + var(--avatar-x, 0px) * 6) calc(38% + var(--avatar-y, 0px) * 6),
              rgba(255,255,255,0.32), transparent 60%);
}
.avatar::after {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: radial-gradient(140px 140px at calc(70% - var(--avatar-x,0px)*5) calc(80% - var(--avatar-y,0px)*5),
              rgba(0,0,0,0.12), transparent 55%);
}
.avatar svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.avatar-shell { transform: rotate(calc(var(--avatar-x, 0px) * 0.15deg)); transform-origin: 50% 60%; transition: transform 120ms var(--ease); }
.avatar-features { transform: translate(calc(var(--avatar-x,0px) * 1.25), calc(var(--avatar-y,0px) * 1.25)); transition: transform 90ms var(--ease); }
.avatar-pupils { transform: translate(calc(var(--avatar-x,0px) * 1.05), calc(var(--avatar-y,0px) * 1.05)); transition: transform 70ms var(--ease); }
.avatar-pupils.is-blinking { transform: translate(calc(var(--avatar-x,0px)*1.05), calc(var(--avatar-y,0px)*1.05)) scaleY(0.08); transform-origin: center; }

.about-id { display: flex; gap: 20px; align-items: center; margin-bottom: 30px; }
.about-id__txt b { font-size: 20px; }
.about-id__txt span { display: block; color: var(--ink-muted); font-size: 14px; }
.about-id__txt .tagline { font-family: var(--font-hand); font-style: italic; font-size: 21px; color: var(--ink); margin-top: 6px; }

/* ============================================================
   11. BUTTONS / LINKS (physical)
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-label); font-weight: 700; font-size: 13px;
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 13px 22px; border: 0; border-radius: 999px;
  color: var(--ink);
  background: linear-gradient(180deg, #ece9e3, #d4d1ca);
  box-shadow: var(--lift-1);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), filter var(--dur) var(--ease);
}
/* tonal hover, not a lift — the boop is banned; depth reads through the
   shadow deepening and the fill brightening in place instead of moving */
.btn:hover { box-shadow: var(--lift-2); filter: brightness(1.04); }
.btn:active { transform: translateY(1px) scale(0.99); box-shadow: var(--press); filter: none; }
.btn--dark { color: var(--bg); background: linear-gradient(180deg, #2e2e2e, #161616);
  box-shadow: 0 8px 16px rgba(0,0,0,0.28), inset 0 1px 0 rgba(255,255,255,0.18); }
.btn--dark:hover { box-shadow: 0 12px 22px rgba(0,0,0,0.34), inset 0 1px 0 rgba(255,255,255,0.2); }

.link-ul { border-bottom: 1.5px solid currentColor; padding-bottom: 1px; transition: opacity var(--dur) var(--ease); }
.link-ul:hover { opacity: 0.6; }

/* ============================================================
   12. CASE STUDY — keeps the physical language
   ============================================================ */
.cs-hero { padding-top: clamp(30px, 6vw, 64px); }
.cs-hero__kicker { font-family: var(--font-label); font-size: 12px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-muted); }
.cs-hero h1 { font-size: clamp(32px, 5.4vw, 60px); line-height: 1.04; margin-top: 14px; max-width: 18ch; }
.cs-hero__lede { font-size: clamp(17px, 2.2vw, 22px); color: var(--ink-muted); max-width: 54ch; margin-top: 20px; }

/* big "cassette being played" hero graphic */
.cs-tape {
  margin: clamp(30px,5vw,52px) auto;
  max-width: 540px;
}
.cs-tape .mixtape__shell { aspect-ratio: 1.58 / 1; }

/* context / TL;DR console */
.spec {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  border-radius: 18px; overflow: hidden; margin: 34px 0;
  background: rgba(0,0,0,0.08);
  box-shadow: var(--lift-1);
}
.spec__cell { padding: 18px 20px; background: linear-gradient(180deg, #e7e4de, #dbd8d1); }
.spec__cell .k { font-family: var(--font-label); font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-muted); }
.spec__cell .v { font-weight: 600; font-size: 15px; margin-top: 5px; }

.tldr {
  border-radius: 18px; padding: 22px 24px; margin: 30px 0;
  background:
    repeating-linear-gradient(0deg, rgba(0,0,0,0.03) 0 1px, transparent 1px 3px),
    linear-gradient(180deg, var(--metal-dark-1), var(--metal-dark-2));
  color: #f2f2f2;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.35), 0 4px 10px rgba(0,0,0,0.18);
}
.tldr .k { font-family: var(--font-label); font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: #d3d3d3; display: inline-flex; align-items: center; gap: 8px; }
.tldr p { margin-top: 10px; font-size: clamp(16px,2vw,19px); max-width: 60ch; }

/* metric LED readouts (VU panel) */
.vu { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 16px; margin: 28px 0; }
.vu__cell {
  border-radius: 16px; padding: 20px;
  background: linear-gradient(180deg, #1c1c1c, #0e0e0e);
  box-shadow: 0 8px 16px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.08);
}
.vu__num { font-family: var(--font-label); font-weight: 800; font-size: clamp(30px, 4.4vw, 44px); letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--vu-amber); text-shadow: 0 0 14px var(--vu-amber-glow); }
.vu__num small { font-size: 0.55em; }
.vu__label { color: #b9b9b9; font-size: 13px; margin-top: 6px; }

/* case study body prose */
.cs-body { display: grid; grid-template-columns: 200px 1fr; gap: clamp(28px, 5vw, 64px); align-items: start; margin-top: 20px; }
.cs-toc { position: sticky; top: 92px; }
.cs-toc__title { font-family: var(--font-label); font-size: 10px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-muted); margin-bottom: 12px; }
.cs-toc a {
  display: block; font-size: 13.5px; color: var(--ink-muted); padding: 7px 12px; border-radius: 8px;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.cs-toc a:hover { color: var(--ink); }
.cs-toc a.is-active { color: var(--ink); background: rgba(0,0,0,0.06); box-shadow: var(--press); }

.prose { max-width: 68ch; }
.prose section { margin-bottom: clamp(40px, 6vw, 72px); scroll-margin-top: 92px; }
.prose h2 { font-size: clamp(22px, 3vw, 30px); margin: 0 0 16px; }
.prose h3 { font-size: 18px; margin: 28px 0 8px; }
.prose p { font-size: 17px; line-height: 1.7; color: #2a2a2a; margin-top: 14px; }
.prose p:first-of-type { margin-top: 0; }
.prose ul { margin: 14px 0 0; padding-left: 0; list-style: none; display: grid; gap: 10px; }
.prose ul li { position: relative; padding-left: 26px; font-size: 16px; line-height: 1.6; color: #2a2a2a; }
.prose ul li::before { content: ""; position: absolute; left: 4px; top: 9px; width: 8px; height: 8px; border-radius: 2px;
  background: var(--ink); box-shadow: 0 0 0 3px rgba(0,0,0,0.06); }
.prose strong { font-weight: 700; color: var(--ink); }

/* findings / insight cards */
.cards { display: grid; gap: 14px; margin-top: 18px; }
.card {
  border-radius: 14px; padding: 18px 20px;
  background: linear-gradient(180deg, #e7e4de, #dad7d0);
  box-shadow: var(--lift-1);
}
.card .n { font-family: var(--font-hand); font-style: italic; font-size: 26px; line-height: 1; color: #3a3322; }
.card h4 { font-size: 16px; margin: 6px 0 6px; }
.card p { font-size: 15px; color: var(--ink-muted); line-height: 1.55; }
.card .impl { margin-top: 10px; font-size: 13px; color: var(--ink); }
.card .impl b { font-family: var(--font-label); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-muted); display: block; margin-bottom: 3px; }

/* constraint callout */
.constraint {
  border-radius: 14px; padding: 18px 20px 18px 22px; margin-top: 16px;
  background: linear-gradient(180deg, #ecebe6, #e3e1d8);
  border-left: 4px solid #b59a3f;
  box-shadow: var(--lift-1);
}
.constraint .k { font-family: var(--font-label); font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: #8a7327; }
.constraint p { margin-top: 8px; font-size: 16px; }

/* device-framed image */
.shot {
  border-radius: 20px; padding: 14px; margin: 22px 0; position: relative;
  background:
    radial-gradient(120% 90% at 14% 8%, rgba(255,255,255,0.4), transparent 50%),
    linear-gradient(160deg, var(--metal-1), var(--metal-3));
  box-shadow: var(--lift-1);
}
.shot .screen {
  border-radius: 12px; overflow: hidden; background: #cfcfcf;
  box-shadow: inset 0 2px 8px rgba(0,0,0,0.3);
  aspect-ratio: 16 / 9; display: grid; place-items: center;
  color: var(--ink-muted); font-family: var(--font-label); font-size: 13px;
}
.shot .caption { font-size: 13px; color: var(--ink-muted); margin-top: 10px; padding: 0 4px; }
.shot .screw { position: absolute; }
.shot .screw--tl { top: 8px; left: 8px; } .shot .screw--tr { top: 8px; right: 8px; }
.shot .screw--bl { bottom: 8px; left: 8px; } .shot .screw--br { bottom: 8px; right: 8px; }

/* under-construction */
.wip {
  border-radius: 18px; padding: 36px; text-align: center; margin: 28px 0;
  background: repeating-linear-gradient(45deg, #e7e2cf 0 16px, #ddd8c4 16px 32px);
  box-shadow: var(--lift-1);
}
.wip .tape-strip { font-family: var(--font-hand); font-style: italic; font-size: 28px; color: #3a3322; }
.wip p { color: var(--ink-muted); margin-top: 8px; }

/* ---------- real work imagery — one framing system everywhere ---------- */
.figure {
  margin: 22px 0; padding: 12px; border-radius: 16px;
  background: linear-gradient(180deg, #e7e4de, #dbd8d1);
  box-shadow: var(--lift-1);
}
.figure img { display: block; width: 100%; border-radius: 8px; cursor: zoom-in; }
.figure figcaption, .compare figcaption {
  font-size: 13px; color: var(--ink-muted); padding: 10px 6px 0; line-height: 1.5;
}

.gallery { display: grid; gap: 14px; margin: 22px 0; align-items: start; }
.gallery--2 { grid-template-columns: repeat(2, 1fr); }
.gallery--3 { grid-template-columns: repeat(3, 1fr); }
.gallery--5 { grid-template-columns: repeat(5, 1fr); }
.gallery .figure { margin: 0; }
.gallery--5 .figure { padding: 7px; }

/* before/after — side by side in ONE container, labels top corners,
   hairline down the middle. Never stacked. */
.compare { margin: 22px 0; }
.compare__row {
  display: grid; grid-template-columns: 1fr 1fr;
  border-radius: 16px; overflow: hidden;
  background: linear-gradient(180deg, #e7e4de, #dbd8d1);
  box-shadow: var(--lift-1);
}
.compare__half { padding: 14px; position: relative; }
.compare__half img { display: block; width: 100%; border-radius: 8px; cursor: zoom-in; }
.compare__tag {
  position: absolute; top: 22px; left: 22px; z-index: 2;
  font-family: var(--font-label); font-size: 10px; font-weight: 800;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 4px 10px; border-radius: 999px;
  color: #f3efe6; background: rgba(24,20,14,0.78);
  box-shadow: 0 1px 3px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.12);
}
.compare__half--after .compare__tag { background: linear-gradient(180deg, #357d43, #27632f); }

/* click-to-zoom lightbox */
.lightbox {
  position: fixed; inset: 0; z-index: 3000;
  display: grid; place-items: center; padding: 4vmin;
  background: rgba(26,22,17,0.84);
  -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px);
  opacity: 0; pointer-events: none; cursor: zoom-out;
  transition: opacity 200ms var(--ease);
}
.lightbox.is-open { opacity: 1; pointer-events: auto; }
@media (prefers-reduced-transparency: reduce) {
  .lightbox { background: rgba(20,17,13,0.97); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-contrast: more) {
  .lightbox { background: #0e0c0a; -webkit-backdrop-filter: none; backdrop-filter: none; }
}
.lightbox img {
  max-width: 94vw; max-height: 92vh; border-radius: 10px;
  box-shadow: 0 36px 90px rgba(0,0,0,0.55);
  transform: scale(0.96); transition: transform 220ms var(--ease);
}
.lightbox.is-open img { transform: scale(1); }

/* next project */
.cs-next { margin-top: 30px; padding-top: 30px; }

/* ============================================================
   13. FOOTER
   ============================================================ */
.footer { padding: clamp(48px, 7vw, 90px) 0 60px; }
.footer__card {
  border-radius: 26px; padding: clamp(28px, 4vw, 48px);
  background:
    radial-gradient(120% 90% at 12% 10%, rgba(255,255,255,0.45), transparent 50%),
    linear-gradient(160deg, var(--metal-1), var(--metal-3));
  box-shadow: var(--lift-1); position: relative; overflow: hidden;
}
.footer__card .screw { position: absolute; }
.footer h2 { font-size: clamp(28px, 4.5vw, 46px); max-width: 16ch; }
.footer p { color: var(--ink-muted); margin-top: 14px; max-width: 46ch; font-size: 17px; }
.footer__actions { margin-top: 26px; display: flex; flex-wrap: wrap; gap: 12px; }
.footer__meta { margin-top: 34px; display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; font-size: 13px; color: var(--ink-muted); }
.footer__hand { font-family: var(--font-hand); font-style: italic; font-size: 20px; color: var(--ink); }

/* --- minimal sign-off: confident type, one hairline + amber LED, breathing room --- */
.footer { padding: clamp(72px, 10vw, 130px) 0 64px; }
.signoff {
  max-width: 880px; margin: 0 auto; text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
.signoff__rule {
  position: relative; width: 100%; max-width: 720px; height: 1px;
  margin-bottom: clamp(40px, 6vw, 66px);
  background: linear-gradient(90deg, transparent, rgba(0,0,0,0.16) 20%, rgba(0,0,0,0.16) 80%, transparent);
}
.signoff__rule .led {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 9px; height: 9px;
}
.signoff__kick {
  font-family: var(--font-label); font-size: 12px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-muted);
  margin-bottom: 22px;
}
.signoff__title {
  font-size: clamp(30px, 5vw, 56px); line-height: 1.04; letter-spacing: -0.025em; max-width: 17ch;
}
.signoff__lede {
  margin-top: 20px; color: var(--ink-muted); font-size: clamp(16px, 1.9vw, 19px); max-width: 46ch;
}
.signoff__contact {
  margin-top: clamp(34px, 4.5vw, 48px);
  display: flex; align-items: center; justify-content: center; gap: 30px; flex-wrap: wrap;
}
.signoff__email {
  font-size: clamp(21px, 2.7vw, 30px); font-weight: 700; letter-spacing: -0.015em; color: var(--ink);
  padding-bottom: 5px; border-bottom: 2px solid rgba(0,0,0,0.18);
  transition: border-color var(--dur) var(--ease);
}
.signoff__email:hover { border-bottom-color: var(--led); }
.signoff__x {
  font-family: var(--font-label); font-size: 14px; font-weight: 600; letter-spacing: 0.03em;
  color: var(--ink-muted); transition: color var(--dur) var(--ease);
}
.signoff__x:hover { color: var(--ink); }
.signoff__foot {
  margin-top: clamp(44px, 6vw, 68px);
  display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.signoff__foot .footer__hand { font-size: 22px; }
.signoff__meta { font-family: var(--font-label); font-size: 12px; letter-spacing: 0.04em; color: var(--ink-faint); }
@media (max-width: 560px) { .signoff__contact { gap: 14px; } }

/* ============================================================
   14. PAGE TRANSITIONS & SHARED PROJECT ARTWORK
   ============================================================ */
/* the arrival settles position only; the page is readable from its
   very first frame even if the animation never gets to run */
.page { animation: page-enter 280ms var(--ease) both; }
@keyframes page-enter { from { transform: translateY(8px); } to { transform: none; } }
.page.is-leaving { animation: page-leave 170ms var(--ease) both; }
@keyframes page-leave { to { opacity: 0; transform: translateY(4px); filter: blur(0.8px); } }

/* Artwork travels in a named snapshot. The arrival-only cover snapshots
   below restore the pocket's occlusion within the transition overlay. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
.nav      { view-transition-name: site-nav; }
.bg-grid  { view-transition-name: site-grid; }
::view-transition-group(*) {
  animation-duration: 440ms;
  animation-timing-function: var(--ease-in-out);
}
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 220ms;
  animation-timing-function: var(--ease-out);
}
/* when the morph carries the entrance, don't double-animate the page */
.vt-in .page { animation: none; }
@media (prefers-reduced-motion: no-preference) {
  .project-folder--weather     .project-folder__hero { view-transition-name: vt-hero-weather; }
  .project-folder--wallet      .project-folder__hero { view-transition-name: vt-hero-wallet; }
  .project-folder--gate        .project-folder__hero { view-transition-name: vt-hero-gate; }
  .project-folder--onboarding  .project-folder__hero { view-transition-name: vt-hero-onboard; }
  .project-folder--foreign     .project-folder__hero { view-transition-name: vt-hero-foreign; }
}
@media (prefers-reduced-motion: no-preference) {
  .project-folder--weather    .project-folder__title { view-transition-name: vt-title-weather; }
  .project-folder--wallet     .project-folder__title { view-transition-name: vt-title-wallet; }
  .project-folder--gate       .project-folder__title { view-transition-name: vt-title-gate; }
  .project-folder--onboarding .project-folder__title { view-transition-name: vt-title-onboard; }
  .project-folder--foreign    .project-folder__title { view-transition-name: vt-title-foreign; }
}
@media (prefers-reduced-motion: no-preference) {
  .project-folder--weather    .project-folder__description { view-transition-name: vt-sub-weather; }
  .project-folder--wallet     .project-folder__description { view-transition-name: vt-sub-wallet; }
  .project-folder--gate       .project-folder__description { view-transition-name: vt-sub-gate; }
  .project-folder--onboarding .project-folder__description { view-transition-name: vt-sub-onboard; }
  .project-folder--foreign    .project-folder__description { view-transition-name: vt-sub-foreign; }
}
::view-transition-group(vt-hero-weather),
::view-transition-group(vt-hero-wallet),
::view-transition-group(vt-hero-gate),
::view-transition-group(vt-hero-onboard),
::view-transition-group(vt-hero-foreign),
::view-transition-group(vt-title-weather),
::view-transition-group(vt-title-wallet),
::view-transition-group(vt-title-gate),
::view-transition-group(vt-title-onboard),
::view-transition-group(vt-title-foreign),
::view-transition-group(vt-sub-weather),
::view-transition-group(vt-sub-wallet),
::view-transition-group(vt-sub-gate),
::view-transition-group(vt-sub-onboard),
::view-transition-group(vt-sub-foreign) {
  animation-duration: 440ms;
  animation-timing-function: var(--ease-drawer);
  z-index: 1;
}
/* Only the incoming landing page names its covers. Keep them fully opaque
   from the first frame: a default fade would expose the phone underneath.
   Their masks, labels and arrows are captured together as one surface. */
@media (prefers-reduced-motion: no-preference) {
  /* Unselected projects stay together in the root image on departure.
     Only the chosen phone, title and subtitle need independent surfaces. */
  .folder-departure .project-folder:not(.is-traveling) :is(.project-folder__hero, .project-folder__title, .project-folder__description) {
    view-transition-name: none;
  }
  .folder-return .project-folder--weather .project-folder__front { view-transition-name: vt-cover-weather; }
  .folder-return .project-folder--wallet .project-folder__front { view-transition-name: vt-cover-wallet; }
  .folder-return .project-folder--gate .project-folder__front { view-transition-name: vt-cover-gate; }
  .folder-return .project-folder--onboarding .project-folder__front { view-transition-name: vt-cover-onboard; }
  .folder-return .project-folder--foreign .project-folder__front { view-transition-name: vt-cover-foreign; }
}
::view-transition-group(vt-cover-weather),
::view-transition-group(vt-cover-wallet),
::view-transition-group(vt-cover-gate),
::view-transition-group(vt-cover-onboard),
::view-transition-group(vt-cover-foreign) {
  z-index: 2;
}
::view-transition-new(vt-cover-weather),
::view-transition-new(vt-cover-wallet),
::view-transition-new(vt-cover-gate),
::view-transition-new(vt-cover-onboard),
::view-transition-new(vt-cover-foreign) {
  animation: none;
  opacity: 1;
  mix-blend-mode: normal;
}
html:active-view-transition .project-folder__media img { filter: none; }
html:active-view-transition .project-folder__stage::after { opacity: 0; }
html:active-view-transition .masthead::before,
html:active-view-transition .case-header::before {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html:active-view-transition,
html:active-view-transition * { scroll-behavior: auto; }

/* reveal on scroll — transform composes with the per-card --tilt so the
   cassettes keep their hand-placed rotation while sliding in.
   Content must be visible by default: the hidden starting state only
   applies once html.js confirms the reveal script is actually running
   (set synchronously at the top of audit-main.js). If that script never
   loads or errors out, .reveal elements simply render in place — never
   a section stuck at opacity:0 with nothing left to trigger it. */
/* Only the offset waits for the observer, never the content: a reveal
   that has not fired yet leaves the card 18px low, still fully opaque,
   so a throttled tab, a missed intersection or a screenshot pass can
   never show an empty band. */
html.js .reveal { transform: translateY(18px) rotate(var(--tilt, 0deg)); transition: transform 650ms var(--ease); }
/* same "html.js" prefix as the hidden state above, purely so this wins
   the specificity match (0,2,1 vs 0,2,1) — .is-in is only ever added by
   the same script anyway, so the guard costs nothing here */
html.js .reveal.is-in { transform: translateY(0) rotate(var(--tilt, 0deg)); }
html.js .project-folder.reveal.is-in {
  transition:
    filter 260ms var(--ease),
    transform 650ms var(--ease);
  transition-delay: 0ms;
}

/* ============================================================
   15a. ABOUT PAGE — "The B-Side" editorial redesign
   ============================================================ */

/* HERO — big name left, circular face right */
.about-hd {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(24px, 5vw, 72px);
  align-items: center;
  padding-block: clamp(48px, 8vw, 96px) clamp(24px, 4vw, 56px);
}
.about-hd__copy .chip { margin-bottom: 20px; }
.about-hd__name {
  display: block;
  font-size: clamp(3rem, 9vw, 7rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 0.9;
  margin: 0 0 22px;
  color: var(--ink);
}
.about-hd__name span { display: block; }
.about-hd__name span:last-child {
  -webkit-text-stroke: 2px var(--ink);
  color: transparent;
}
.about-hd__role {
  font-family: var(--font-label);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.about-hd__face {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
}
.about-hd__circle {
  width: clamp(160px, 22vw, 220px);
  height: clamp(160px, 22vw, 220px);
  border-radius: 50%;
  overflow: hidden;
  background: var(--paper);
  border: 2px solid rgba(0,0,0,0.06);
  box-shadow:
    0 16px 40px rgba(0,0,0,0.14),
    0 4px 10px rgba(0,0,0,0.08),
    inset 0 1px 0 rgba(255,255,255,0.8);
}
.about-hd__circle .avatar { width: 100%; height: 100%; }
.about-hd__note {
  font-family: var(--font-hand); font-style: italic;
  font-size: 15px;
  color: var(--ink-muted);
  margin-top: 12px;
  text-align: center;
  transform: rotate(-1.5deg);
  display: block;
  max-width: 18ch;
  line-height: 1.3;
}

/* Chapter sections */
.about-reel {
  padding-block: clamp(44px, 7vw, 80px);
}
.about-reel__hd {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  margin-bottom: 28px;
}
.about-reel__num {
  font-family: var(--font-label);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border: 1px solid rgba(0,0,0,0.12);
  border-radius: 99px;
  padding: 5px 11px;
  flex-shrink: 0;
  margin-top: 9px;
}
.about-reel__title {
  font-family: var(--font-hand); font-style: italic;
  font-size: clamp(2rem, 5.5vw, 4rem);
  font-weight: 700;
  line-height: 1;
  color: var(--ink);
  transform: rotate(-0.4deg);
}
.about-pullquote {
  margin: 0 0 28px;
  padding: 0;
  font-family: var(--font-hand); font-style: italic;
  font-size: clamp(1.2rem, 3vw, 1.75rem);
  line-height: 1.3;
  color: var(--ink);
  font-weight: 600;
  max-width: 54ch;
  transform: rotate(-0.2deg);
}
.about-reel__body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 4vw, 48px);
}
.about-reel__body p {
  color: var(--ink-muted);
  font-size: clamp(15px, 1.8vw, 17px);
  line-height: 1.72;
  margin-top: 16px;
}
.about-reel__body p:first-child { margin-top: 0; }
.about-reel__body p b { color: var(--ink); font-weight: 600; }

/* "What I believe" — full-bleed dark band */
.about-dark {
  background: linear-gradient(172deg, #1c1a17 0%, #0e0d0b 100%);
  padding-block: clamp(56px, 9vw, 108px);
  margin-block: clamp(0px, 0vw, 0px);
  position: relative;
  overflow: hidden;
}
.about-dark::before {
  content: "";
  position: absolute; inset: 0;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,0.012) 0 1px, transparent 1px 14px),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.012) 0 1px, transparent 1px 14px);
  pointer-events: none;
}
.about-dark__inner { position: relative; z-index: 1; }
.about-dark__label {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 28px;
  font-family: var(--font-label);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--led);
}
.about-dark__quote {
  margin: 0;
  font-family: var(--font-hand); font-style: italic;
  font-size: clamp(1.8rem, 5.5vw, 3.6rem);
  font-weight: 700;
  line-height: 1.08;
  color: #f0ece4;
  max-width: 20ch;
  transform: rotate(-0.3deg);
}
.about-dark__quote em {
  font-style: normal;
  color: var(--led);
}
.about-dark__sub {
  margin-top: 36px;
  max-width: 52ch;
  color: rgba(240,236,228,0.5);
  font-size: clamp(15px, 1.8vw, 17px);
  line-height: 1.72;
}
.about-dark__sub b { color: rgba(240,236,228,0.82); font-weight: 600; }

/* Tracklist — custom timeline with bigger year type */
.about-track {
  margin-top: 4px;
  display: grid;
  gap: 0;
}
.about-track__row {
  display: grid;
  grid-template-columns: 110px 1fr auto;
  gap: 16px;
  align-items: center;
  padding: 12px 0;
}
.about-track__yr {
  font-family: var(--font-label);
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-faint);
  letter-spacing: 0.04em;
}
.about-track__role b { display: block; font-weight: 700; font-size: 16px; }
.about-track__role span { font-size: 13px; color: var(--ink-muted); display: block; margin-top: 2px; }
.about-track__tag {
  font-family: var(--font-label);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--led);
  border: 1px solid var(--led);
  padding: 3px 9px;
  border-radius: 99px;
  white-space: nowrap;
  opacity: 0;
}
.about-track__row:first-child .about-track__tag { opacity: 1; }

/* Off the clock — polaroid wall section */
.about-shots {
  padding-block: clamp(44px, 7vw, 80px);
}
.about-shots__hd {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 4px;
}
.about-shots__title {
  font-family: var(--font-hand); font-style: italic;
  font-size: clamp(2rem, 5.5vw, 4rem);
  font-weight: 700;
  color: var(--ink);
  transform: rotate(-0.5deg);
}
.about-shots__hint {
  font-family: var(--font-hand); font-style: italic;
  font-size: 16px;
  color: var(--ink-faint);
  margin-bottom: 0;
  margin-left: 2px;
}

/* Responsive adjustments for about redesign */
@media (max-width: 680px) {
  .about-hd {
    grid-template-columns: 1fr;
  }
  .about-hd__face {
    order: -1;
    align-items: flex-start;
    flex-direction: row;
    gap: 16px;
  }
  .about-hd__circle {
    width: 80px;
    height: 80px;
    flex-shrink: 0;
  }
  .about-hd__note { margin-top: 0; text-align: left; }
  .about-reel__body { grid-template-columns: 1fr; }
  .about-track__row { grid-template-columns: 90px 1fr; }
  .about-track__tag { display: none; }
}

/* ============================================================
   15b. ABOUT PAGE — Sidebar + Timeline layout
   ============================================================ */

/* ── 2-column: sticky sidebar | scrollable timeline ── */
.about-page__sr-title {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.about-page {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: 0 clamp(36px, 5vw, 64px);
  align-items: start;
  padding-block: clamp(48px, 8vw, 88px) clamp(40px, 6vw, 72px);
  margin-bottom: clamp(40px, 6vw, 64px);
}

/* ── Left sidebar: sticky ── */
.about-sidebar {
  position: sticky;
  /* clears the floating nav: at 88px the top of the portrait sat permanently
     under the masthead's blur band while scrolling, so the sticky element
     read as stuck behind the chrome rather than beneath it */
  top: clamp(96px, 10vw, 116px);
  display: flex;
  flex-direction: column;
  gap: 28px;
  align-self: start;
}

/* ── Identity block: face + name + role ── */
.brief__id {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: flex-start;
}

/* The portrait used to sit in a plain rounded-square tile with a 5px ring
   and a soft shadow blooming evenly on all sides — an icon in a box, and
   the reflex all-round shadow with it. It is a print now, like every other
   photograph on this site: the same instant-film stock as the timeline
   chapters and the wall below, tilted on the same axis. The container
   stopped being decoration and became part of the world. */
.brief__face {
  width: 190px;
  padding: 9px 9px 26px;
  border-radius: 3px;
  background: linear-gradient(177deg, #fffffe 0%, #f6f3ec 70%, #efe9dd 100%);
  /* directional, low-offset, tinted to the surface rather than a black halo */
  box-shadow:
    0 2px 4px rgba(20,16,10,0.10),
    0 10px 22px rgba(20,16,10,0.14),
    inset 0 1px 0 rgba(255,255,255,0.9),
    inset 0 0 0 1px rgba(0,0,0,0.045);
  transform: rotate(-1.6deg);
  flex-shrink: 0;
}
.brief__face .avatar {
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  border: 0;
  border-radius: 2px;
  box-shadow:
    inset 0 0 0 1px rgba(0,0,0,0.10),
    inset 0 3px 10px rgba(0,0,0,0.22);
}

/* One name, set once. The old block stacked a light letterspaced "DERRICK"
   over a heavy "Lionardy" (the standard tracked-out wordmark move) and then
   put the role under it in tracked caps too — three different tracked-caps
   treatments in one 200px column, on a page that already wears that costume
   on every label. Weight and size carry the hierarchy now.
   Note the old first line asked for font-weight 300, which this page never
   loads, so the browser was synthesising it. */
.brief__name {
  margin: 0;
  font-size: clamp(1.32rem, 2vw, 1.6rem);
  font-weight: 700;
  letter-spacing: -0.028em;
  line-height: 1.15;
  color: var(--ink);
}
.brief__role {
  margin: 3px 0 0;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: -0.005em;
  color: var(--ink-muted);
  line-height: 1.45;
}


/* ── Right col: vertical numbered timeline ── */
.about-main {
  display: flex;
  flex-direction: column;
  padding-top: 4px;
}

/* timeline entry: content column + image column */
/* Staggered entrances for the timeline, on the site's existing .reveal
   mechanism: the offset is applied only under `html.js`, so if the script
   never runs the chapters simply render in place rather than staying at
   opacity 0 with nothing left to reveal them. */
html.js .tl-entry.reveal { transition-delay: 0ms; }
html.js .tl-entry.reveal:nth-of-type(2) { transition-delay: 60ms; }
html.js .tl-entry.reveal:nth-of-type(3) { transition-delay: 90ms; }
html.js .tl-entry.reveal:nth-of-type(4) { transition-delay: 120ms; }
html.js .tl-entry.reveal:nth-of-type(5) { transition-delay: 150ms; }

.tl-entry {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 208px;
  gap: 0 28px;
  padding-bottom: 64px;
}
.tl-entry:last-child { padding-bottom: 0; }

/* left: text content */
.tl-content {
  position: relative;
  padding-left: 58px;
}

/* Perforated connector between entries — a generic dashed hairline
   read as a default "timeline rule," so this borrows the site's own
   tape/sprocket vocabulary instead: a column of small punched dots,
   like the perforation strip along a film or tape edge. */
.tl-entry:not(:last-child) .tl-content::after {
  content: '';
  position: absolute;
  left: 15.5px;
  top: 52px;
  bottom: -64px;
  width: 3px;
  background-image: radial-gradient(circle, rgba(0,0,0,0.18) 1.1px, transparent 1.3px);
  background-size: 3px 9px;
  background-repeat: repeat-y;
}

/* Track-number stamp — reuses the exact dark printed-label badge
   from the homepage mixtape shells (.mixtape__sticker::after, the
   "A"/"B" side stamp) instead of a generic handwritten-number
   circle, so the about page's timeline reads as the same object
   language as the work, not a separate template. */
.tl-num {
  position: absolute;
  left: 0;
  top: 10px;
  width: 34px;
  height: 34px;
  border-radius: 6px;
  background: #1d1812;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.14),
    0 1px 2px rgba(0,0,0,0.24),
    0 0 0 5px var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-label);
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: #f1ecdf;
  z-index: 2;
  transform: rotate(-2deg);
  /* Optical, not just mathematical, centring. Flex centres the LINE BOX, and
     lining figures carry no descender, so the descent space in that box left
     the digits sitting ~2px high inside the stamp. Half of this padding is
     what actually moves them. */
  padding-top: 3.5px;
}

/* category label + date */
/* `justify-content: space-between` threw the date to the far right of a
   ~740px column, ~500px from the label it belongs with — two related scraps
   marooned at opposite rims with nothing between them. Proximity is the
   whole signal here, so they sit together, separated by a small mark. */
.tl-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 12px;
  /* a dateline under the headline, not a label announcing it */
  margin-bottom: 14px;
}
/* 9px tracked to 0.22em was below any legible floor and the widest tracking
   on the page. Bigger, calmer, and the date drops the caps entirely so the
   two roles in this row do not wear the identical costume. */
.tl-label {
  font-family: var(--font-label);
  font-size: 13px;
  font-weight: 650;
  color: var(--ink);
}
.tl-date {
  font-size: 12px;
  color: var(--ink-faint);
  letter-spacing: -0.002em;
}


/* entry headline */
.tl-headline {
  font-family: var(--font-screen);
  font-size: clamp(18px, 2vw, 24px);
  font-weight: 700;
  color: var(--ink);
  line-height: 1.15;
  letter-spacing: -0.025em;
  /* the first line centres on the 34px number badge beside it */
  padding-top: 12px;
  margin: 0 0 8px;
}

/* body copy */
.tl-body {
  font-family: var(--font-screen);
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink-muted);
  margin: 0;
}


/* image / visual column */
.tl-visual {
  padding-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}


.tl-polaroid {
  background: #faf9f6;
  padding: 10px 10px 28px;
  border-radius: 3px;
  box-shadow:
    0 2px 4px rgba(0,0,0,0.08),
    0 8px 24px rgba(0,0,0,0.12),
    inset 0 1px 0 rgba(255,255,255,0.9),
    inset 0 0 0 1px rgba(0,0,0,0.04);
  transform: rotate(-1.2deg);
  position: relative;
}

.tl-entry:nth-child(even) .tl-polaroid {
  transform: rotate(1deg);
}

.tl-img {
  width: 100%;
  aspect-ratio: 1/1;
  object-fit: cover;
  border-radius: 2px;
  display: block;
  position: relative;
}

.tl-polaroid::after {
  content: "";
  position: absolute;
  inset: 10px 10px 28px;
  pointer-events: none;
  border-radius: 2px;
  background:
    radial-gradient(126% 120% at 50% 42%, transparent 50%, rgba(0,0,0,0.18) 100%),
    radial-gradient(70% 55% at 80% 6%, rgba(255,238,200,0.22), transparent 62%);
}


/* handwritten annotation beside image */
.tl-note {
  font-family: var(--font-hand); font-style: italic;
  font-size: 13px;
  color: var(--ink-faint);
  display: inline-block;
  transform: rotate(-1deg);
  padding-left: 4px;
  line-height: 1.3;
}

/* ── Right col: Cassette liner-note insert ── */

.cass-panel {
  position: relative;
  border-radius: 5px;
  overflow: hidden;
  background: var(--paper);
  border: 1px solid var(--paper-edge);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.92),
    0 6px 18px rgba(0,0,0,0.10),
    0 2px 5px rgba(0,0,0,0.07);
}

/* Fine paper grain, dithered rather than a flat tint — the cream
   fill on its own read as a solid CSS color block instead of card
   stock. Kept just barely visible per the "you should feel it, not
   see it" rule. */
.cass-panel::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(138,112,78,0.5) 0.55px, transparent 0.6px);
  background-size: 3px 3px;
  opacity: 0.15;
  mix-blend-mode: multiply;
}

/* Amber header — artist credit bar, pure paper language */
.cass-header {
  position: relative;
  z-index: 1;
  /* Was a flat fill of --led, the phosphor amber the site reserves for
     LIGHTS (the recorder's REC lamp, the status dot). Poured across a whole
     band it stopped being a light and became a poster-bright swatch — the
     one saturated colour on the page, belonging to no system. This is the
     tonal form: the label stock's own colour, stepped darker, so the header
     reads as a printed band on the same paper rather than a sticker from
     somewhere else. */
  background: linear-gradient(180deg, #ddd5bd 0%, #d5ccb2 100%);
  box-shadow: inset 0 -1px 0 rgba(110,90,60,0.22);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
}
.cass-header__group {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Side stamp — the exact "A"/"B" printed side-letter box from the
   homepage mixtape shells (.mixtape__sticker::after), reused here
   so the liner note reads as the same object language as the work
   itself, not a separate one-off component. */
.cass-header__stamp {
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  border-radius: 3px;
  background: #1d1812;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14), 0 1px 1px rgba(0,0,0,0.22);
  font-family: var(--font-label);
  font-weight: 800;
  font-size: 9px;
  color: #f1ecdf;
  /* same descent-space correction as .tl-num */
  padding-top: 2px;
}
.cass-header__spec {
  font-family: var(--font-label);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
}
.cass-header__side {
  font-family: var(--font-label);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(24,21,18,0.55);
}

/* Paper body — faint ruled lines behind the tracklist, the same
   "printed on ruled label stock" cue as the mixtape sticker's
   ::before writing lines, so the liner note and the shell it lives
   inside share one material instead of two unrelated surfaces. */
.cass-body {
  position: relative;
  z-index: 1;
  padding: 10px 14px 12px;
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 20px,
    var(--paper-rule) 20px,
    var(--paper-rule) 21px
  );
  background-position: 0 4px;
}

/* Printed tracklist with dot leaders */
.cass-tracks {
  display: flex;
  flex-direction: column;
}
.cass-tracks {
  list-style: none;
  margin: 0;
  padding: 0;
}
.cass-track {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0 6px;
  padding: 9px 0;
  border-bottom: 1px solid var(--paper-rule);
  text-align: left;
  width: 100%;
  border-radius: 2px;
}
.cass-track:last-child { border-bottom: none; }
/* Tonal, not tinted: the old amber wash read as a highlighted table cell.
   A shift in value against the label stock belongs to the paper it sits on. */
.cass-track.is-active { background: rgba(90, 70, 40, 0.07); }

/* Track number — amber pill badge when active */
.cass-track__num {
  font-family: var(--font-label);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
  flex-shrink: 0;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 3px;
  transition: color 120ms, background 120ms;
  margin-bottom: 1px;
}
/* The current role's track number was the last saturated amber left on the
   page. It marks "this one is now", which is a status worth showing — but a
   status reads just as clearly as ink on the label's own stock, and the dark
   stamp matches the A/B side-letter used on every cassette here. */
.cass-track.is-active .cass-track__num {
  background: #1d1812;
  color: #f1ecdf;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14), 0 1px 1px rgba(0,0,0,0.22);
}

/* Track title */
.cass-track__name {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-muted);
  white-space: nowrap;
  flex-shrink: 0;
  font-family: var(--font-screen);
  transition: color 120ms;
  line-height: 1;
  padding-bottom: 1px;
}
.cass-track.is-active .cass-track__name { color: var(--ink); }

/* Dot leader */
.cass-track__dot {
  flex: 1;
  min-width: 10px;
  border-bottom: 1.5px dotted rgba(24,21,18,0.16);
  margin-bottom: 3px;
}

/* Year stamp */
.cass-track__yr {
  font-family: var(--font-label);
  font-size: 10px;
  color: var(--ink-faint);
  flex-shrink: 0;
  line-height: 1;
  padding-bottom: 1px;
  transition: color 120ms;
}
.cass-track.is-active .cass-track__yr { color: var(--ink-muted); }

/* Inline annotation — expands below the track row on hover */
/* This used to animate max-height 0 → 48px on hover, so every row below the
   pointer jumped ~50px down the moment you touched one — the list ran away
   from the cursor as you read down it, and the panel changed height six
   different ways depending on where the mouse was. The line is simply always
   there now, holding its own space, and hover is a quiet tonal lift instead
   of a layout change. Nothing moves, and the information is readable without
   having to hunt for it. (The copy also lost its redundant job title: the row
   already says "Lead UI/UX", so the second line only adds employer and span.) */
.cass-track__sub {
  width: 100%;
  font-family: var(--font-label);
  font-size: 10px;
  line-height: 1.4;
  letter-spacing: 0.01em;
  color: var(--ink-faint);
  padding-left: 34px;
  padding-top: 2px;
  white-space: nowrap;
}
.cass-track.is-active .cass-track__sub { color: var(--ink-muted); }

/* ── Off-the-clock polaroid section ── */
.about-shots {
  padding-bottom: clamp(32px, 5vw, 56px);
}
/* This heading used to be an <h3 class="chip"> holding a glowing LED dot:
   a capsule + a tiny icon + tracked caps, three stock moves stacked into one
   12px element, with a badge lighting up from the inside. It is a heading, so
   it is set as one. */
.about-shots__title {
  font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 700;
  letter-spacing: -0.028em;
  line-height: 1.1;
  color: var(--ink);
  margin: 0;
}
.about-shots__hint {
  font-family: var(--font-hand); font-style: italic;
  font-size: 16px;
  color: var(--ink-muted);
  margin: 8px 0 clamp(24px, 3vw, 36px);
  display: block;
}

/* ── Responsive: stack below 900px ── */
@media (max-width: 900px) {
  .about-page {
    grid-template-columns: minmax(0, 1fr);
    gap: 36px 0;
    padding-block: clamp(36px, 6vw, 56px) clamp(24px, 4vw, 40px);
  }
  .about-sidebar {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 24px;
  }
  /* width only — the portrait is a print with a deep bottom border now, so a
     fixed square height cropped it */
  .brief__face { width: 132px; }
  .cass-panel { max-width: 100%; }
  .tl-entry { grid-template-columns: minmax(0, 1fr); }
  /* These were `display: none` below 900px, which silently dropped all five
     chapter photographs — the childhood sketches, the thesis game, the
     Bridestory screens — on every phone and tablet, leaving the story as
     unbroken text. They stack under their chapter instead, aligned to the
     same left edge as the copy. */
  .tl-visual {
    padding-top: 20px;
    padding-left: 58px;
    max-width: 420px;
  }
  .tl-entry:nth-child(even) .tl-polaroid { transform: rotate(-1deg); }
}
@media (max-width: 620px) {
  .tl-visual { padding-left: 0; max-width: none; }
}

/* ============================================================
   15. RESPONSIVE
   ============================================================ */
@media (max-width: 880px) {
  .hero__grid { grid-template-columns: minmax(0, 1fr); }
  .hero__device { padding-bottom: 40px; margin-top: 8px; }
  .about-grid { grid-template-columns: 1fr; }
  .cs-body { grid-template-columns: 1fr; }
  .cs-toc { display: none; }
  .spec { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .mixtapes { grid-template-columns: 1fr; }
  .mixtapes .mixtape { --tilt: 0deg; }
  .nav { width: 94vw; }
  .nav__brand span.full { display: none; }
  .hero__name { font-size: clamp(36px, 11vw, 54px); }
  .cs-hero h1 { font-size: clamp(28px, 8vw, 40px); }
  .hero__meta { gap: 8px 16px; }
  .about-id { flex-direction: column; align-items: flex-start; }
  .vu { grid-template-columns: 1fr 1fr; }
  .gallery--3, .gallery--5 { grid-template-columns: repeat(2, 1fr); }
}

/* The instant camera is a fixed 375px illustration whose internals (film door,
   eject slot, lens, hanging print, ground shadow) are pinned with absolute px
   offsets tuned to that width. Shrinking it via max-width would misalign those
   parts, so instead scale the whole device as one unit. `zoom` is used (not
   `transform`) because it also collapses the layout box — that removes the
   horizontal overflow / grid blow-out and keeps the float animation working. */
/* Below ~360px the cassette shell is only ~290px wide, so the label band
   above the hub plate is barely 50px tall while the type is already sitting
   on its clamp floors. Trim the label's own metrics there so the tagline
   still clears the hub instead of running under it. */
@media (max-width: 360px) {
  .mixtape__sticker { padding-top: 3px; }
  .mixtape__title { font-size: 17px; margin-top: 2px; }
  .mixtape__sub { font-size: 10.5px; }
}


/* ============================================================
   16. REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
  .mixtape__shell { transform: none !important; }
  .reveal { opacity: 1; transform: none; }
}

/* ============================================================
   17. AWWWARDS-LEVEL CASSETTE POLISH
   ============================================================ */

/* Spotlight — siblings recede while one tape is hovered,
   creating a single point of focus without hiding anything */
@media (hover: hover) {
  /* The deck recedes with the tapes. The selector used to name only
     .mixtape, so hovering a tape dimmed the other four and left the deck
     — now the darkest, heaviest object on the wall — sitting at full
     strength, which broke the focus the effect exists to create. */
  .mixtapes:has(.mixtape:hover) .mixtape:not(:hover),
  .mixtapes:has(.mixtape:hover) .recorder {
    opacity: 0.44;
    filter: brightness(0.74) saturate(0.50);
    transform: translateY(0) rotate(var(--tilt, 0deg)) scale(0.960);
    transition:
      opacity   260ms var(--ease),
      filter    260ms var(--ease),
      transform 280ms var(--ease);
  }
}

/* Deeper entrance — cassettes slide in from 36px below
   with a spring-y cubic for the reveal (was 18px default). Same visible-
   by-default guarantee as the base .reveal rule: only offsets once
   html.js confirms the script that clears it is actually running. */
html.js .mixtapes .reveal {
  transform: translateY(36px) rotate(var(--tilt, 0deg));
  transition:
    transform 820ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
html.js .mixtapes .reveal.is-in {
  transform: translateY(0) rotate(var(--tilt, 0deg));
}

/* Custom cursor label — a pill that follows the mouse
   and surfaces the project title while hovering a tape */
.tape-cursor {
  position: fixed;
  top: 0; left: 0;
  pointer-events: none;
  z-index: 9999;
  padding: 7px 15px 7px 12px;
  border-radius: 100px;
  background: var(--ink);
  color: var(--bg);
  font-family: var(--font-label);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow:
    0 4px 24px rgba(0,0,0,0.34),
    0 1px 6px rgba(0,0,0,0.22),
    inset 0 1px 0 rgba(255,255,255,0.10);
  opacity: 0;
  scale: 0.78;
  will-change: translate;
  transition:
    opacity 160ms var(--ease),
    scale   240ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tape-cursor.is-visible {
  opacity: 1;
  scale: 1;
}

/* Press depth — more tactile feedback on click */
.mixtape:active .mixtape__shell {
  box-shadow:
    0 6px 12px rgba(0,0,0,0.20),
    0 2px 4px rgba(0,0,0,0.16),
    inset 0 1px 0 rgba(255,255,255,0.28),
    inset 0 -2px 14px rgba(0,0,0,0.30),
    inset 0 0 0 1px rgba(0,0,0,0.06) !important;
}
