/* ---- Fonts: PP Kyoto by Pangram Pangram (https://pangrampangram.com/products/kyoto).
   Commercial font: this is the free personal-use trial. Buy a licence that includes web use
   before the site goes public. Headings only now: body text is Hanken Grotesk (Google Fonts, free). ---- */
/* The free trial has four weights (Thin 100, Light 300, Medium 500, Extrabold 800) + italics.
   Other weights in this file snap to the nearest one: 400 -> Medium, 700/900 -> Extrabold. */
@font-face { font-family: "PP Kyoto"; src: url("../fonts/PPKyoto-Thin.otf") format("opentype"); font-weight: 100; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Kyoto"; src: url("../fonts/PPKyoto-ThinItalic.otf") format("opentype"); font-weight: 100; font-style: italic; font-display: swap; }
@font-face { font-family: "PP Kyoto"; src: url("../fonts/PPKyoto-Light.otf") format("opentype"); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Kyoto"; src: url("../fonts/PPKyoto-LightItalic.otf") format("opentype"); font-weight: 300; font-style: italic; font-display: swap; }
@font-face { font-family: "PP Kyoto"; src: url("../fonts/PPKyoto-Medium.otf") format("opentype"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Kyoto"; src: url("../fonts/PPKyoto-MediumItalic.otf") format("opentype"); font-weight: 500; font-style: italic; font-display: swap; }
@font-face { font-family: "PP Kyoto"; src: url("../fonts/PPKyoto-Extrabold.otf") format("opentype"); font-weight: 800; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Kyoto"; src: url("../fonts/PPKyoto-ExtraboldItalic.otf") format("opentype"); font-weight: 800; font-style: italic; font-display: swap; }

/* PP Palma trial: Light 300, Medium 500, Heavy 900 + italics, plus the textured "Fizzy" cut.
   Also a personal-use trial: needs a web licence before going public. */
@font-face { font-family: "PP Palma"; src: url("../fonts/PPPalma-Light.otf") format("opentype"); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Palma"; src: url("../fonts/PPPalma-LightItalic.otf") format("opentype"); font-weight: 300; font-style: italic; font-display: swap; }
@font-face { font-family: "PP Palma"; src: url("../fonts/PPPalma-Medium.otf") format("opentype"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Palma"; src: url("../fonts/PPPalma-MediumItalic.otf") format("opentype"); font-weight: 500; font-style: italic; font-display: swap; }
@font-face { font-family: "PP Palma"; src: url("../fonts/PPPalma-Heavy.otf") format("opentype"); font-weight: 900; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Palma"; src: url("../fonts/PPPalma-HeavyItalic.otf") format("opentype"); font-weight: 900; font-style: italic; font-display: swap; }
@font-face { font-family: "PP Palma Fizzy"; src: url("../fonts/PPPalma-FizzyLight.otf") format("opentype"); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Palma Fizzy"; src: url("../fonts/PPPalma-FizzyLightItalic.otf") format("opentype"); font-weight: 300; font-style: italic; font-display: swap; }
@font-face { font-family: "PP Palma Fizzy"; src: url("../fonts/PPPalma-FizzyMedium.otf") format("opentype"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Palma Fizzy"; src: url("../fonts/PPPalma-FizzyMediumItalic.otf") format("opentype"); font-weight: 500; font-style: italic; font-display: swap; }
@font-face { font-family: "PP Palma Fizzy"; src: url("../fonts/PPPalma-FizzyHeavy.otf") format("opentype"); font-weight: 900; font-style: normal; font-display: swap; }
@font-face { font-family: "PP Palma Fizzy"; src: url("../fonts/PPPalma-FizzyHeavyItalic.otf") format("opentype"); font-weight: 900; font-style: italic; font-display: swap; }

/* ---- Motion tokens: every transition uses these ---- */
:root {
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);        /* entering, settling, hover: starts fast, lands softly */
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);    /* moving across the screen */
  --ease-smooth: cubic-bezier(0.25, 0.1, 0.25, 1);   /* headings rising in: slow and even (linear.app's h1) */
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);     /* sheets and cards sliding out or away (iOS's drawer curve) */
  --ease-pop: cubic-bezier(0.34, 1.56, 0.64, 1);     /* overshoot: little flourishes only */
  --press: 120ms;                                    /* how fast things respond to a press */
  --press-scale: .96;                                /* how far buttons, pills and the x shrink while pressed */
  --press-scale-lg: .985;                            /* cards and big surfaces: big things move less */
}

/* Tap feedback (Emil Kowalski): tappable things shrink a touch while pressed, quickly, and ease back
   out more slowly when let go. Uses `scale` so it stacks with any transform they already have.
   Each one lists `scale .3s var(--ease-out)` in its own transition. */
.logo:active, nav a:active, .paired-link:active, .view-all a:active, .tune-panel button:active {
  scale: var(--press-scale); transition-duration: var(--press);
}

/* ---- Design tokens: change these to restyle the whole site ---- */
:root {
  /* Warm night: the blacks lean brown, the text is your site's off-white */
  --bg: #100d0b;
  --surface: #1a1613;
  --line: #2b2521;
  --text: #f9f8f5;
  --muted: #b3aca4;
  --faint: #6b625b;
  /* Brand colours from jamesrobinsondesign.com */
  --terracotta: #e26f46;
  --blue: #1f4494;
  --blue-light: #7d9be0;  /* the brand blue, lifted so it reads on dark */
  --pink: #fad1d1;
  --yellow: #f3cc46;
  --cream: #f5f3ed;
  --accent: var(--terracotta);
  --quote: var(--text);         /* testimonials: the text colour (was pink / blue) */
  --max-width: 1040px;
  --frame: 16px;          /* the black window frame round the site */
  /* Phones: space taken by the status bar, address bar and rounded screen corners (0 elsewhere).
     The page runs underneath them (viewport-fit=cover), so the frame adds these to stay clear */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --frame-radius: 32px;
  --radius: 24px;
  --sans: "Hanken Grotesk", system-ui, sans-serif;   /* body text: a free stand-in for Graphik (wearecollins.com's) */
  --display: "PP Palma Fizzy", "Hanken Grotesk", system-ui, sans-serif;   /* big headlines; [ typeface ] switches between the trial fonts */
  --mono: "Azeret Mono", Menlo, "SF Mono", Consolas, monospace;
}

/* ---- Light theme, from jamesrobinsondesign.com. Toggle in [ tune ] > theme (js/theme.js) ---- */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f9f8f5;
  --surface: #ffffff;
  --line: #e7e2d9;
  --text: #1d1a17;
  --muted: #5d5751;
  --faint: #9b948c;
  --blue-light: #5b7fcf;
}
:root { color-scheme: dark; }

* { box-sizing: border-box; margin: 0; }
html { text-transform: lowercase; }   /* all text is lower case, no capitals */
html { scroll-behavior: smooth; }
body {
  transition: background-color .5s ease, color .5s ease;
  font-family: var(--sans);
  background: var(--bg);
  color: var(--text);
  font-size: 1rem;   /* 16px */
  line-height: var(--body-leading, 1.3125);   /* 21px */
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
main { max-width: var(--max-width); margin: 0 auto; padding: 0 calc(24px + var(--frame)); }

/* ---- Header ---- */
/* A floating glass pill, the same width as the page content (js/glass.js adds the liquid refraction) */
:root {
  --glass-tint: rgba(14, 18, 30, 0.42);        /* enough tint to keep text readable over bright things */
  --glass-rim: rgba(255, 255, 255, 0.35);      /* bright top edge */
  --glass-edge: rgba(255, 255, 255, 0.12);     /* hairline border */
  --glass-shadow: 0 10px 30px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.3);
}
:root[data-theme="light"] {
  --glass-tint: rgba(255, 255, 255, 0.5);
  --glass-rim: rgba(255, 255, 255, 0.9);
  --glass-edge: rgba(255, 255, 255, 0.55);
  --glass-shadow: 0 10px 30px rgba(31, 68, 148, 0.14), 0 1px 2px rgba(31, 68, 148, 0.12);
}
.site-header {
  position: sticky; top: calc(14px + var(--frame) + var(--safe-t)); z-index: 22;   /* the glass things sit above the birds (20), under the grain (25) */
  width: 457px; max-width: calc(100% - 48px - 2 * var(--frame));   /* centred; the width it had with three nav links (fills the width on phones) */
  margin: calc(14px + var(--frame) + var(--safe-t)) auto 0;
  display: flex; align-items: center; gap: 32px;
  padding: 24px 22px 24px 30px;       /* a chunky pill: ~75px tall */
  border-radius: 999px;
  font-family: var(--mono); font-size: .85rem;
  background: linear-gradient(180deg, var(--glass-tint), transparent 140%), var(--glass-tint);
  border: 1px solid var(--glass-edge);
  box-shadow:
    inset 0 1px 0.5px var(--glass-rim),          /* light catching the top rim */
    inset 0 -1px 1px rgba(0, 0, 0, 0.06),         /* slight shade on the lower rim */
    inset 0 0 18px rgba(255, 255, 255, 0.05),     /* thickness */
    var(--glass-shadow);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
          backdrop-filter: blur(14px) saturate(160%);
  isolation: isolate;
}
/* A soft sheen across the upper half, like light on a curved surface */
.site-header::before {
  content: ""; position: absolute; inset: 1px; border-radius: inherit; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0) 55%);
  opacity: .6;
}
/* Chromium: bend the backdrop at the rim like a lens (the map is generated by js/glass.js) */
html.liquid .site-header {
  -webkit-backdrop-filter: url(#liquid-glass) blur(6px) saturate(160%);
          backdrop-filter: url(#liquid-glass) blur(6px) saturate(160%);
}
.logo { transition: scale .3s var(--ease-out); font-family: var(--sans); font-weight: 900; font-size: 1.5rem; line-height: 1; letter-spacing: -0.03em; color: var(--terracotta); }
nav { display: flex; gap: 24px; margin-left: auto; }
nav a { white-space: nowrap; color: var(--text); opacity: .75; transition: opacity .2s, scale .3s var(--ease-out); padding: 18px 12px; margin: -18px -12px; }   /* a big hit area, same layout */
nav a:hover { opacity: 1; }
[data-flock-count] { display: inline-block; }   /* so it can pop (js/birds.js) */
/* A thin pill round the flock counter (in the starling card), so it reads as a status, not a link */
.flock-count {
  color: var(--accent); font-variant-numeric: tabular-nums; white-space: nowrap;
  min-width: 9ch; text-align: center;    /* room for "20 / 20", so it doesn't change width as you catch birds */
  padding: 7px 14px;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); border-radius: 999px;
}
/* Light/dark switch (js/theme.js): a small glass bead in the header pill, showing the theme you'd switch to */
.theme-toggle {
  position: relative; flex: none; width: 38px; height: 38px; margin: -10px 0; border-radius: 50%;   /* negative margin: keeps the pill its usual height */
  display: grid; place-items: center; color: var(--text);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.02) 70%), var(--glass-tint);
  border: 1px solid var(--glass-edge);
  box-shadow: inset 0 1px 0.5px var(--glass-rim), inset 0 -1px 2px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.18);
  -webkit-backdrop-filter: blur(8px) saturate(160%);
          backdrop-filter: blur(8px) saturate(160%);
  transition: transform .3s var(--ease-out), scale .3s var(--ease-out), box-shadow .2s ease;
}
@media (hover: hover) and (pointer: fine) { .theme-toggle:hover { transform: scale(1.06); } }
.theme-toggle:active { scale: var(--press-scale); transition-duration: var(--press); }   /* quick press, softer release */
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.theme-toggle svg {
  grid-area: 1 / 1; width: 18px; height: 18px;
  fill: currentColor;   /* Phosphor icons (phosphoricons.com): filled shapes, not strokes */
  transition: opacity .25s ease, transform .35s var(--ease-out);
}
.theme-toggle__moon { opacity: 0; transform: rotate(-60deg) scale(.6); }
[data-theme="light"] .theme-toggle__sun { opacity: 0; transform: rotate(60deg) scale(.6); }
[data-theme="light"] .theme-toggle__moon { opacity: 1; transform: none; }
/* The icons (js/theme.js): the one showing the theme you'd switch to sits in the bead; the other waits
   below it, clipped by the bead. Switching, the showing one sets (sinks down, speeding up) over the
   first half of the wash, and the other rises (slowing to a stop) over its last part, finishing as the
   wash does (--wash). Transitions, which html.theme-instant leaves alone. */
[data-theme-toggle] { overflow: hidden; }
[data-theme-toggle] :is(.theme-toggle__sun, .theme-toggle__moon) {
  opacity: 1; transform: none;
  transition: transform calc(var(--wash, 1.6s) * .42) var(--ease-out) calc(var(--wash, 1.6s) * .58);   /* rising */
}
:root:not([data-theme="light"]) [data-theme-toggle] .theme-toggle__moon, [data-theme="light"] [data-theme-toggle] .theme-toggle__sun {
  transform: translateY(190%);   /* fully below the bead (38px, 34px on phones), not peeking up into it */
  transition: transform calc(var(--wash, 1.6s) * .5) cubic-bezier(0.55, 0, 0.75, 0.3);   /* setting */
}

/* Sound on/off (js/sounds.js): the same glass bead, showing a speaker with waves (on) or crossed out (off) */
.sound-toggle__off { opacity: 0; transform: scale(.6); }
.sound-toggle[aria-pressed="false"] .sound-toggle__on { opacity: 0; transform: scale(.6); }
.sound-toggle[aria-pressed="false"] .sound-toggle__off { opacity: 1; transform: none; }
.site-header .sound-toggle { margin-right: -18px; }   /* sits close to the theme button, as a pair */
/* reduced motion: the icons just crossfade (no turning or shrinking), and the bead doesn't grow */
@media (prefers-reduced-motion: reduce) {
  .theme-toggle { transition: box-shadow .2s ease; }
  .theme-toggle svg { transform: none !important; transition: opacity .2s ease !important; animation: none !important; }
  :root:not([data-theme="light"]) [data-theme-toggle] .theme-toggle__moon, [data-theme="light"] [data-theme-toggle] .theme-toggle__sun { opacity: 0; }   /* a crossfade */
}
.flock-total { color: var(--muted); }

/* ---- Type ---- */
.hero { min-height: 88vh; display: flex; flex-direction: column; justify-content: center; align-items: var(--head-items, center); text-align: var(--head-align, center); padding: 80px 0; }
/* Phones: centred on the screen, not in the space under the header: as tall as the visible screen
   (svh: not counting the browser's bars) less the header's space above and the same again below.
   86px = the header's gap from the top (10px) + its height (68px) + the frame (8px) */
@media (max-width: 600px) { .hero { min-height: calc(100svh - 2 * (86px + var(--safe-t))); padding: 40px 0; } }
h1 { font-size: clamp(3rem, 9vw, 6.5rem); font-weight: 900; line-height: 1; letter-spacing: -0.03em; }
h1 .accent { color: var(--terracotta); }
/* The hero: one paragraph, one size (between the old headline and the old intro text) */
h1.intro { font-size: calc(clamp(2.2rem, 5.8vw, 4rem) * var(--head-scale, 1)); font-weight: var(--head-weight, 800); line-height: 1.1; letter-spacing: -0.02em; max-width: 22ch; }
/* "Currently head of design at paired." on its own line, with a small gap above (less than a blank line) */
.intro__now { display: block; margin-top: .35em; }
/* Paired's brand purple (#8c50fb) in the light theme; lifted a little in the dark so it reads on the night sky */
:root { --paired: #a987fd; }
:root[data-theme="light"] { --paired: #8c50fb; }
/* Paired: in its brand purple with a plain underline; its logo mark pops out to the right on hover */
.paired-link {
  position: relative; display: inline-block; white-space: nowrap; transition: scale .3s var(--ease-out); color: var(--paired);
  text-decoration: underline; text-decoration-thickness: 0.07em; text-underline-offset: 0.12em;
}
.paired-link__mark {
  position: absolute; left: calc(100% + 0.5em); top: 0.08em; width: 0.8em; height: auto;   /* level with the word, just past the full stop */
  fill: currentColor; pointer-events: none;
  opacity: 0; transform: translate(-0.4em, 0.3em) scale(0.3) rotate(-25deg); transform-origin: 0% 100%;
  transition: opacity .15s ease, transform .2s var(--ease-out);   /* tucks away quickly */
}
@media (hover: hover) and (pointer: fine) {
  .paired-link:hover .paired-link__mark {
    opacity: 1; transform: rotate(10deg);
    transition: opacity .15s ease, transform .5s var(--ease-pop);   /* pops out with an overshoot */
  }
}
.paired-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 4px; }
@media (prefers-reduced-motion: reduce) {
  .paired-link__mark, .paired-link:hover .paired-link__mark { transform: rotate(10deg); transition: opacity .15s ease; }   /* just fades */
}
/* "positive" and "open-minded" replay their entrance from jamesrobinsondesign.com on hover (js/main.js) */
.word-grow, .word-letters, .word-letters span { display: inline-block; }
.word-grow { transform-origin: 50% 50%; }
.word-letters { white-space: nowrap; }
.lede { margin-top: 24px; font-size: clamp(1.15rem, 2.2vw, 1.5rem); color: var(--muted); max-width: 32ch; }

section { padding: 72px 0 96px; }
.section-label {
  font-family: var(--mono); font-size: .8rem; font-weight: 400;
  text-transform: lowercase; letter-spacing: .04em; color: var(--accent);
  margin-bottom: 32px;
}
.section-label::before { content: "// "; color: var(--faint); }
section p { color: var(--muted); max-width: 60ch; }

/* ---- Work ---- */
/* Just images (each will carry its case study's name), two per row, a little taller than wide; some are
   animations made from the case study's images (images/work/*-card.webp). The links open their case study in
   a sheet (js/sheet.js). Hovering one grows it a touch, as on wearecollins.com (js/main.js) */
.work-lede {   /* "positivity is creative problem solving.", under the "case studies" label */
  max-width: none; margin: -12px 0 40px; text-align: left; text-wrap: balance;
  font-family: var(--display); font-size: calc(clamp(1.4rem, 2.6vw, 1.9rem) * var(--head-scale, 1)); font-weight: var(--head-weight, 800);
  font-style: var(--head-style, normal); line-height: 1.15; letter-spacing: var(--head-tracking, -0.02em); color: var(--text);
}
.work .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.work .card img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; border-radius: var(--radius); }
@media (max-width: 767px) {
  .work .grid { grid-template-columns: 1fr 1fr; gap: 12px; }
  .work .card img { border-radius: 16px; box-shadow: 0 12px 31px rgba(0, 0, 0, .12); }   /* wearecollins.com's shadow on mobile */
}
.card { transition: transform .3s var(--ease-out); }
/* the title and description, over a soft dark fade at the bottom of the image (bottom left), and an
   expand icon (Phosphor arrows-out) bottom right on the ones that open. White whatever the theme,
   since they sit on the image. Phones: just the title, the cards are too small for more */
.work .card { position: relative; display: block; }
.work .card::after {
  content: ""; position: absolute; inset: 45% 0 0; border-radius: 0 0 var(--radius) var(--radius); pointer-events: none;
  background: linear-gradient(to bottom, transparent, rgba(0, 0, 0, .18) 40%, rgba(0, 0, 0, .55));
}
.card__info {
  position: absolute; z-index: 1; left: 24px; right: 64px; bottom: 22px; display: grid; gap: 6px;
  color: #fff; text-shadow: 0 1px 12px rgba(0, 0, 0, .25);
}
.card__title { font-family: var(--display); font-size: calc(clamp(1.1rem, 1.9vw, 1.45rem) * var(--head-scale, 1)); font-weight: var(--head-weight, 700); line-height: 1.15; text-wrap: balance; }
.card__desc { font-size: .85rem; line-height: 1.35; opacity: .85; text-wrap: pretty; max-width: 40ch; }
.card__expand { position: absolute; z-index: 1; right: 22px; bottom: 24px; width: 22px; height: 22px; fill: #fff; opacity: .9; }
/* hovering the card, the icon's four arrows ease out a hair towards their corners (~1px) */
.card__arrow { transition: translate .45s var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .card:hover .card__arrow--ne { translate: 12px -12px; }
  .card:hover .card__arrow--nw { translate: -12px -12px; }
  .card:hover .card__arrow--se { translate: 12px 12px; }
  .card:hover .card__arrow--sw { translate: -12px 12px; }
}
@media (max-width: 767px) {
  .work .card::after { border-radius: 0 0 16px 16px; inset-block-start: 55%; }
  .card__info { left: 12px; right: 36px; bottom: 12px; }
  .card__title { font-size: .82rem; line-height: 1.2; }
  .card__desc { display: none; }
  .card__expand { right: 12px; bottom: 13px; width: 16px; height: 16px; }
}
a.card:active { transform: scale(var(--press-scale-lg)); transition-duration: var(--press); }
/* a phone playing over the card's photo (back-up box: the same video as in its case study, same corners) */
.card__device {
  position: absolute; top: 7%; left: 50%; width: 42%; height: auto; aspect-ratio: 838 / 1720; object-fit: cover;
  border-radius: 17.5% / 8.5%; box-shadow: 0 24px 48px rgba(0, 0, 0, .35);
}

/* "Copy my email" (js/main.js): a button that looks like the links beside it */
.copy-email { font: inherit; text-transform: inherit; background: none; border: 0; border-radius: 0; padding: 0; }
.copy-email:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }


/* ---- Case study pages ---- */
.case-study .hero { min-height: auto; padding: 120px 0 64px; }
.case-study h2 { font-size: 1.4rem; font-weight: 500; margin: 48px 0 12px; }

/* ---- The bird layer sits over everything but never blocks clicks ---- */
canvas.birds { position: fixed; left: 0; top: 0; pointer-events: none; z-index: 20; }   /* sized in px by js/birds.js to the visible window: 100vh is taller than it on phones, which stretched the birds downward */
canvas.birds--page { position: absolute; will-change: transform; }   /* touch screens: in the page, so it scrolls with the text; js/birds.js moves it around the screen */

/* ---- [ tune ] panel (built by js/panel.js) ---- */
.tune-panel {
  position: fixed; right: calc(16px + var(--frame) + var(--safe-r)); bottom: calc(16px + var(--frame) + var(--safe-b)); z-index: 30;
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
  font-family: var(--mono); font-size: .75rem; color: var(--muted);
}
.tune-panel button {
  font: inherit; color: var(--muted); background: var(--surface);
  border: 1px solid var(--line); border-radius: 999px; padding: 6px 14px; cursor: var(--cursor-hand);
  transition: color .2s, border-color .2s, scale .3s var(--ease-out);
}
.tune-panel button:hover, .tune-panel__toggle[aria-expanded="true"] { color: var(--accent); border-color: var(--faint); }
.tune-panel button:focus-visible, .tune-panel input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tune-panel__body {
  order: -1; display: grid; gap: 14px; padding: 14px 16px; width: 290px;
  max-height: calc(100vh - 90px); overflow-y: auto;
  background: color-mix(in srgb, var(--surface) 92%, transparent); backdrop-filter: blur(10px);
  border: 1px solid var(--line); border-radius: var(--radius);
}
.tune-panel__body[hidden] { display: none; }
.tune-panel__sections { display: grid; gap: 14px; }
.tune-panel__section { border: 0; padding: 0; display: grid; gap: 8px; }
.tune-panel__section + .tune-panel__section { padding-top: 12px; border-top: 1px solid var(--line); }
.tune-panel legend { padding: 0; margin-bottom: 8px; color: var(--accent); }
.tune-panel legend::before { content: "// "; color: var(--faint); }
.tune-panel label { display: grid; grid-template-columns: 10ch 1fr 5ch; align-items: center; gap: 10px; }
.tune-panel label.toggle { grid-template-columns: 10ch auto; justify-content: start; }
.tune-panel output { text-align: right; color: var(--text); }
.tune-panel input[type="range"] { width: 100%; accent-color: var(--accent); }
.tune-panel input[type="checkbox"] { accent-color: var(--accent); width: 14px; height: 14px; margin: 0; }
.tune-panel__note { font-size: .7rem; color: var(--faint); }
.tune-panel__reset { justify-self: end; padding: 4px 12px !important; }
.tune-panel__actions { display: flex; justify-content: flex-end; gap: 8px; }
.tune-panel__actions button { padding: 4px 12px; }

/* ---- Film grain (js/grain.js): oversized so it can jitter without showing edges ---- */
.grain {
  position: fixed; inset: -800px; z-index: 25; pointer-events: none;
  background-repeat: repeat; opacity: 0.08;
}

/* Sections fade in as they scroll into view */
.reveal { opacity: 0; transform: translateY(24px); transition: opacity .7s var(--ease-out), transform .7s var(--ease-out); }
.reveal.visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { transform: none; transition: opacity .4s ease; }   /* a gentle fade, no movement */
  html { scroll-behavior: auto; }
}

@media (max-width: 600px) {
  :root { --frame: 8px; --frame-radius: 24px; }
  .site-header { gap: 10px; max-width: calc(100% - 24px - 2 * var(--frame)); top: calc(10px + var(--frame) + var(--safe-t)); margin-top: calc(10px + var(--frame) + var(--safe-t)); padding: 21px 14px 21px 18px; }
  nav { gap: 12px; font-size: .75rem; }   /* "get in touch" has to fit on one line */
  nav a { padding: 18px 7px; margin: -18px -7px; }
  .theme-toggle { width: 34px; height: 34px; margin: -8px 0; }
  .site-header .sound-toggle { margin-right: -4px; }
}

/* Positivity: the explanation, then the principle as big as the hero */
.quotes { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; }
/* each quote is two columns: who said it (name, role, company) on the left, what they said on the right */
.quotes figure { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: 24px; align-items: start; }
.quotes figure figcaption { order: -1; }
@media (max-width: 860px) { .quotes { grid-template-columns: 1fr; } }
@media (max-width: 520px) { .quotes figure { grid-template-columns: 1fr; gap: 0; } .quotes figure figcaption { order: 0; } }
.quotes blockquote p { font-size: calc(1rem * var(--body-scale, 1)); font-weight: var(--body-weight, 500); font-style: var(--body-style, normal); line-height: var(--body-leading, 1.3125); color: var(--quote); max-width: none; }
.quotes blockquote p + p { margin-top: 14px; }
.quotes figcaption { font-family: var(--mono); font-size: .8rem; color: var(--muted); display: grid; gap: 2px; }
@media (max-width: 520px) { .quotes figcaption { margin-top: 20px; } }
.quotes .who { color: var(--text); }   /* the name, then "role • company" under it */

/* ---- Background (js/sky.js), from the Figma frame: sky colour, faint grid, soft colour shapes ---- */
:root { --sky-bg: #0b1220; --grid-v: rgba(200, 220, 255, 0.07); --grid-h: rgba(200, 220, 255, 0.035); }
:root[data-theme="light"] { --sky-bg: #d0eeff; --grid-v: rgba(102, 102, 102, 0.16); --grid-h: rgba(102, 102, 102, 0.075); }
/* The page's own background is black and the sky colour is a fixed layer on top of it: phone
   browsers (iPhone Safari) colour their status and address bars from the page background, so this
   makes them black to match the frame. The layer stops short of those bar areas (0 on desktop). */
html.sky body { background: #000; }
html.sky body::before {
  content: ""; position: fixed; left: 0; right: 0; top: var(--safe-t); bottom: var(--safe-b); z-index: -4;
  background: var(--sky-bg); transition: background-color .5s ease; pointer-events: none;
}
.sky-grid, .sky-shapes { position: fixed; inset: 0; width: 100vw; height: 100vh; pointer-events: none; }
.sky-grid {
  z-index: -3; --grid: 11.3px;
  background-image:
    linear-gradient(to right, var(--grid-v) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-h) 1px, transparent 1px);
  background-size: var(--grid) var(--grid);
  /* like the design, the grid fades in from the left edge and softens toward the right */
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 30%, #000 70%, rgba(0,0,0,.45) 100%);
          mask-image: linear-gradient(to right, transparent 0%, #000 30%, #000 70%, rgba(0,0,0,.45) 100%);
  transition: opacity .6s ease;
}
.sky-shapes { z-index: -2; }   /* fades out with the scroll towards the about section (js/sky.js) */

/* ---- Desktop intro: only the bird is visible until it's collected (js/birds.js) ---- */
.site-header, main, .site-end, .tune-panel, .dial-host { transition: opacity 1.4s ease; }
html:not(.gated) main { transition-delay: .3s; }
/* ...and the hero rises in: all at once, or line by line, word by word or letter by letter
   ([ tune ] > hero reveal, js/theme.js). Each piece (.hero-unit) rises a little and fades in,
   its delay stepping up by --hero-step. `top` rather than transform, so underlines stay drawn. */
.hero .hero-unit {
  position: relative; top: 0; opacity: 1;
  transition: opacity 1s var(--ease-smooth), top 1s var(--ease-smooth);
  transition-delay: calc(.35s + var(--i, 0) * var(--hero-step, 0s));
}
.hero:not(.hero-shown) .hero-unit { opacity: 0; top: .3em; }
/* ...and a small pause before "currently head of design / at paired" (not in "all at once", where
   the heading is one piece) */
.hero .intro__now .hero-unit { transition-delay: calc(.35s + var(--i, 0) * var(--hero-step, 0s) + var(--hero-pause, .22s)); }
.hero.hero-instant .hero-unit { transition: none; }
@media (prefers-reduced-motion: reduce) { .hero:not(.hero-shown) .hero-unit { top: 0; } }
html:not(.gated) .site-end, html:not(.gated) .tune-panel, html:not(.gated) .dial-host { transition-delay: .6s; }
html.gated body { overflow: hidden; }
html.gated .site-header, html.gated main, html.gated .site-end, html.gated .tune-panel, html.gated .dial-host { opacity: 0; visibility: hidden; }
/* the nav drops in from above as the page appears (after the intro on the home page; on load on the
   others), rather than fading in. `backwards` only, so once it's in, the page's own rules (dimming for
   the sheet, hiding for the murmur) still apply to it */
@keyframes nav-drop { from { translate: 0 calc(-100% - 48px); opacity: 0; } }
@keyframes nav-fade { from { opacity: 0; } }
html:not(.gated) .site-header { animation: nav-drop .9s var(--ease-out) .1s backwards; }
@media (prefers-reduced-motion: reduce) { html:not(.gated) .site-header { animation-name: nav-fade; } }
/* The "perch" button in the intro: the same floating glass pill as the nav (js/glass.js adds the refraction) */
.perch-button {
  position: fixed; left: 50%; top: 50%; z-index: 15;   /* under the bird canvas, so the bird can land on it */
  transform: translate(-50%, -50%);
  padding: 26px 58px; border-radius: 999px;
  white-space: nowrap; width: max-content;   /* one line, always: centred with left: 50% it would otherwise wrap on phones */
  font: 500 1rem var(--mono); letter-spacing: .06em; color: var(--text);
  /* clearer glass than the header: a lighter tint, so more of the sky shows through, with a bright rim */
  --perch-tint: color-mix(in srgb, var(--glass-tint) 45%, transparent);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.14), transparent 70%), var(--perch-tint);
  border: 1px solid var(--glass-edge);
  box-shadow: inset 0 1px 0.5px var(--glass-rim), inset 0 -1px 1px rgba(0, 0, 0, 0.05),
              inset 0 0 22px rgba(255, 255, 255, 0.08), var(--glass-shadow);
  -webkit-backdrop-filter: blur(10px) saturate(180%);
          backdrop-filter: blur(10px) saturate(180%);
  transition: transform .35s var(--ease-out), opacity .5s ease;
  animation: perch-in .8s ease .2s backwards;   /* fades in; then js/birds.js writes its words */
}
@keyframes perch-in { from { opacity: 0; } }
@media (hover: hover) and (pointer: fine) { .perch-button:not(:disabled):hover { transform: translate(-50%, -50%) scale(1.04); } }
.perch-button:disabled { cursor: var(--cursor-arrow); }   /* while the bird writes its words, and after it's pressed */
.perch-button:not(:disabled):active { transform: translate(-50%, -50%) scale(var(--press-scale)); transition-duration: var(--press); }
.perch-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.perch-button.chosen { transform: translate(-50%, -50%); cursor: var(--cursor-arrow); }
.perch-button.gone { opacity: 0; transform: translate(-50%, -50%) scale(.96); }
html:not(.gated) .perch-button { pointer-events: none; }

/* ---- Cursor: a classic-Mac-style pixel arrow, and the matching pixel hand on anything clickable ---- */
:root {
  --cursor-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 16 16' shape-rendering='crispEdges'%3E%3Crect x='0' y='0' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='1' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='1' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='2' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='2' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='2' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='3' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='3' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='3' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='3' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='4' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='4' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='4' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='4' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='4' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='5' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='5' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='5' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='5' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='5' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='5' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='6' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='6' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='7' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='7' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='8' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='8' y='8' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='9' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='9' width='1' height='1' fill='%23000'/%3E%3Crect x='6' y='9' width='1' height='1' fill='%23000'/%3E%3Crect x='7' y='9' width='1' height='1' fill='%23000'/%3E%3Crect x='8' y='9' width='1' height='1' fill='%23000'/%3E%3Crect x='9' y='9' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='10' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='10' width='1' height='1' fill='%23000'/%3E%3Crect x='3' y='10' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='10' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='11' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='11' width='1' height='1' fill='%23000'/%3E%3Crect x='3' y='11' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='11' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='12' width='1' height='1' fill='%23000'/%3E%3Crect x='3' y='12' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='12' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='13' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='13' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='14' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='14' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='14' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='14' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='15' width='1' height='1' fill='%23000'/%3E%3Crect x='6' y='15' width='1' height='1' fill='%23000'/%3E%3C/svg%3E") 0 0, auto;   /* classic pixel Mac arrow */
  --cursor-hand: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 16 16' shape-rendering='crispEdges'%3E%3Crect x='5' y='0' width='1' height='1' fill='%23000'/%3E%3Crect x='6' y='0' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='1' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='1' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='1' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='1' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='2' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='2' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='2' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='2' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='3' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='3' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='3' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='3' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='4' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='4' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='4' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='4' width='1' height='1' fill='%23000'/%3E%3Crect x='8' y='4' width='1' height='1' fill='%23000'/%3E%3Crect x='9' y='4' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='5' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='5' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='5' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='5' width='1' height='1' fill='%23000'/%3E%3Crect x='8' y='5' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='5' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='5' width='1' height='1' fill='%23000'/%3E%3Crect x='11' y='5' width='1' height='1' fill='%23000'/%3E%3Crect x='12' y='5' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='6' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='6' width='1' height='1' fill='%23000'/%3E%3Crect x='8' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='6' width='1' height='1' fill='%23000'/%3E%3Crect x='11' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='12' y='6' width='1' height='1' fill='%23fff'/%3E%3Crect x='13' y='6' width='1' height='1' fill='%23000'/%3E%3Crect x='14' y='6' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='7' width='1' height='1' fill='%23000'/%3E%3Crect x='2' y='7' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='7' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='7' width='1' height='1' fill='%23000'/%3E%3Crect x='8' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='7' width='1' height='1' fill='%23000'/%3E%3Crect x='11' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='12' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='13' y='7' width='1' height='1' fill='%23000'/%3E%3Crect x='14' y='7' width='1' height='1' fill='%23fff'/%3E%3Crect x='15' y='7' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='8' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='8' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='8' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='8' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='11' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='12' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='13' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='14' y='8' width='1' height='1' fill='%23fff'/%3E%3Crect x='15' y='8' width='1' height='1' fill='%23000'/%3E%3Crect x='0' y='9' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='2' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='9' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='8' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='11' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='12' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='13' y='9' width='1' height='1' fill='%23fff'/%3E%3Crect x='14' y='9' width='1' height='1' fill='%23000'/%3E%3Crect x='1' y='10' width='1' height='1' fill='%23000'/%3E%3Crect x='2' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='3' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='8' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='11' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='12' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='13' y='10' width='1' height='1' fill='%23fff'/%3E%3Crect x='14' y='10' width='1' height='1' fill='%23000'/%3E%3Crect x='2' y='11' width='1' height='1' fill='%23000'/%3E%3Crect x='3' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='8' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='11' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='12' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='13' y='11' width='1' height='1' fill='%23fff'/%3E%3Crect x='14' y='11' width='1' height='1' fill='%23000'/%3E%3Crect x='2' y='12' width='1' height='1' fill='%23000'/%3E%3Crect x='3' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='4' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='8' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='11' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='12' y='12' width='1' height='1' fill='%23fff'/%3E%3Crect x='13' y='12' width='1' height='1' fill='%23000'/%3E%3Crect x='3' y='13' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='5' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='8' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='11' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='12' y='13' width='1' height='1' fill='%23fff'/%3E%3Crect x='13' y='13' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='14' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='14' width='1' height='1' fill='%23fff'/%3E%3Crect x='6' y='14' width='1' height='1' fill='%23fff'/%3E%3Crect x='7' y='14' width='1' height='1' fill='%23fff'/%3E%3Crect x='8' y='14' width='1' height='1' fill='%23fff'/%3E%3Crect x='9' y='14' width='1' height='1' fill='%23fff'/%3E%3Crect x='10' y='14' width='1' height='1' fill='%23fff'/%3E%3Crect x='11' y='14' width='1' height='1' fill='%23fff'/%3E%3Crect x='12' y='14' width='1' height='1' fill='%23000'/%3E%3Crect x='4' y='15' width='1' height='1' fill='%23000'/%3E%3Crect x='5' y='15' width='1' height='1' fill='%23000'/%3E%3Crect x='6' y='15' width='1' height='1' fill='%23000'/%3E%3Crect x='7' y='15' width='1' height='1' fill='%23000'/%3E%3Crect x='8' y='15' width='1' height='1' fill='%23000'/%3E%3Crect x='9' y='15' width='1' height='1' fill='%23000'/%3E%3Crect x='10' y='15' width='1' height='1' fill='%23000'/%3E%3Crect x='11' y='15' width='1' height='1' fill='%23000'/%3E%3Crect x='12' y='15' width='1' height='1' fill='%23000'/%3E%3C/svg%3E") 7 0, pointer;
}
html, body { cursor: var(--cursor-arrow); }
a[href], button, label, summary, select, input[type="range"], input[type="checkbox"], [role="button"], .card { cursor: var(--cursor-hand); }

/* Big headlines use the display face (the same as --sans unless a typeface option changes it) */
h1, .logo { font-family: var(--display); }
/* [ tune ] > text (js/theme.js) can set these; unset, each heading keeps its own weight */
h1.intro { font-style: var(--head-style, normal); text-wrap: var(--head-wrap, wrap); }
.quotes blockquote p { text-align: var(--body-align, start); text-wrap: var(--body-wrap, wrap); }
.quotes figcaption { justify-items: var(--body-items, start); }

/* ---- Window frame: a black border with rounded corners, fixed to the screen, so the site
   looks like it's seen through a rounded window. It sits over everything but never blocks clicks ---- */
.site-frame {
  position: fixed; z-index: 50; pointer-events: none;
  inset: calc(var(--frame) + var(--safe-t)) calc(var(--frame) + var(--safe-r)) calc(var(--frame) + var(--safe-b)) calc(var(--frame) + var(--safe-l));
  border-radius: var(--frame-radius);
  box-shadow: 0 0 0 100vmax #000;   /* everything outside the rounded rectangle is black */
  transition: inset .9s var(--ease-in-out), border-radius .9s var(--ease-in-out);   /* draws in after "perch", closes in for "your murmur" */
}
/* Solid black strips along the very top and bottom edges (.site-edge, beside .site-frame in each page).
   Phone browsers (iPhone Safari especially) draw the page behind the status bar and a shrunk address
   bar, outside the area the frame's shadow covers; these fill that in. They're real elements, not
   pseudo-elements, because Safari picks its bars' colour from elements pinned to the edges, and only
   when the page loads: so they're there from the start. During the intro they only cover the phone's
   status/address bar areas (nothing on desktop), leaving the sky full bleed, then grow in with the
   frame (same timing: js/birds.js sets both). */
.site-edge {
  position: fixed; left: 0; right: 0; z-index: 50; pointer-events: none; background: #000;
  transition: height .9s var(--ease-in-out);
}
.site-edge--top { top: 0; height: calc(var(--frame) + var(--safe-t)); }
.site-edge--bottom { bottom: 0; height: calc(var(--frame) + var(--safe-b)); }
html.gated:not(.framing) .site-edge--top { height: var(--safe-t); }
html.gated:not(.framing) .site-edge--bottom { height: var(--safe-b); }

/* keep the [ tune ] button (DialKit) inside the frame */
.dial-host .dialkit-panel { right: calc(16px + var(--frame) + var(--safe-r)); bottom: calc(16px + var(--frame) + var(--safe-b)); }

/* Agentation (js/agentation.js, local preview only): its toolbar sits inside the frame, just left of [ tune ] */
agentation-toolbar { right: calc(16px + var(--frame) + var(--safe-r) + 50px) !important; bottom: calc(16px + var(--frame) + var(--safe-b)) !important; }

/* ---- The starling card (js/starling-card.js): a glass card tucked under the frame's right edge.
   It peeks out, comes a little further on hover, and slides fully out when clicked ---- */
.starling-card {
  --peek: 64px;                                   /* how much shows while it's tucked away */
  --gap: 20px;                                    /* space between the card and the frame when it's out */
  position: fixed; top: calc(var(--frame) + 116px); right: calc(var(--frame) + var(--gap)); z-index: 23;   /* glass: above the birds, under the grain and the frame */
  display: grid; justify-items: center; gap: 14px;
  padding: 18px 18px 16px; border-radius: var(--radius);
  font: 500 .8rem/1.45 var(--mono); color: var(--text); text-align: center;
  background: linear-gradient(180deg, var(--glass-tint), transparent 140%), var(--glass-tint);
  border: 1px solid var(--glass-edge);
  box-shadow: inset 0 1px 0.5px var(--glass-rim), inset 0 -1px 1px rgba(0, 0, 0, 0.06),
              inset 0 0 18px rgba(255, 255, 255, 0.05), var(--glass-shadow);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
          backdrop-filter: blur(14px) saturate(160%);
  transform: translateX(calc(100% + var(--gap) - var(--peek))) rotate(-4deg);
  transition: transform .3s var(--ease-out), opacity 1.4s ease, scale .3s var(--ease-out);   /* hover nudge, tucking back */
}
.starling-card::before {   /* the same soft sheen as the header pill */
  content: ""; position: absolute; inset: 1px; border-radius: inherit; pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0) 55%); opacity: .6;
}
@media (hover: hover) and (pointer: fine) {
  .starling-card:hover { --peek: 100px; transform: translateX(calc(100% + var(--gap) - var(--peek))) rotate(-2.5deg); }
}
.starling-card:has(> .starling-card__toggle:active) { scale: var(--press-scale-lg); transition-duration: var(--press); }
.starling-card.waiting { transform: translateX(calc(100% + var(--gap) + 24px)) rotate(8deg); }   /* fully under the frame until it springs in */
.starling-card.entering { transition: transform var(--enter-duration) var(--enter-ease), opacity 1.4s ease, scale .3s var(--ease-out); transition-delay: 0s; }
.starling-card[data-open="true"] { transform: none; transition-duration: .45s; transition-timing-function: var(--ease-drawer); }
.starling-card:has(> .starling-card__toggle:focus-visible) { outline: 2px solid var(--accent); outline-offset: 4px; }
/* An invisible button covering the whole card: tap or click anywhere on it to open or close it */
.starling-card__toggle {
  position: absolute; inset: 0; z-index: 1; border-radius: inherit;
  appearance: none; background: none; border: 0; padding: 0; margin: 0; outline: none;
}
/* "start murmur": on top of that, below the counter, once you've had a murmur and still have the whole flock */
.starling-card__start {
  position: relative; z-index: 2;
  font: 500 .75rem var(--mono); text-transform: inherit; color: #fff;
  background: var(--accent); border: 0; border-radius: 999px; padding: 8px 16px;
  opacity: 0; transition: opacity .2s ease, scale .3s var(--ease-out);
}
.starling-card__start[hidden] { display: none; }
.starling-card[data-open="true"] .starling-card__start { opacity: 1; transition: opacity .5s ease .5s, scale .3s var(--ease-out); }
.starling-card__start:active { scale: var(--press-scale); transition-duration: var(--press); }
.starling-card__start:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.starling-card__bird { display: block; width: 200px; height: auto; }
.starling-card__text {
  max-width: 200px; opacity: 0; transform: translateY(6px);
  transition: opacity .2s ease, transform .2s var(--ease-out);   /* leaves quickly... */
}
.starling-card .flock-count { font-size: .75rem; opacity: 0; transition: opacity .2s ease; }
.starling-card[data-open="true"] .flock-count { opacity: 1; transition: opacity .5s ease .4s; }   /* after the words */
/* While it's tucked away: a small count in the corner of the strip that peeks out */
.starling-card__mini {
  position: absolute; left: 14px; bottom: 14px;
  font-size: .7rem; color: var(--accent); font-variant-numeric: tabular-nums;
  transition: opacity .3s ease .2s;
}
.starling-card__mini [data-flock-count] { display: inline-block; }
.starling-card[data-open="true"] .starling-card__mini { opacity: 0; transition-delay: 0s; }
.starling-card[data-open="true"] .starling-card__text {
  opacity: 1; transform: none;
  transition-duration: .5s; transition-delay: .3s;               /* ...arrives once the card is out */
}
html.gated .starling-card { opacity: 0; visibility: hidden; }
html:not(.gated) .starling-card { transition-delay: 0s, .6s, 0s; }
@media (max-width: 600px) {
  .starling-card { --peek: 48px; --gap: 12px; padding: 14px 14px 12px; top: calc(var(--frame) + 100px); }
  .starling-card__bird { width: 140px; }
  .starling-card__text { max-width: 140px; }
}
/* reduced motion: gentler, not gone: it still fades, but moves in and out at once */
@media (prefers-reduced-motion: reduce) {
  .starling-card, .starling-card__text { transition-property: opacity !important; transition-duration: .2s !important; transition-timing-function: ease !important; transition-delay: 0s !important; }
  .starling-card__text { transform: none; }
}

/* ---- Glass close button (.glass-close): the round frosted x from "your murmur", for anywhere that
   needs one. Where it sits, and any fade, belong to the place using it (.murmur__close, .sheet__close):
   <button type="button" class="glass-close" aria-label="Close"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg></button> ---- */
.glass-close {
  width: 44px; height: 44px; border-radius: 50%; padding: 0;
  display: grid; place-items: center; color: var(--text);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.02) 70%), var(--glass-tint);
  border: 1px solid var(--glass-edge);
  box-shadow: inset 0 1px 0.5px var(--glass-rim), inset 0 -1px 2px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.18);
  -webkit-backdrop-filter: blur(8px) saturate(160%); backdrop-filter: blur(8px) saturate(160%);
  transition: scale .3s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .glass-close:hover { scale: 1.06; } }
.glass-close:active { scale: var(--press-scale); transition-duration: var(--press); }
.glass-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.glass-close svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

/* ---- "Your murmur" (js/murmur.js): catch every bird and the frame closes in to a smaller window
   where your flock grows into a murmuration ---- */
:root { --murmur-y: max(var(--frame), 14vh); --murmur-x: max(var(--frame), 16vw); }
@media (max-width: 600px) { :root { --murmur-y: max(var(--frame), 15vh); --murmur-x: max(var(--frame), 5vw); } }
html.murmuring .site-frame { inset: var(--murmur-y) var(--murmur-x); }
/* The intro has no frame (the sky runs to the edges); pressing "perch" draws it in (js/birds.js adds .framing) */
html.gated:not(.framing) .site-frame { inset: 0; border-radius: 0; }
html.murmuring body { overflow: hidden; }
html.murmuring .dial-host, html.murmuring agentation-toolbar { opacity: 0; visibility: hidden; }
/* The page's content fades out (the sky stays), leaving just the murmur */
html.murmuring :is(.site-header, main, .site-end, .starling-card) { opacity: 0; pointer-events: none; transition: opacity .6s ease; }   /* (the bird canvas stays: your flock keeps following you) */
.murmur { position: fixed; inset: 0; z-index: 49; opacity: 0; transition: opacity .5s ease; }   /* just under the frame */
.murmur[hidden] { display: none; }
html.murmuring .murmur { opacity: 1; transition: opacity .7s ease .2s; }
.murmur__window {
  position: absolute; inset: var(--murmur-y) var(--murmur-x); overflow: hidden; border-radius: var(--frame-radius);
  /* see-through: the page's own sky (colour, grid, glowing shapes) carries on behind the murmur */
}
.murmur__sky { position: absolute; inset: 0; width: 100%; height: 100%; }
.murmur__head {
  position: absolute; left: 0; right: 0; top: 28px; padding: 0 72px; text-align: center; pointer-events: none;   /* side padding keeps it clear of the x */
  font-family: var(--mono); color: var(--muted);
  opacity: 0; transform: translateY(10px); transition: opacity .3s ease, transform .3s var(--ease-out);
}
html.murmuring .murmur__head { opacity: 1; transform: none; transition: opacity 1s ease 1.6s, transform 1s var(--ease-out) 1.6s; }
.murmur__title { font: italic 500 clamp(1.05rem, 2.2vw, 1.4rem) / 1.2 var(--mono); letter-spacing: .02em; color: var(--text); }
/* a dictionary entry: the word, how to say it, and what it means */
.murmur__word { margin-top: 12px; font-size: .75rem; color: var(--text); }
.murmur__word i { margin-left: .5em; }
.murmur__word i, .murmur__def i { color: var(--faint); }
.murmur__def { margin: 4px auto 0; max-width: 46ch; font-size: .75rem; line-height: 1.55; }
.murmur__def b { font-weight: 500; color: var(--text); }
.murmur__close {   /* a .glass-close */
  position: absolute; top: 18px; right: 18px;
  opacity: 0; transition: opacity .3s ease, scale .3s var(--ease-out);
}
html.murmuring .murmur__close { opacity: 1; transition: opacity .6s ease 1s, scale .3s var(--ease-out); }
.murmur__sound { position: absolute; top: 21px; right: 72px; margin: 0; }   /* beside the x */
@media (max-width: 600px) { .murmur__head { top: 76px; padding: 0 20px; } }   /* narrow: under the sound button and the x, not between them */
/* reduced motion: the frame closes in and opens out at once; the murmur's words and x still fade */
@media (prefers-reduced-motion: reduce) {
  .site-frame { transition: none !important; }
  .murmur, .murmur__head, .murmur__close { transition-property: opacity !important; transition-duration: .2s !important; transition-timing-function: ease !important; transition-delay: 0s !important; }
}

/* Touch screens: no collecting birds (js/birds.js), so no flock counter or starling card */
@media (hover: none) and (pointer: coarse) {
  .flock-count, .starling-card { display: none; }
}

/* ==================================================================================================
   Inner pages: work (/work-all/), about, contact and the case studies (/work/<slug>/).
   Content copied from jamesrobinsondesign.com; built from the blocks below. Every page has
   <html data-page="..." data-birds="ambient">. The [ tune ] controls for these live in js/controls.js:
   sliders set the custom properties in the :root block below, menus set data-* on <html>.
   ================================================================================================== */
:root {
  --olive: #aab374;               /* from the old site's about page, lifted for the dark theme */
  --read-width: 680px;            /* the text column */
  --section-gap: 128px;           /* space between sections */
  --para-gap: 1em;
  --body-leading: 1.3125;         /* 21px at 16px */
  --img-radius: var(--radius);
  --img-gap: 24px;
  --label-size: .8rem;
  --label-font: var(--mono);
  --label-prefix: "";   /* [ tune ] > labels > show // puts "// " back */
  --label-color: var(--accent);
  --caption-size: .8rem;
  --surface-pad: 28px;
  --surface-radius: var(--radius);
}
:root[data-theme="light"] { --olive: #6e7547; }
/* [ tune ] > type details > case: all lower case (as designed) or as written */
:root[data-case="as written"] { text-transform: none; }
/* [ tune ] > type details > heading tracking (each heading keeps its own spacing until it's set) */
h1.intro { letter-spacing: var(--head-tracking, -0.02em); }
/* [ tune ] > labels: every small "// label", the homepage's too */
.section-label { font-family: var(--label-font); font-size: var(--label-size); color: var(--label-color); }
.section-label::before { content: var(--label-prefix); }
/* The page you're on, in the header */
nav a[aria-current="page"] { opacity: 1; color: var(--accent); }

/* ---- The page title: the home hero's reveal, sized for a title ---- */
.page .hero.page-hero { min-height: auto; padding: clamp(96px, 16vh, 168px) 0 0; }
.page-hero h1 {
  font-size: calc(clamp(2.4rem, 6vw, 4.4rem) * var(--head-scale, 1)); font-weight: var(--head-weight, 800);
  font-style: var(--head-style, normal); text-wrap: var(--head-wrap, balance);
  line-height: 1.05; letter-spacing: var(--head-tracking, -0.025em); max-width: 18ch;
}
.page-hero .lede {
  margin-top: 24px; max-width: 36ch; color: var(--muted);
  font-size: calc(clamp(1.1rem, 2vw, 1.4rem) * var(--body-scale, 1)); font-weight: var(--body-weight, 400);
  font-style: var(--body-style, normal); text-wrap: var(--body-wrap, pretty); line-height: 1.45;
}

/* ---- Year / Role / Company ([ tune ] > case study > meta: row, pills or stacked) ---- */
.meta { display: flex; flex-wrap: wrap; justify-content: var(--head-items, center); gap: 16px 48px; margin-top: 40px; }
.meta > div { display: grid; gap: 2px; text-align: start; }
.meta dt { font-family: var(--label-font); font-size: var(--label-size); color: var(--faint); }
.meta dd { margin: 0; font-family: var(--display); font-size: calc(1.35rem * var(--head-scale, 1)); font-weight: var(--head-weight, 700); line-height: 1.2; color: var(--text); }
[data-meta="pills"] .meta { gap: 10px; }
[data-meta="pills"] .meta > div {
  display: flex; align-items: baseline; gap: 10px; padding: 10px 18px; border-radius: 999px;
  background: var(--glass-tint); border: 1px solid var(--glass-edge); box-shadow: inset 0 1px 0.5px var(--glass-rim);
  -webkit-backdrop-filter: blur(10px) saturate(160%); backdrop-filter: blur(10px) saturate(160%);
}
[data-meta="pills"] .meta dd { font-size: 1rem; }
[data-meta="stacked"] .meta { flex-direction: column; align-items: var(--head-items, center); gap: 14px; }
[data-meta="stacked"] .meta > div { text-align: var(--head-align, center); }

/* ---- Sections and the text column ---- */
.page > section:not(.hero) { padding: 0; margin-top: var(--section-gap); }
.page-hero + .media { margin-top: calc(var(--section-gap) * .5); }
.flow { max-width: var(--read-width); margin-inline: auto; text-align: var(--flow-text, start); }
[data-flow="left"] .flow { margin-left: 0; }
.flow h2 {
  font-family: var(--display); font-size: calc(clamp(1.8rem, 3.6vw, 2.6rem) * var(--head-scale, 1));
  font-weight: var(--head-weight, 800); font-style: var(--head-style, normal); text-wrap: var(--head-wrap, balance);
  line-height: 1.1; letter-spacing: var(--head-tracking, -0.02em); color: var(--text); margin-bottom: .55em;
}
.flow .section-label { margin-bottom: 6px; }
.flow .section-label + h2 { margin-top: 0; }   /* the label sits just above its heading (h2s otherwise have 48px above) */
.flow p, .flow li {
  color: var(--muted); max-width: none;
  font-size: calc(1rem * var(--body-scale, 1)); font-weight: var(--body-weight, 400); font-style: var(--body-style, normal);
  line-height: var(--body-leading); text-wrap: var(--body-wrap, pretty);
}
.flow p + p { margin-top: var(--para-gap); }
.flow .note { color: var(--text); }   /* a line that stands out: "Problem: ..." */
.flow em { font-style: italic; }

/* ---- Images and video ([ tune ] > images) ---- */
.media { margin-top: calc(var(--section-gap) * .4); }
.media img, .media video { display: block; width: 100%; height: auto; border-radius: var(--img-radius); }
.media figcaption, .media .caption {
  margin-top: 12px; font-family: var(--caption-font, var(--mono)); font-size: var(--caption-size);
  color: var(--muted); text-wrap: pretty;
}
.media--pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--img-gap); align-items: start; }
.media--narrow { max-width: 580px; margin-inline: auto; }
.media--tall { max-width: 680px; margin-inline: auto; }
.media--square img { aspect-ratio: 1; object-fit: cover; }
/* cropped to the same frames as the old site */
.media--crop img { aspect-ratio: 1080 / 572; object-fit: cover; }
.media--pair-crop img { aspect-ratio: 525 / 571; object-fit: cover; }
.media--crop-finale img { aspect-ratio: 1080 / 784; object-fit: cover; }
.media--grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--img-gap); }
.media--grid img { aspect-ratio: 528 / 539; object-fit: cover; }
/* width: the text column, the page (as designed) or nearly the whole window */
[data-media="column"] .media { max-width: var(--read-width); margin-inline: auto; }
[data-media="full"] .media:not(.media--narrow):not(.media--tall) {
  width: min(calc(100vw - 2 * var(--frame) - 48px), 1600px); position: relative; left: 50%; translate: -50%;
}
/* a phone (gif or video) standing in front of a photo, as on the old site */
.media--device { position: relative; margin-bottom: 8%; }
.media--device > img { aspect-ratio: 1080 / 573; object-fit: cover; }
.media--device .device {
  position: absolute; left: var(--x); top: 9%; width: 26.2%; height: auto; aspect-ratio: 600 / 1215; object-fit: cover;
  border-radius: 21% / 10.4% !important; padding: 0 !important; border: 0 !important; background: none !important;
  box-shadow: 0 24px 48px rgba(0, 0, 0, .35) !important;
}
/* the corners match each phone's own (measured from the files), so no background shows past them */
.media--device video.device { aspect-ratio: 838 / 1720; border-radius: 17.5% / 8.5% !important; }
/* border or shadow round every image */
[data-img-style="line"] .media img, [data-img-style="line"] .media video { border: 1px solid var(--line); }
[data-img-style="shadow"] .media img, [data-img-style="shadow"] .media video { box-shadow: 0 18px 44px rgba(0, 0, 0, .28), 0 2px 6px rgba(0, 0, 0, .18); }
[data-img-style="glass"] .media img, [data-img-style="glass"] .media video {
  padding: 8px; background: var(--glass-tint); border: 1px solid var(--glass-edge); box-shadow: inset 0 1px 0.5px var(--glass-rim), var(--glass-shadow);
  border-radius: calc(var(--img-radius) + 8px);
}

/* ---- Surfaces: stats, reviews, the now playing card ([ tune ] > surfaces) ---- */
.surface { padding: var(--surface-pad); border-radius: var(--surface-radius); }
[data-surface="glass"] .surface {
  background: linear-gradient(180deg, var(--glass-tint), transparent 140%), var(--glass-tint);
  border: 1px solid var(--glass-edge); box-shadow: inset 0 1px 0.5px var(--glass-rim), var(--glass-shadow);
  -webkit-backdrop-filter: blur(14px) saturate(160%); backdrop-filter: blur(14px) saturate(160%);
}
[data-surface="solid"] .surface { background: var(--surface); }   /* plain rounded boxes */
[data-surface="line"] .surface { border: 1px solid var(--line); }
[data-surface="none"] .surface { padding: 0; }

.stats .stat { margin: 0; }   /* they're paragraphs: no paragraph gap */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; margin-block: 36px; }
.stat b { display: block; font-family: var(--display); font-weight: var(--head-weight, 800); font-size: calc(clamp(2.2rem, 4.4vw, 3rem) * var(--head-scale, 1)); line-height: 1; color: var(--accent); }
.flow .stat span { display: block; margin-top: 10px; font-size: calc(1rem * var(--body-scale, 1)); color: var(--muted); }

.stats .stat {
  box-shadow: 0 9px 9px rgba(0, 0, 0, .04), 0 2px 5px rgba(0, 0, 0, .05);
  transition: transform .45s var(--ease-out), box-shadow .45s var(--ease-out);
}
/* hovered, a stat grows a touch and the others ease 8px away (pushHover in main.js), and its shadow deepens */
.stats .push-lead { box-shadow: 0 21px 13px rgba(0, 0, 0, .06), 0 9px 9px rgba(0, 0, 0, .08), 0 2px 5px rgba(0, 0, 0, .08); }

/* reviews: no boxes, just the quotes, lined up with the text column */
.reviews { display: grid; gap: 32px; margin-top: 8px; }
.review { margin: 0; }
.review blockquote p { color: var(--text); }
.review figcaption { margin-top: 12px; font-family: var(--mono); font-size: .8rem; color: var(--muted); display: grid; gap: 2px; }

/* ---- Split bar chart (Back-up box's impact): who chose the boxes we sent, before and after. Built in
   HTML so it follows the theme. Each segment's --share is its percentage. The bars fill in from the
   left as the chart rises into view; hovering (or tapping) a segment picks out that kind in both bars,
   so you can see "chosen by us" shrink as back-up boxes take its place. ---- */
.split-chart {
  --chart-backup: #48a864; --chart-user: color-mix(in srgb, #48a864 45%, var(--bg)); --chart-us: color-mix(in srgb, var(--text) 22%, var(--bg));
  max-width: var(--read-width); margin: calc(var(--section-gap) * .4) auto 0; display: grid; gap: 48px;
}
.split-chart__title { font-family: var(--display); font-size: calc(1.35rem * var(--head-scale, 1)); font-weight: var(--head-weight, 700); line-height: 1.2; color: var(--text); margin-bottom: 20px; }
.split-chart__bar { display: flex; gap: 6px; }
.split-chart__seg { flex: var(--share) 1 0%; min-width: 0; display: flex; flex-direction: column; gap: 12px; outline: none; }
.split-chart__seg::after {   /* the bar itself */
  content: ""; order: 2; margin-top: auto; height: clamp(36px, 6vw, 52px); border-radius: 12px; background: var(--chart-us);
  transform-origin: left; transition: transform .9s var(--ease-out), opacity .3s ease;
}
.split-chart__seg[data-kind="user"]::after { background: var(--chart-user); }
.split-chart__seg[data-kind="backup"]::after { background: var(--chart-backup); }
.split-chart__label { order: 1; font-size: .9rem; line-height: 1.25; color: var(--muted); transition: opacity .3s ease; }
.split-chart__label b { display: block; font-family: var(--display); font-weight: var(--head-weight, 700); font-size: calc(clamp(1.3rem, 3vw, 1.7rem) * var(--head-scale, 1)); line-height: 1.1; color: var(--text); }
.split-chart__seg[data-kind="backup"] .split-chart__label b { color: var(--chart-backup); }
.split-chart__seg[data-kind="backup"] .split-chart__label b::after { content: " ✹"; font-size: .6em; vertical-align: .5em; }
.split-chart__note { order: 1; margin-top: -6px; font-family: var(--mono); font-size: .72rem; color: var(--muted); }
.split-chart__note::before { content: "↑ "; }
/* filling in: each bar's segments one after another, as the chart rises in (riseIn in main.js) */
.split-chart.rise-wait .split-chart__seg::after { transform: scaleX(0); }
.split-chart__seg:nth-child(2)::after { transition-delay: .12s, 0s; }
.split-chart__seg:nth-child(3)::after { transition-delay: .24s, 0s; }
.split-chart__row:nth-child(2) .split-chart__seg::after { transition-delay: .3s, 0s; }
.split-chart__row:nth-child(2) .split-chart__seg:nth-child(2)::after { transition-delay: .42s, 0s; }
.split-chart__row:nth-child(2) .split-chart__seg:nth-child(3)::after { transition-delay: .54s, 0s; }
/* picking one out: the other kinds fade back */
.split-chart:has([data-kind="us"]:is(:hover, :focus-visible)) .split-chart__seg:not([data-kind="us"]) > *,
.split-chart:has([data-kind="user"]:is(:hover, :focus-visible)) .split-chart__seg:not([data-kind="user"]) > *,
.split-chart:has([data-kind="backup"]:is(:hover, :focus-visible)) .split-chart__seg:not([data-kind="backup"]) > * { opacity: .3; }
.split-chart:has([data-kind="us"]:is(:hover, :focus-visible)) .split-chart__seg:not([data-kind="us"])::after,
.split-chart:has([data-kind="user"]:is(:hover, :focus-visible)) .split-chart__seg:not([data-kind="user"])::after,
.split-chart:has([data-kind="backup"]:is(:hover, :focus-visible)) .split-chart__seg:not([data-kind="backup"])::after { opacity: .3; }
@media (prefers-reduced-motion: reduce) { .split-chart.rise-wait .split-chart__seg::after { transform: none; } }
@media (max-width: 520px) {
  .split-chart__label { font-size: .75rem; }
  .split-chart__bar { gap: 4px; }
}

/* ---- Pull quote ([ tune ] > case study > quote: band, boxed or plain) ---- */
.pull-quote { margin-inline: auto; text-align: center; }
.pull-quote p {
  font-family: var(--display); font-size: calc(clamp(2rem, 5.4vw, 4.2rem) * var(--head-scale, 1));
  font-weight: var(--head-weight, 900); font-style: var(--head-style, normal); line-height: 1.05;
  letter-spacing: var(--head-tracking, -0.03em); text-wrap: balance; max-width: 16ch; margin-inline: auto;
  color: inherit;
}
.pull-quote p + p { margin-top: .5em; }   /* All Dressed Up's two lines */
[data-quote="band"] .page .pull-quote { padding: clamp(64px, 12vw, 140px) clamp(24px, 6vw, 72px); border-radius: var(--radius); background: var(--terracotta); color: #fff; }
[data-quote="boxed"] .page .pull-quote { padding: clamp(48px, 8vw, 96px) clamp(24px, 6vw, 72px); }
[data-quote="plain"] .pull-quote p { color: var(--accent); }

/* ---- About ---- */
.about-photos { margin-top: calc(var(--section-gap) * .4); }
.about-photos img { aspect-ratio: 395 / 292; object-fit: cover; }
/* The photos in a pile (js/main.js, photoPile): stacked in one spot, each a little turned and offset so
   you can see there's more than one. Drag or swipe the top one in any direction and it follows, flies
   out a bit further when you let go, then tucks in behind the others (a click, or Enter, sends it off
   to the side). The pile catches every touch (to drag any way), so on phones it's narrower than the
   screen, leaving room either side to scroll past. */
.photo-pile { display: grid; width: min(364px, 55%); margin-inline: auto; touch-action: none; cursor: grab; }
.photo-pile:active { cursor: grabbing; }
.photo-pile:focus-visible { outline: 2px solid var(--accent); outline-offset: 12px; border-radius: var(--img-radius); }
.photo-pile figure {
  grid-area: 1 / 1; margin: 0;
  transform: translate(var(--pile-x, 0), var(--pile-y, 0)) rotate(var(--pile-r, 0deg));
  filter: brightness(var(--pile-dim, 1));   /* the ones behind a touch darker (js/main.js) */
  transition: transform .5s var(--ease-out), filter .5s ease;
}
.photo-pile img { box-shadow: 0 10px 30px rgba(0, 0, 0, .18), 0 2px 6px rgba(0, 0, 0, .12); user-select: none; -webkit-user-drag: none; -webkit-touch-callout: none; }
/* each heading in its own brand colour, as on the old site; or all accent, or all text ([ tune ] > about) */
.about-block h2 { color: var(--tone, var(--accent)); }
[data-tone="accent"] .about-block h2 { color: var(--accent); }
[data-tone="text"] .about-block h2 { color: var(--text); }
.about-block h2 .sym { display: inline-block; margin-right: .2em; }
.page .about-block + .about-block { margin-top: calc(var(--section-gap) * .6); }
/* lists: plain lines (as designed), bullets, pills or two columns */
.about-list { list-style: none; padding: 0; display: grid; gap: .35em; }
[data-lists="bullets"] .about-list li { padding-left: 1.2em; position: relative; }
[data-lists="bullets"] .about-list li::before { content: "✹"; position: absolute; left: 0; color: var(--tone, var(--accent)); font-size: .8em; top: .2em; }
[data-lists="pills"] .about-list { display: flex; flex-wrap: wrap; gap: 10px; }
[data-lists="pills"] .about-list li {
  padding: 8px 16px; border-radius: 999px; color: var(--text);
  background: var(--glass-tint); border: 1px solid var(--glass-edge); box-shadow: inset 0 1px 0.5px var(--glass-rim);
  -webkit-backdrop-filter: blur(10px) saturate(160%); backdrop-filter: blur(10px) saturate(160%);
}
[data-lists="columns"] .about-list { grid-template-columns: 1fr 1fr; gap: .35em 32px; }
/* the bookshelf: the title on the left, who wrote it flush right, and a thin line joining them across
   the gap between, all in mono. A long title wraps, and the line stays level with its first line.
   "(currently reading)" sits under its title. */
.bookshelf { list-style: none; padding: 0; display: grid; gap: 16px; font-family: var(--mono); font-size: .8rem; line-height: 1.5; }
.bookshelf li { display: grid; grid-template-columns: fit-content(70%) minmax(32px, 1fr) fit-content(38%); column-gap: 12px; align-items: start; }
.bookshelf .book-title { color: var(--text); }
.bookshelf .book-sep {   /* the joining line (its " - " text hidden) */
  height: 1px; margin-top: .6rem;   /* half a line down (.8rem × 1.5), in rem since its font size is 0 */
  background: color-mix(in srgb, var(--muted) 35%, transparent); font-size: 0; overflow: hidden;
}
.bookshelf .book-author { text-align: right; color: var(--muted); }
.bookshelf li > em { grid-column: 1; margin-top: 2px; font-style: normal; color: var(--accent); }

.back-link { margin-top: calc(var(--section-gap) * .6); text-align: center; }

@media (max-width: 700px) {
  .media--pair, .media--grid, [data-lists="columns"] .about-list { grid-template-columns: 1fr; }
  :root { --section-gap: 88px; }
}

/* ---- Grow and push: hover an image or a work card and it grows while its neighbours ease away
   from it (like the hero carousel on wearecollins.com, but more so). js/main.js marks the groups
   (.push-group) and sets --push-scale on the one you're over and --push-x/-y on the others; mouse
   devices only. `transform`, so the about page's scattered photos keep their `translate`/`rotate`. ---- */
.push-group > * {
  transform: translate(var(--push-x, 0px), var(--push-y, 0px)) scale(var(--push-scale, 1));
  transition: transform .45s var(--ease-out);   /* quick enough that neighbours have settled by the time you move on */
}
.push-group > .push-lead { position: relative; z-index: 1; }
/* the work cards also pick up wearecollins.com's hover shadow (its --shadow-sm at half strength) */
.work .card img { transition: box-shadow .45s var(--ease-out); }
.work .push-lead img { box-shadow: 0 21px 13px rgba(0, 0, 0, .03), 0 9px 9px rgba(0, 0, 0, .05), 0 2px 5px rgba(0, 0, 0, .055); }
.push-group > a.card.push-lead:active { transform: scale(calc(var(--push-scale, 1) * var(--press-scale-lg))); transition-duration: var(--press); }

/* ---- Case study sheet (js/sheet.js, home page): a <dialog> that slides up over the page with the
   case study in it, stopping just short of the top; the page behind dims and loses some colour
   (wearecollins.com's story sheet). Drag it down to close on touch screens. ---- */
.sheet {
  position: fixed; inset: calc(20px + var(--safe-t)) 0 0; width: 100%; height: auto;
  max-width: none; max-height: none; margin: 0; padding: 0; border: 0; outline: none;
  border-radius: 24px 24px 0 0; background: var(--bg); color: var(--text);
  overflow: clip auto; overscroll-behavior: contain;
}
.sheet::backdrop { background: transparent; }
.sheet__bar { position: sticky; top: 0; z-index: 2; height: 0; }
.sheet__handle { position: absolute; left: 50%; top: 10px; width: 42px; height: 5px; margin-left: -21px; border-radius: 99px; background: var(--line); }
.sheet__close { position: absolute; right: 16px; top: 16px; }   /* a .glass-close */
@media (hover: hover) and (pointer: fine) { .sheet__handle { display: none; } }
@media (hover: none) and (pointer: coarse) { .sheet__close { top: 22px; right: 14px; } }
.sheet__page { position: relative; isolation: isolate; max-width: var(--max-width); margin: 0 auto; padding: 0 calc(24px + var(--frame)) 256px; }   /* plenty of room after the last section */
/* the page's graph-paper grid behind the story, fainter (60%), the full width of the sheet and
   scrolling with it, fading unevenly at the edges like the home page's: in from nothing on the left,
   full through the middle, softening to the right, and thinning a little in places down the page */
.sheet__page::before {
  content: ""; position: absolute; z-index: -1; top: 0; bottom: 0; left: 50%; width: 100vw; translate: -50% 0; pointer-events: none;
  background:
    linear-gradient(to right, color-mix(in srgb, var(--grid-v) 60%, transparent) 1px, transparent 1px) 0 0 / 11.3px 11.3px,
    linear-gradient(to bottom, color-mix(in srgb, var(--grid-h) 60%, transparent) 1px, transparent 1px) 0 0 / 11.3px 11.3px;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 30%, #000 70%, rgba(0, 0, 0, .45) 100%),
                      linear-gradient(to bottom, rgba(0, 0, 0, .55), #000 8%, rgba(0, 0, 0, .7) 30%, #000 55%, rgba(0, 0, 0, .6) 80%, #000);
  -webkit-mask-composite: source-in;
          mask-image: linear-gradient(to right, transparent 0%, #000 30%, #000 70%, rgba(0, 0, 0, .45) 100%),
                      linear-gradient(to bottom, rgba(0, 0, 0, .55), #000 8%, rgba(0, 0, 0, .7) 30%, #000 55%, rgba(0, 0, 0, .6) 80%, #000);
          mask-composite: intersect;
}
.sheet__page .hero.page-hero { padding-top: clamp(72px, 12vh, 120px); }
/* the page behind: dims while the sheet is up; no scrolling under it */
html.sheet-on { overflow: hidden; }
html.sheet-on :is(main, .site-header) { transition: opacity .5s ease, filter .5s ease; }
html.sheet-open :is(main, .site-header) { opacity: .4; filter: saturate(.4); }

/* Header links scroll to these on the home page: stop them short of the header */
#work, #about, #kind-words { scroll-margin-top: calc(120px + var(--frame) + var(--safe-t)); }

/* ---- The end (js/footer.js). The footer is an empty strip (--end tall) at the bottom of every page.
   Scroll into it and the whole window rises by as much (a second frame, .site-frame--lift, moved up by
   js/footer.js with translate; everything inside moves with it, except the header, which stays put) and
   brings its sides in by up to 5% (the frame scaled across, main scaled with it; not on touch screens),
   showing black round it. "copy my email" (left) and
   "linkedin" (right) don't move: they sit 128px from the bottom of the screen, behind the page, and
   the rising edge uncovers them (.site-end__inner is the black below the window, clipping them). ---- */
:root { --end: 240px; }
@media (max-width: 600px) { :root { --end: 208px; } }
@media (min-width: 601px) and (hover: hover) and (pointer: fine) { :root { --end: 360px; } }   /* computers: 50% taller (phones and tablets keep their own heights, which are based on 240px) */
.site-end { height: var(--end); }
.site-frame--lift {
  position: fixed; z-index: 50; pointer-events: none; visibility: hidden;
  inset: calc(var(--frame) + var(--safe-t)) calc(var(--frame) + var(--safe-r)) calc(var(--frame) + var(--safe-b)) calc(var(--frame) + var(--safe-l));   /* moved up (translate) and in (scale) by js/footer.js */
  border-radius: var(--frame-radius);
  box-shadow: 0 0 0 100vmax #000;
}
html.lifted .site-frame--lift { visibility: visible; will-change: translate, scale; }
/* the whole window rises as one: the page scrolls, and the background and the black strip along the top
   move up with it, so nothing inside moves against the window's edges */
html.lifted .site-frame { visibility: hidden; }
html.gated .site-frame--lift, html.murmuring .site-frame--lift { visibility: hidden; }
.site-end__inner {
  position: fixed; z-index: 51; left: 0; right: 0; bottom: 0; overflow: hidden;
  height: calc(var(--frame) + var(--safe-b));   /* grows as the window lifts (js/footer.js) */
  color: #f9f8f5; font-size: 1rem;   /* always light: it sits on the black */
}
/* Touch screens: no lifting (js/footer.js). The footer is plain black at the end of the page, with the
   links on it, and scrolls up into view like everything else, so nothing moves to follow the scroll.
   Two corner pieces at its top curve the black up into the frame's sides, so the page still ends in a
   rounded window. */
@media (hover: none) and (pointer: coarse) {
  .site-end { position: relative; height: calc(var(--end) * 1.3 + var(--safe-b)); background: #000; }   /* 30% taller than the strip computers lift into */
  .site-end::before, .site-end::after {
    content: ""; position: absolute; bottom: 100%; width: var(--frame-radius); height: var(--frame-radius); pointer-events: none;
  }
  .site-end::before { left: calc(var(--frame) + var(--safe-l)); background: radial-gradient(circle at 100% 0, transparent calc(var(--frame-radius) - .5px), #000 var(--frame-radius)); }
  .site-end::after { right: calc(var(--frame) + var(--safe-r)); background: radial-gradient(circle at 0 0, transparent calc(var(--frame-radius) - .5px), #000 var(--frame-radius)); }
  .site-end__inner { position: absolute; inset: 0; height: auto; z-index: auto; }
  /* the home page: taller, with the links along the top, "start murmur" (js/footer.js) and the starling
     from the card peeking up from the bottom edge, as the card peeks in from the side on computers */
  .site-end:has(.site-end__murmur) { height: calc(430px + var(--safe-b)); }
  .site-end:has(.site-end__murmur) :is(.site-end__email, .site-end__link) { top: 32px; bottom: auto; z-index: 1; }
  .site-end__murmur {
    position: absolute; inset: 0;
    display: flex; align-items: flex-end; justify-content: center; gap: 12px;
    padding-inline: max(calc(24px + var(--frame)), 5vw);
  }
  /* most of the starling showing, just its feet below the edge; "start murmur" beside it, a plain
     link like the others */
  .site-end__starling { position: relative; display: block; width: 190px; height: auto; margin-bottom: -6%; rotate: -4deg; }
  .site-end__start {
    position: relative; align-self: center; margin-top: 60px; padding: 12px 0;
    font-size: 1rem; color: inherit; background: none; border: 0; text-transform: inherit; white-space: nowrap;
    transition: opacity .2s ease, scale .3s var(--ease-out);
  }
  .site-end__start:active { scale: var(--press-scale); transition-duration: var(--press); }
  .site-end__start:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }
}
/* a flock flying back and forth across the black (js/footer.js): on computers, the strip the lifting
   window uncovers (anchored to the bottom, full size, so the rising edge reveals it); on phones, the
   whole black footer */
.site-end__sky { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; height: calc(var(--end) + var(--frame) + var(--safe-b)); pointer-events: none; }
@media (hover: none) and (pointer: coarse) { .site-end__sky { top: 0; height: 100%; } }
.site-end__murmur { display: none; }   /* computers have the starling card */
@media (hover: none) and (pointer: coarse) { .site-end__murmur { display: flex; } }
@media (prefers-reduced-motion: reduce) { .site-end__murmur { display: none !important; } .site-end:has(.site-end__murmur) { height: calc(var(--end) * 1.3 + var(--safe-b)); } }   /* (no murmur then) */
.site-end__email, .site-end__link {
  position: absolute; bottom: calc(128px + var(--safe-b));
  display: inline-flex; align-items: center; gap: 10px; padding: 12px 0; color: inherit;
  transition: opacity .2s ease, scale .3s var(--ease-out);
}
/* lined up with the content column */
.site-end__email { left: max(calc(24px + var(--frame)), calc((100% - var(--max-width)) / 2 + 24px + var(--frame))); }
.site-end__link { right: max(calc(24px + var(--frame)), calc((100% - var(--max-width)) / 2 + 24px + var(--frame))); }
.site-end__icon { width: 22px; height: 22px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.site-end__email:active, .site-end__link:active { scale: var(--press-scale); transition-duration: var(--press); }
@media (hover: hover) and (pointer: fine) { .site-end__email:hover, .site-end__link:hover { opacity: .7; } }
.site-end :focus-visible { outline: 2px solid currentColor; outline-offset: 4px; }
/* the bird that carries the envelope off (js/footer.js), and the envelope it carries */
.email-bird, .email-bird__load { position: fixed; left: 0; top: 0; z-index: 60; pointer-events: none; }
.email-bird { font: 500 18px/1 var(--mono); color: #f9f8f5; translate: -50% -100%; }
.email-bird__load { color: #f9f8f5; transform-origin: 50% 0; }   /* swings from where the bird holds it */

/* ---- About (home, #about): the two photos (smaller, with the grow-and-push hover), four short blocks
   in a 2x2 grid (about me, how I got here, things I believe, bookshelf) ---- */
.about .about-photos { margin: 0 auto 80px; }
.about-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 56px 64px; align-items: start; }
.about .flow { max-width: none; margin: 0; }
.about .about-block h3 {
  font-family: var(--display); font-size: calc(1.35rem * var(--head-scale, 1)); font-weight: var(--head-weight, 800);
  font-style: var(--head-style, normal); line-height: 1.15; letter-spacing: var(--head-tracking, -0.01em);
  color: var(--tone, var(--accent)); margin-bottom: .7em;
}
[data-tone="accent"] .about .about-block h3 { color: var(--accent); }
[data-tone="text"] .about .about-block h3 { color: var(--text); }
.about .about-block h3 .sym { display: inline-block; margin-right: .2em; }
@media (max-width: 700px) { .about-grid { grid-template-columns: 1fr; gap: 44px; } }

/* ---- Record player (js/player.js): a glass card like the starling card, tucked under the frame's right
   edge just below it (js/player.js sets its top). It springs in just after the starling card, peeks out
   with the edge of the record showing, comes a little further on hover, and slides fully out when
   clicked to show the turntable: the record (the cover as its label) spins while it plays and the
   tonearm swings on; the retro switch in the bottom right plays and stops it. While it plays tucked
   away, a second switch shows on the strip that peeks out, to stop it quickly. ---- */
.record-player {
  --peek: 64px;   /* how much shows while it's tucked away (as the starling card) */
  --gap: 20px;    /* space between the card and the frame when it's out */
  position: fixed; top: calc(var(--frame) + 116px); right: calc(var(--frame) + var(--gap)); z-index: 23;   /* with the starling card */
  width: 172px; padding: 14px 14px 12px; border-radius: var(--radius);
  color: var(--text);
  background: linear-gradient(180deg, var(--glass-tint), transparent 140%), var(--glass-tint);
  border: 1px solid var(--glass-edge);
  box-shadow: inset 0 1px 0.5px var(--glass-rim), inset 0 -1px 1px rgba(0, 0, 0, 0.06),
              inset 0 0 18px rgba(255, 255, 255, 0.05), var(--glass-shadow);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
          backdrop-filter: blur(14px) saturate(160%);
  transform: translateX(calc(100% + var(--gap) - var(--peek))) rotate(3deg);
  transition: transform .3s var(--ease-out), opacity 1.4s ease, scale .3s var(--ease-out);   /* hover nudge, tucking back */
}
.record-player::before {   /* the same soft sheen as the header pill */
  content: ""; position: absolute; inset: 1px; border-radius: inherit; pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0) 55%); opacity: .6;
}
@media (hover: hover) and (pointer: fine) {
  .record-player:not([data-open="true"]):hover { --peek: 100px; transform: translateX(calc(100% + var(--gap) - var(--peek))) rotate(2deg); }
}
.record-player:has(> .record-player__toggle:active) { scale: var(--press-scale-lg); transition-duration: var(--press); }
.record-player.waiting { transform: translateX(calc(100% + var(--gap) + 24px)) rotate(-6deg); }   /* fully under the frame until it springs in */
.record-player.entering { transition: transform var(--enter-duration) var(--enter-ease), opacity 1.4s ease, scale .3s var(--ease-out); transition-delay: 0s; }
.record-player[data-open="true"] { transform: none; transition-duration: .45s; transition-timing-function: var(--ease-drawer); }
.record-player:has(> .record-player__toggle:focus-visible) { outline: 2px solid var(--accent); outline-offset: 4px; }
html.gated .record-player, html.murmuring .record-player { opacity: 0; visibility: hidden; pointer-events: none; }
/* an invisible button covering the whole card: tap or click anywhere on it to open or close it */
.record-player__toggle {
  position: absolute; inset: 0; z-index: 1; border-radius: inherit;
  appearance: none; background: none; border: 0; padding: 0; margin: 0; outline: none;
}
.record-player .retro-switch { z-index: 2; }   /* above the toggle */
/* the quick stop switch on the strip that peeks out, only while it plays tucked away */
.record-player .record-player__mini {
  position: absolute; left: 16px; bottom: 14px;
  opacity: 0; visibility: hidden; transition: opacity .2s ease, visibility 0s .2s;
}
.record-player.is-playing:not([data-open="true"]) .record-player__mini { opacity: 1; visibility: visible; transition-delay: .15s, 0s; }
.record-player .record-player__foot { transition: opacity .2s ease; }
.record-player.is-playing:not([data-open="true"]) .record-player__foot { opacity: 0; }   /* out of the stop switch's way */
@media (max-width: 600px) {
  .record-player { --peek: 48px; --gap: 12px; width: 150px; padding: 12px 12px 10px; }
}
/* reduced motion: fades, but moves in and out at once (as the starling card) */
@media (prefers-reduced-motion: reduce) {
  .record-player { transition-property: opacity !important; transition-duration: .2s !important; transition-timing-function: ease !important; transition-delay: 0s !important; }
  .record-player__disc, .record-player__shine { transition: none; }
}
/* the deck: the record, straight on the glass, with the tonearm to its right */
.record-player__deck { position: relative; aspect-ratio: 1; padding: 9%; }
.record-player__disc {
  position: relative; display: grid; place-items: center; width: 100%; aspect-ratio: 1; border-radius: 50%;
  background: repeating-radial-gradient(circle, #141414 0 1px, #1e1e1e 1px 2px);   /* grooves */
  box-shadow: 0 6px 14px rgba(0, 0, 0, .4), 0 0 0 1px rgba(255, 255, 255, .05) inset;
}
/* tucked away and playing, the record slides out past the card's edge, like out of a sleeve, so you
   can see it spin; back in when it stops or the card comes out (the tonearm needs it there) */
.record-player__disc, .record-player__shine { transition: translate .7s var(--ease-out); }
.record-player.is-playing:not([data-open="true"]) :is(.record-player__disc, .record-player__shine) { translate: -44px 0; transition-delay: .15s; }
@media (max-width: 600px) { .record-player.is-playing:not([data-open="true"]) :is(.record-player__disc, .record-player__shine) { translate: -36px 0; } }
.record-player__disc img { width: 36%; height: auto; aspect-ratio: 1; border-radius: 50%; object-fit: cover; }
.record-player__disc::after {   /* the spindle */
  content: ""; position: absolute; left: 50%; top: 50%; width: 4%; aspect-ratio: 1; translate: -50% -50%;
  border-radius: 50%; background: #d8d4cc;
}
/* light catching the grooves: stays still while the record turns */
.record-player__shine {
  position: absolute; inset: 9%; border-radius: 50%; pointer-events: none;
  background: conic-gradient(from 20deg, transparent 0 8%, rgba(255, 255, 255, .10) 13%, transparent 20% 55%, rgba(255, 255, 255, .07) 62%, transparent 70%);
  -webkit-mask: radial-gradient(circle, transparent 0 19%, #000 19.5%); mask: radial-gradient(circle, transparent 0 19%, #000 19.5%);
}
.record-player__arm {
  position: absolute; right: 7%; top: 7%; width: 3px; height: 58%; border-radius: 2px; pointer-events: none;
  background: linear-gradient(90deg, #9d9a94, #eeebe4 45%, #a8a49d);
  box-shadow: 1px 2px 4px rgba(0, 0, 0, .3);
  transform-origin: 50% 0; rotate: 6deg;          /* resting off the record */
  transition: rotate .7s var(--ease-in-out);
}
.record-player.is-playing .record-player__arm { rotate: 27deg; }   /* on the record */
.record-player__arm::before {   /* the pivot */
  content: ""; position: absolute; left: 50%; top: -5px; width: 11px; height: 11px; translate: -50% 0; border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #f4f1ea, #9d9a94); box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
}
.record-player__arm::after {   /* the head */
  content: ""; position: absolute; left: 50%; bottom: -3px; width: 6px; height: 10px; translate: -50% 0; border-radius: 2px;
  background: linear-gradient(90deg, #6f6c67, #c9c5bd); rotate: 18deg;
}
/* under the deck: the track, and the switch in the corner */
.record-player__foot { display: flex; align-items: center; gap: 6px; margin-top: 7px; padding-inline: 2px; }
.record-player__track { flex: 1; min-width: 0; max-width: none; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: .65rem; line-height: 1.3; }
.record-player__title { font-family: var(--display); font-weight: var(--head-weight, 800); color: var(--text); }
.record-player__artist { font-family: var(--mono); color: var(--muted); }

/* ---- Retro switch (.retro-switch, role="switch" with aria-checked): a tiny on/off slider like an old
   Mac control, to go with the pixel cursors. A raised, bevelled square knob with grip lines sits in a
   recessed slot, so it reads as something to slide even when it's off; it clicks across in steps, and
   the slot shows a 1-bit dither when it's on. ---- */
.retro-switch {
  position: relative; flex: none; width: 30px; height: 16px; padding: 0; border-radius: 0;
  border: 1px solid var(--text);
  background: color-mix(in srgb, var(--text) 22%, var(--bg));                     /* the slot, set into the case */
  box-shadow: inset 1px 1px 0 color-mix(in srgb, var(--text) 55%, var(--bg)),     /* its shaded inner edge */
              1px 1px 0 var(--text);                                                /* a 1px drop shadow */
}
.retro-switch[aria-checked="true"] {
  background: repeating-conic-gradient(var(--text) 0 25%, var(--bg) 0 50%) 0 0 / 2px 2px;   /* 50% dither */
}
.retro-switch__knob {
  position: absolute; left: -1px; top: -1px; width: 16px; height: 16px;   /* over the slot's border: it stands proud */
  border: 1px solid var(--text);
  background:
    repeating-linear-gradient(90deg, color-mix(in srgb, var(--text) 70%, var(--bg)) 0 1px, transparent 1px 2px) center / 5px 6px no-repeat,   /* grip lines */
    var(--bg);
  box-shadow: inset 1px 1px 0 color-mix(in srgb, #fff 75%, var(--bg)),          /* lit top and left */
              inset -1px -1px 0 color-mix(in srgb, var(--text) 40%, var(--bg)),  /* shaded bottom and right */
              1px 1px 0 var(--text);
  transition: translate .12s steps(3, end);   /* chunky, like it's moving a pixel at a time */
}
.retro-switch[aria-checked="true"] .retro-switch__knob { translate: 14px 0; }
.retro-switch:active .retro-switch__knob { box-shadow: inset 1px 1px 0 color-mix(in srgb, var(--text) 40%, var(--bg)); }   /* pressed in */
.retro-switch:focus-visible { outline: 1px dotted var(--text); outline-offset: 3px; }
.retro-switch::after { content: ""; position: absolute; inset: -14px -12px; }   /* a bigger target for fingers (about 54 x 44) than the switch itself */
/* play/stop: a play triangle on the knob instead of grip lines, turning into a stop square when it's on */
.retro-switch--play .retro-switch__knob { background: var(--bg); }
.retro-switch--play .retro-switch__knob::before {
  content: ""; position: absolute; left: 50%; top: 50%; width: 8px; height: 8px; translate: -40% -50%;
  background: var(--play-green); clip-path: polygon(0 0, 100% 50%, 100% 50%, 0 100%);   /* green: play */
  transition: clip-path .12s steps(2, end), translate .12s steps(2, end), background-color .12s steps(1, end);
}
.retro-switch--play[aria-checked="true"] .retro-switch__knob::before { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); translate: -50% -50%; background: var(--stop-red); }   /* red: stop */
.retro-switch--play { --play-green: #2f9e4f; --stop-red: #d8392b; }
@media (prefers-reduced-motion: reduce) { .record-player__arm, .retro-switch__knob { transition: none; } }   /* (and the record doesn't spin: js/player.js) */

/* ---- Theme waterfall (js/theme.js): pressing the theme button uncovers the new theme with a soft
   diagonal edge that washes down from the top right to the bottom left (1.6s, a wide feathered edge). The mask is a gradient four times the page's size, opaque towards its top right; it slides from
   showing only its clear corner to showing only its opaque one. The colours switch at once meanwhile (html.theme-instant), so the new
   page is caught finished. ---- */
html.theme-instant :not([data-theme-toggle] svg), html.theme-instant *::before, html.theme-instant *::after { transition: none !important; }   /* (not the theme icons: they set and rise through it) */
html.theme-waterfall::view-transition-old(root) { animation: none; }
html.theme-waterfall::view-transition-new(root) {
  animation: theme-waterfall var(--wash, 1.6s) cubic-bezier(0.37, 0, 0.63, 1) both; mix-blend-mode: normal;   /* even: a gentle wash (--wash: js/theme.js) */
  -webkit-mask: linear-gradient(to bottom left, #000 30%, transparent 70%) 0 100% / 400% 400% no-repeat;   /* a wide, soft edge */
          mask: linear-gradient(to bottom left, #000 30%, transparent 70%) 0 100% / 400% 400% no-repeat;
}
@keyframes theme-waterfall { to { -webkit-mask-position: 100% 0; mask-position: 100% 0; } }
/* the theme button isn't part of the wash: it's lifted out on top, live, so its icons can be seen setting
   and rising instead of the old button dissolving into the new */
html.theme-waterfall [data-theme-toggle] { view-transition-name: theme-toggle; }
html.theme-waterfall::view-transition-group(theme-toggle), html.theme-waterfall::view-transition-new(theme-toggle) { animation: none; }
html.theme-waterfall::view-transition-old(theme-toggle) { display: none; }

/* ---- Rising in (js/main.js, riseIn): pieces and images waiting to rise in stay hidden until they come
   into view (then WAAPI brings them in). A case study's lede and year/role/company follow its title up
   as it rises (theme.js's hero reveal adds .hero-shown). ---- */
.rise-wait, .clip-wait { opacity: 0; }
.page-hero > :not(h1) { transition: opacity .6s var(--ease-out) .55s, translate .6s var(--ease-out) .55s; }
.page-hero > .meta { transition-delay: .67s; }
.page-hero:not(.hero-shown) > :not(h1) { opacity: 0; translate: 0 16px; }
.page-hero.hero-instant > :not(h1) { transition: none; }
@media (prefers-reduced-motion: reduce) { .page-hero:not(.hero-shown) > :not(h1) { translate: none; } }
