/* Detective Dave. One courtroom behind the whole page, one centre line
   down the middle of it, and six parts hung on that line at one even beat.

   COHERENCE RULES. These are hard; read them before touching anything.

   1  One central axis, like meesbeuk.com. One container (max 1120px,
      --dd-max, the same side gutters everywhere), and every part is centred
      on the page's centre line: headings, short lines (measure max 640px,
      --dd-measure), keys, the counter, the newest video, the card grid, the
      footer. The only left-aligned text is a paragraph inside a centred
      block (the About bio), because a paragraph reads better that way.
   2  One vertical rhythm. Every part is a .part: --dd-rhythm above it and
      nothing else. Heading to content is always --dd-head-gap. Items inside
      a part are always --dd-stack apart.
   3  Four type sizes: display (Akira: headings, numerals, doodles), large
      (one-line statements: the hero line, the video title, the line under
      a heading), body (reading text and keys), small (meta, labels, nav).
      Two text weights: 400 and 600.
   4  One card: white, a 2px navy rim, radius = key radius + its padding
      (--dd-radius-card, 24), the hard white lip under it. Video cards, the
      newest video, the HTPD photo and the career keys are this card. The
      counter's digit tiles are keys (--dd-radius-md, 12). Three radii in
      all: key 12, nav 20, card 24, one concentric family.
   5  One primary key (white) and one secondary key (outline). Everything
      else you can click is an underlined text link.
   6  One shadow: the hard key lip, and only under light objects (white
      keys, white cards, digit keys, Dave's bar). Dark objects on navy (the
      nav, the quiet key) get no lip and no shadow at all. No soft or black
      shadows anywhere. Borders: 2px on keys and cards; dark surfaces (the
      nav's outer edge, the quiet key) get the one 1px white/12% hairline.
   7  Only the newest video tilts, and it settles flat. Nothing else is
      rotated (bar the yellow ticker and the handwriting). Nothing idles:
      the ticker moves only while the page scrolls.
   9  One width. Nav, newest video, grid and footer share the 1120px
      container (--dd-max; the newest video settles at exactly that width,
      no overscale). Text inside runs at the 640px measure (--dd-measure):
      the About bio and its three keys share it; the HTPD photo is 420.
      The yellow ticker is decorative band art (aria-hidden, no links) and
      the one type-size exception, like the handwriting face.
   8  Colour: navy, white and its alpha tints. Yellow only for the doodles
      and the ticker; red only inside the YouTube mark.

   The ticker (ticker.css/.js) and the doodles (doodles.css/.js) are their
   own files; this sheet only leaves room for them.

   Every value comes from tokens.css (kit-src/tokens.json). Sizes are rem:
   fixed up to 1920 CSS px; above that (TVs) the root grows and the page
   scales as one, on purpose. */

@import url('tokens.css?v=1790179932');

/* AKIRA Expanded, the channel's title face (Super Bold only). Very wide, so
   it is set small, and its word spaces are pulled in. */
@font-face {
  font-family: 'Akira Expanded';
  src: url('/fonts/akira-expanded.woff2') format('woff2');
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

/* ------------------------------------------------------------------ base */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* a navy site: dark scrollbars, focus and autofill UI */
:root {
  color-scheme: dark;
}

html {
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--dd-nav-h) + var(--dd-space-8));
  background: var(--dd-navy);
  overflow-x: clip;
}

/* above 1920 CSS px: 16px at 1920 wide, growing with the screen, 32px cap */
@media (min-width: 1921px) {
  html {
    font-size: min(calc(100vw / 120), 2rem);
  }
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* the body stays clear so the fixed courtroom (z-index -1) shows through */
body {
  margin: 0;
  background: transparent;
  color: var(--dd-fg);
  font-family: var(--dd-font-sans);
  font-size: var(--dd-size-body);
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: var(--dd-track-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

img,
svg,
picture {
  display: block;
  max-width: 100%;
}

p,
h1,
h2,
h3,
figure,
ol,
ul {
  margin: 0;
}

ol,
ul {
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
}

::selection {
  background: var(--dd-select-bg);
  color: var(--dd-select-fg);
}

:focus-visible {
  outline: 0.1875rem solid var(--dd-focus);
  outline-offset: 0.1875rem;
  border-radius: var(--dd-radius-md);
}

[hidden] {
  display: none !important;
}

[data-theme='navy'] {
  color: var(--dd-fg);
}

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

.skip {
  position: absolute;
  left: var(--dd-space-4);
  top: var(--dd-space-3);
  z-index: 100;
  padding: var(--dd-space-3) var(--dd-space-5);
  border-radius: var(--dd-radius-md);
  background: var(--dd-white);
  color: var(--dd-navy);
  font-weight: 600;
  translate: 0 -200%;
  transition: translate var(--dd-dur-base) var(--dd-ease-out);
}

.skip:focus-visible {
  translate: 0 0;
  outline-color: var(--dd-white);
}

/* ---------------------------------------------------------------- layout */

.wrap {
  width: 100%;
  max-width: calc(var(--dd-max) + var(--dd-gutter) * 2);
  margin-inline: auto;
  padding-inline: max(var(--dd-gutter), env(safe-area-inset-left)) max(var(--dd-gutter), env(safe-area-inset-right));
}

/* one part of the page: the one beat above it, centred on the axis */
.part {
  position: relative;
  padding-top: var(--dd-rhythm);
  text-align: center;
}

.part .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* ------------------------------------------------------------------ type */

/* display: the heading of every part, in the channel's wide voice */
.head-title {
  max-width: 22em;
  text-align: center;
  margin-bottom: var(--dd-head-gap);
  font-family: var(--dd-font-display);
  font-size: var(--dd-size-display);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: 0;
  word-spacing: -0.15em;
  text-wrap: balance;
}

/* the second line of a heading always starts on its own line */
/* a heading with its own subline right under it (the footer's "Send me an
   email."): the subline is part of the heading block, 16px under it; the
   block then keeps the usual gap to its content */
.head-title:has(+ .foot__line) {
  margin-bottom: var(--dd-space-4);
}

.head-title__soft {
  display: block;
  color: var(--dd-fg-3);
}

/* large: a one-line statement, never wider than the measure */
.hero__lede,
.stage__title,
.count__line,
.foot__line {
  max-width: min(var(--dd-measure), 100%);
  font-size: var(--dd-size-large);
  line-height: 1.45;
  text-wrap: pretty;
}

/* small: meta and labels */
.stage__when,
.video__meta,
.cred span,
.foot__base,
.nav__links a {
  font-size: var(--dd-size-small);
}

/* the one inline link: underlined, arrow after */
.text-link {
  display: inline-flex;
  align-items: center;
  gap: var(--dd-space-1);
  border-radius: var(--dd-radius-md);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-thickness: var(--dd-stroke-ink);
  text-underline-offset: 0.3125rem;
  white-space: nowrap;
}

.text-link svg {
  width: 1.125em;
  height: 1.125em;
  flex: none;
  transition: translate var(--dd-dur-base) var(--dd-ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .text-link:hover svg {
    translate: 0.125rem -0.125rem;
  }
}

/* ------------------------------------------------------------------ keys */

/* The pressed key: a 2px rim with the hard lip under it. Pressing sinks it
   into its lip; hover lifts it a hair. Primary is white, secondary is an
   outline; there is nothing else. */
.key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--dd-space-3);
  min-height: var(--dd-key-h);
  padding: var(--dd-space-2) var(--dd-space-6);
  border: var(--dd-stroke-ink) solid var(--dd-white);
  border-radius: var(--dd-radius-md);
  font: inherit;
  font-size: var(--dd-size-body);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--dd-shadow-lip);
  transition:
    translate var(--dd-dur-press) var(--dd-ease-out),
    box-shadow var(--dd-dur-press) var(--dd-ease-out);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  user-select: none;
}

.key--light {
  background: var(--dd-white);
  color: var(--dd-navy);
}

/* the quiet secondary: the nav's own surface, no rim, no lip. For the
   buttons that sit beside a primary without competing with it. */
.key.key--quiet {
  min-height: 3.5rem;
  padding-inline: var(--dd-space-5);
  gap: var(--dd-space-2);
  border: 1px solid var(--dd-white-a12);
  background: var(--dd-white-a08);
  color: var(--dd-white);
  font-size: var(--dd-size-small);
  box-shadow: none;
  transition:
    background-color var(--dd-dur-fast) var(--dd-ease-hover),
    scale var(--dd-dur-press) var(--dd-ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .key.key--quiet:hover {
    translate: none;
    box-shadow: none;
    background: var(--dd-white-a12);
  }
}

.key.key--quiet:active {
  translate: none;
  box-shadow: none;
  scale: 0.97;
}

.key--quiet .key__icon {
  width: 1.25rem;
  height: 1.25rem;
}

.key--quiet .key__yt {
  width: 1.5rem;
  height: 1.0625rem;
}

.key__icon {
  width: 1.375rem;
  height: 1.375rem;
  flex: none;
}

/* the real YouTube mark, in its own red: a brand asset, not a UI colour */
.key__yt {
  width: 1.75rem;
  height: 1.25rem;
  flex: none;
}

/* the compact key, for the nav only */
.key--sm {
  min-height: var(--dd-key-h-sm);
  padding: 0 var(--dd-space-4);
  border: 0;
  gap: var(--dd-space-2);
  font-size: var(--dd-size-small);
}

.key--sm .key__yt {
  width: 1.5rem;
  height: 1.0625rem;
}

@media (hover: hover) and (pointer: fine) {
  .key:hover {
    translate: 0 var(--dd-lift);
    box-shadow: var(--dd-shadow-lip-hover);
  }
}

.key:active {
  translate: 0 0.25rem;
  box-shadow: var(--dd-shadow-lip-down);
}

.key:focus-visible {
  outline-offset: var(--dd-space-1);
  border-radius: var(--dd-radius-md);
}

/* ------------------------------------------------------------------ card */

/* The one card: white, navy ink inside, radius concentric with what it
   holds (key radius + its padding), the hard white lip under it. */
.card {
  --dd-fg: var(--dd-navy);
  --dd-fg-2: var(--dd-navy-a78);
  --dd-sunk: var(--dd-navy-a06);
  --dd-focus: var(--dd-navy);
  display: flex;
  flex-direction: column;
  padding: var(--dd-card-pad);
  border: var(--dd-stroke-ink) solid var(--dd-navy);
  border-radius: var(--dd-radius-card);
  background: var(--dd-white);
  color: var(--dd-navy);
  box-shadow: var(--dd-shadow-lip);
  text-decoration: none;
}

/* ------------------------------------------------------------------- nav */

/* One nav, the same from the first frame to the last: a solid white bar on
   the container's edges with the fedora, three links and the Subscribe
   key. Its corner is concentric with the key (key radius + its padding).
   A white object, so the standard lip (plus a navy/24% hairline for when
   it passes over white cards); navy ink, and the Subscribe key inverts to
   navy. Nothing inside it has a border of its own. */
.nav {
  --pad: var(--dd-space-2);
  position: fixed;
  top: calc(var(--dd-space-3) + env(safe-area-inset-top));
  left: 50%;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: var(--dd-space-2);
  width: min(var(--dd-max), calc(100% - var(--dd-gutter) * 2));
  height: var(--dd-nav-h);
  padding: 0 var(--pad) 0 calc(var(--pad) + var(--dd-space-3));
  border-radius: var(--dd-radius-nav);
  background: var(--dd-white);
  color: var(--dd-navy);
  /* a white object: the standard lip, plus a navy hairline so it still
     separates when it slides over the white cards */
  box-shadow: var(--dd-shadow-lip), 0 0 0 1px var(--dd-navy-a24);
  --dd-focus: var(--dd-navy);
  translate: -50% 0;
}

.nav :focus-visible {
  outline: var(--dd-stroke-ink) solid var(--dd-navy);
  outline-offset: 0.125rem;
}

.nav__mark {
  display: grid;
  place-items: center;
  height: var(--dd-key-h-sm);
  flex: none;
  color: var(--dd-navy);
  border-radius: var(--dd-radius-md);
}

.nav__mark svg {
  width: auto;
  height: var(--dd-nav-mark);
  aspect-ratio: 247 / 143;
}

.nav__links {
  display: flex;
  align-items: center;
  margin-left: auto;
  margin-right: var(--dd-space-2);
}

.nav__links a {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: var(--dd-key-h-sm);
  padding: 0 var(--dd-space-3);
  border-radius: var(--dd-radius-md);
  color: var(--dd-navy-a78);
  font-weight: 600;
  text-decoration: none;
  transition: color var(--dd-dur-fast) var(--dd-ease-hover);
}

/* the part you are reading: a short line under its word */
.nav__links a::after {
  content: '';
  position: absolute;
  left: var(--dd-space-3);
  right: var(--dd-space-3);
  bottom: 0.5rem;
  height: var(--dd-stroke-ink);
  background: currentColor;
  scale: 0 1;
  transition: scale var(--dd-dur-base) var(--dd-ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .nav__links a:hover {
    color: var(--dd-navy);
  }
}

.nav__links a[aria-current='true'] {
  color: var(--dd-navy);
}

.nav__links a[aria-current='true']::after {
  scale: 1 1;
}

/* Subscribe inverts inside the white bar: a navy key, no lip */
.nav__sub {
  flex: none;
}

.nav .key.nav__sub {
  background: var(--dd-navy);
  color: var(--dd-white);
  box-shadow: none;
  transition:
    background-color var(--dd-dur-fast) var(--dd-ease-hover),
    scale var(--dd-dur-press) var(--dd-ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .nav .key.nav__sub:hover {
    translate: none;
    box-shadow: none;
    background: var(--dd-navy-2);
  }
}

.nav .key.nav__sub:active {
  translate: none;
  box-shadow: none;
  scale: 0.97;
}

/* ----------------------------------------------------------------- world */

/* One courtroom behind the whole page. As you scroll the camera walks
   slowly into the room, the room dims while there is reading to do, and it
   eases back for the goodbye at the bottom. site.js drives both. */
.world {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  background: var(--dd-navy);
  pointer-events: none;
}

.world__plate {
  position: absolute;
  inset: -4%;
  background:
    image-set(url('/assets/world/court.avif') type('image/avif'), url('/assets/world/court.webp') type('image/webp'), url('/assets/world/court.jpg') type('image/jpeg'))
    center 38% / cover no-repeat,
    var(--dd-navy);
  transform-origin: 50% 40%;
  will-change: transform;
}

.world__light {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(60% 45% at 50% 44%, var(--dd-white-a08), transparent 70%),
    linear-gradient(to bottom, var(--dd-navy-a60) 0, transparent 24%, transparent 60%, var(--dd-navy-a86) 100%),
    radial-gradient(120% 90% at 50% 45%, transparent 55%, var(--dd-navy-a60) 100%);
}

.world__dim {
  position: absolute;
  inset: 0;
  background: var(--dd-navy);
  opacity: 0;
}

/* ------------------------------------------------------------------ hero */

/* A show poster, composed like the channel banner: the logo and Dave side
   by side as one lockup centred on the axis, Dave large and lit, fading
   out at the waist into the room; the line and the one key centred below.
   The yellow ticker runs along the hero's bottom edge. */
.hero {
  /* logo 1.35x its old 380: the left group weighs as much as Dave */
  --dave-h: min(calc(100svh - 14rem), 42rem);
  --logo-w: 31.25rem;
  /* pinned while the page rides up over it (site.js: curtain) */
  position: sticky;
  top: 0;
  z-index: 0;
  isolation: isolate;
  overflow: clip;
  display: grid;
  align-items: center;
  min-height: max(100svh, 40rem);
  padding-block: calc(var(--dd-space-3) + var(--dd-nav-h) + var(--dd-space-6)) var(--dd-space-16);
  text-align: center;
}

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
}

/* The hero is the one exception to the centre axis: two columns, the
   pair centred in the container. Left: logo, line, key, left-aligned to
   the logo and centred (a touch high) against Dave. Right: Dave on his bar.
   Nothing under the pair: the ticker follows. */
.hero__lockup {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--dd-space-4);
}

.hero__side {
  position: relative;
  z-index: 1;
  flex: none;
  display: grid;
  justify-items: start;
  width: var(--logo-w);
  margin-bottom: var(--dd-space-8);
  text-align: left;
  will-change: transform, opacity;
}

.hero__logo {
  margin: 0;
}

.hero__logo img {
  width: var(--logo-w);
  height: auto;
}

.hero__dave {
  position: relative;
  z-index: -1;
  flex: none;
  height: var(--dave-h);
  aspect-ratio: 1171 / 1343;
  will-change: transform;
}

.hero__dave picture,
.hero__dave img {
  width: 100%;
  height: 100%;
}

.hero__dave img {
  object-fit: contain;
  object-position: 50% 100%;
}

/* An invisible box over just his head and hat, for the "Hi, I'm Dave!"
   doodle to point at. Measured from the cutout's alpha (head+hat: x 26.8
   to 69.3%, y 0.4 to 38% of the image); site.js maps it onto wherever the
   image is actually drawn, contain or cover. */
.hero__head {
  position: absolute;
  left: 26.8%;
  top: 0.4%;
  width: 42.5%;
  height: 37.6%;
  pointer-events: none;
}

/* Dave rises out from behind his bar, never below it */
.hero__dave picture {
  display: block;
  clip-path: inset(-50% -50% 0 -50%);
}

/* The banner's white bar: Dave stands on it, a clean base instead of a fade.
   Proportions from Mees's card (361 wide: bar 293 x 22, 11px below him). */
.hero__bar {
  --bar-h: calc(var(--dave-h) * 0.0537);
  position: absolute;
  left: 9.4%;
  right: 9.4%;
  bottom: calc(var(--bar-h) * -0.5);
  height: var(--bar-h);
  border-radius: var(--dd-radius-md);
  background: var(--dd-white);
  box-shadow: var(--dd-shadow-lip);
}

/* a soft pool of light in the room behind him */
.hero__glow {
  position: absolute;
  z-index: -1;
  inset: -12% -30% -4%;
  background: radial-gradient(closest-side at 50% 42%, var(--dd-white-a14), var(--dd-white-a08) 45%, transparent 100%);
  pointer-events: none;
}

.hero__copy {
  display: grid;
  justify-items: start;
  width: 100%;
  margin-top: var(--dd-space-8);
}

.hero .hero__lede {
  max-width: 100%;
  color: var(--dd-white);
  text-wrap: balance;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--dd-space-4);
  margin-top: var(--dd-space-8);
}

/* Entrance: Dave rises into the room, then the logo, the line and the keys
   fade up out of a blur, one after another. */
.js .hero__dave img {
  translate: 0 18%;
  opacity: 0;
}

.js .hero__bar {
  opacity: 0;
  scale: 0.92 1;
}

.hero__bar {
  transition:
    opacity var(--dd-dur-enter) var(--dd-ease-expo),
    scale var(--dd-dur-enter) var(--dd-ease-expo);
}

.hero.is-in .hero__bar {
  opacity: 1;
  scale: 1;
}


.js .hero__logo,
.js .hero__lede,
.js .hero__actions {
  opacity: 0;
  translate: 0 var(--dd-reveal-y);
  filter: blur(var(--dd-reveal-blur));
}

.hero__dave img,
.hero__logo,
.hero__lede,
.hero__actions {
  transition:
    opacity var(--dd-dur-enter) var(--dd-ease-expo),
    translate var(--dd-dur-enter) var(--dd-ease-expo),
    filter var(--dd-dur-enter) var(--dd-ease-expo);
}

.hero__logo {
  transition-delay: var(--dd-stagger-enter);
}

.hero__lede {
  transition-delay: calc(var(--dd-stagger-enter) * 2);
}

.hero__actions {
  transition-delay: calc(var(--dd-stagger-enter) * 3);
}

.hero.is-in :is(.hero__dave img, .hero__logo, .hero__lede, .hero__actions) {
  opacity: 1;
  translate: 0 0;
  filter: none;
}

/* "Hi, I'm Dave!" is the first doodle in the page, so the first in the
   doodle layer: it waits for the hero to finish arriving, then draws on */
.dd-doodle:first-child .dd-doodle__note {
  transition-delay: 900ms;
}

.dd-doodle:first-child .dd-doodle__shaft {
  transition-delay: 1040ms, 1040ms;
}

.dd-doodle:first-child .dd-doodle__head {
  transition-delay: 1520ms, 1520ms;
}

/* ----------------------------------------------------------------- stage */

/* The newest video is the big video card: the screen and its caption plate
   in one card, centred. It starts tilted back and settles flat as it comes
   up the page. It turns on its top edge and grows from its centre, so its
   top edge never moves: the doodle above it keeps its gap. */
.stage__anchor {
  position: relative;
  width: 100%;
  max-width: var(--dd-stage-max);
}

.stage__card {
  transform-origin: 50% 0;
  will-change: transform;
}

.stage__screen {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--dd-radius-md);
  background: var(--dd-navy);
}

.stage__screen img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* the real player, once asked for: always the whole 16:9 box */
.stage__screen iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* the whole still is the play button; its key sits in the corner, clear
   of the words burned into the thumbnail */
.stage__start {
  position: absolute;
  inset: 0;
  border: 0;
  padding: 0;
  background: transparent;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.stage__play {
  position: absolute;
  left: var(--dd-space-5);
  bottom: var(--dd-space-5);
  pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
  .stage__start:hover .stage__play {
    translate: 0 var(--dd-lift);
    box-shadow: var(--dd-shadow-lip-hover);
  }
}

.stage__start:active .stage__play {
  translate: 0 0.25rem;
  box-shadow: var(--dd-shadow-lip-down);
}

.stage__start:focus-visible {
  outline: 0.25rem solid var(--dd-white);
  outline-offset: -0.5rem;
  border-radius: var(--dd-radius-md);
}

.stage__caption {
  display: grid;
  justify-items: center;
  gap: var(--dd-space-1);
  padding: var(--dd-space-5) var(--dd-space-4) var(--dd-space-4);
}

.stage__words {
  display: contents;
}

/* segments never break inside; where the line does break, site.js turns
   that separator into the break, so no line starts or ends with a dot */
.stage__when {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  font-weight: 600;
  color: var(--dd-fg-2);
}

.stage__seg {
  white-space: nowrap;
}

.stage__dot {
  white-space: pre;
}

.stage__dot.is-break {
  flex-basis: 100%;
  height: 0;
  overflow: hidden;
}

.stage__title {
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: var(--dd-track-title);
  text-wrap: balance;
}

/* ----------------------------------------------------------------- count */

.count__row {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--dd-space-1);
}

/* inside a part the gaps are small and fixed: tiles to line 24, line to
   key 32; between parts it is the much larger --dd-rhythm */
.count__line {
  margin-top: var(--dd-space-6);
  color: var(--dd-fg-2);
}

.count .key {
  margin-top: var(--dd-space-8);
}

/* ----------------------------------------------------------------- tiles */

/* Numbers on small cards. Each digit is a reel of 0 to 9 that rolls up
   into place, odometer style, when it scrolls in. */
.tiles {
  --tile-w: 3.75rem;
  --tile-h: 5rem;
  --tile-step: calc(var(--tile-h) - var(--dd-stroke-ink) * 2);
  display: flex;
  align-items: flex-end;
  gap: var(--dd-space-2);
  padding-bottom: 0.3125rem;
}

.tile {
  width: var(--tile-w);
  height: var(--tile-h);
  overflow: hidden;
  border: var(--dd-stroke-ink) solid var(--dd-navy);
  border-radius: var(--dd-radius-md);
  background: var(--dd-white);
  box-shadow: var(--dd-shadow-lip);
}

.tile__reel {
  display: grid;
  transition: translate var(--dd-dur-count) var(--dd-ease-expo);
  transition-delay: calc(var(--i, 0) * var(--dd-stagger) * 2);
}

.tile__reel span,
.tiles__sep {
  font-family: var(--dd-font-display);
  font-size: var(--dd-size-display);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.tile__reel span {
  display: grid;
  place-items: center;
  height: var(--tile-step);
  color: var(--dd-navy);
}

.tiles.is-in .tile__reel {
  translate: 0 calc(var(--d) * var(--tile-step) * -1);
}

/* the thousands comma: on the digits' baseline, with the same air either
   side as between two tiles, so 3 , 3 2 0 reads evenly spaced */
.tiles__sep {
  align-self: center;
  margin-inline: var(--dd-space-1);
  line-height: 1;
  translate: 0 0.3em;
}

/* ---------------------------------------------------------------- videos */

.videos {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--dd-col-gap);
}

.video {
  min-width: 0;
}

.video .card {
  height: 100%;
}

a.card {
  -webkit-tap-highlight-color: transparent;
  transition:
    translate var(--dd-dur-base) var(--dd-ease-out),
    box-shadow var(--dd-dur-base) var(--dd-ease-out);
}

@media (hover: hover) and (pointer: fine) {
  a.card:hover {
    translate: 0 var(--dd-lift-card);
    box-shadow: var(--dd-shadow-lip-hover);
  }
  a.card:hover .video__thumb img {
    scale: 1.03;
  }
}

a.card:active {
  translate: 0 0.25rem;
  box-shadow: var(--dd-shadow-lip-down);
  transition-duration: var(--dd-dur-press);
}

a.card:focus-visible {
  outline: 0.1875rem solid var(--dd-white);
  outline-offset: 0.3125rem;
  border-radius: var(--dd-radius-card);
}

.video__thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--dd-radius-md);
  background: var(--dd-sunk);
  overflow: hidden;
}

.video__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition:
    opacity var(--dd-dur-slow) var(--dd-ease-out),
    scale var(--dd-dur-slow) var(--dd-ease-out);
}

.video__thumb.is-loaded img {
  opacity: 1;
}

.video .card {
  text-align: left;
}

.video__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--dd-space-3);
  padding: var(--dd-space-4) var(--dd-space-2) var(--dd-space-2);
}

.video__title {
  font-size: var(--dd-size-body);
  line-height: 1.35;
  font-weight: 600;
  letter-spacing: var(--dd-track-title);
  text-wrap: pretty;
}

.video__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--dd-space-2);
  margin-top: auto;
  color: var(--dd-fg-2);
}

.video__when {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0 var(--dd-space-2);
}

/* a small play mark in the thumbnail's corner: decoration only, the whole
   card is the one link */
.video__play {
  position: absolute;
  left: var(--dd-space-2);
  bottom: var(--dd-space-2);
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--dd-radius-md);
  background: var(--dd-white);
  color: var(--dd-navy);
}

.video__play svg {
  width: 0.875rem;
  height: 0.875rem;
  translate: 0.0625rem 0;
}

/* skeletons breathe calmly while the list loads, then they are gone */
.video--skeleton .video__thumb,
.video--skeleton .bar {
  background: var(--dd-sunk);
  animation: breathe var(--dd-dur-pulse) var(--dd-ease-in-out) infinite alternate;
}

@keyframes breathe {
  to {
    opacity: 0.35;
  }
}

.bar {
  display: block;
  height: 1.125rem;
  border-radius: var(--dd-radius-md);
}

.bar--short {
  width: 40%;
}

.videos__error {
  max-width: 34em;
}

.more__all {
  margin-top: var(--dd-stack);
}

.more__ask {
  margin-top: var(--dd-space-6);
  color: var(--dd-white);
  text-wrap: balance;
}

/* ----------------------------------------------------------------- about */

/* Everything on the one central axis: the heading, the HTPD photo card,
   Dave's words at a reading measure, the three keys as one row, then the
   voice line. */
.about__stack {
  display: grid;
  justify-items: center;
  gap: var(--dd-stack);
  width: 100%;
  text-align: center;
}

.about__photo {
  position: relative;
  width: min(100%, 26.25rem);
}

.about__card img {
  width: 100%;
  height: auto;
  aspect-ratio: 1200 / 1481;
  object-fit: cover;
  border-radius: var(--dd-radius-md);
}

/* Dave's words: two short paragraphs at a narrow centred measure, then
   the pull line, one step up (large) in full white, split evenly */
.about__bio {
  display: grid;
  gap: var(--dd-space-5);
  max-width: 35rem;
  line-height: 1.6;
  color: var(--dd-white-a86);
  text-wrap: pretty;
}

.about__pull {
  max-width: 35rem;
  font-size: var(--dd-size-large);
  font-weight: 600;
  line-height: 1.4;
  color: var(--dd-white);
  text-wrap: balance;
}

.creds {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--dd-space-4);
  width: min(100%, var(--dd-measure));
  padding-bottom: 0.3125rem;
}

.cred {
  display: grid;
  align-content: start;
  justify-items: center;
  text-align: center;
  gap: var(--dd-space-2);
  padding: var(--dd-space-4);
  border: var(--dd-stroke-ink) solid var(--dd-navy);
  border-radius: var(--dd-radius-card);
  background: var(--dd-white);
  color: var(--dd-navy);
  box-shadow: var(--dd-shadow-lip);
}

.cred b {
  font-family: var(--dd-font-display);
  font-size: var(--dd-size-display);
  font-weight: 800;
  line-height: 1;
}

.cred span {
  font-weight: 600;
  line-height: 1.3;
  text-wrap: balance;
  color: var(--dd-navy-a78);
}

.about__voice {
  color: var(--dd-fg-2);
  text-wrap: balance;
}

.about__voice .text-link {
  color: var(--dd-white);
}

/* The career line: quiet, not a resume. Desktop: five equal columns on one
   hairline across the measure, year above, dot on the line, label below;
   the last dot (now) is doodle yellow. Phone: the same list running down a
   vertical hairline, left-aligned inside a centred block. The line draws
   in (600ms ease-out) as the list scrolls in; the entries fade up on the
   usual stagger. */
.career {
  /* 720, a touch past the 640 measure: at 640 the longer labels need 3 lines */
  width: min(100%, 45rem);
  /* keys to timeline 48 (the stack gap is already between them) */
  margin-top: calc(var(--dd-space-12) - var(--dd-stack));
  margin-bottom: calc(var(--dd-space-10) - var(--dd-stack));
}

.timeline {
  --tl-year: 0.9375rem;
  --tl-gap: var(--dd-space-3);
  --tl-dot: 0.625rem;
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0;
}

/* the hairline, from the first dot to the last */
.timeline::before {
  content: '';
  position: absolute;
  left: 10%;
  right: 10%;
  top: calc(var(--tl-year) + var(--tl-gap) + var(--tl-dot) / 2 - 0.5px);
  height: 1px;
  background: var(--dd-white-a24);
  transform-origin: 0 50%;
}

.js .timeline[data-reveal] {
  opacity: 1;
  translate: none;
  filter: none;
}

.js .timeline::before {
  scale: 0 1;
  transition: scale 600ms var(--dd-ease-out);
}

.js .timeline.is-in::before {
  scale: 1 1;
}

.timeline__item {
  display: grid;
  justify-items: center;
  align-content: start;
  gap: var(--tl-gap);
  text-align: center;
}

.timeline__year {
  font-family: var(--dd-font-display);
  font-size: var(--tl-year);
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0;
}

.timeline__dot {
  position: relative;
  width: var(--tl-dot);
  height: var(--tl-dot);
  border-radius: var(--dd-radius-md);
  background: var(--dd-white);
}

.timeline__item--now .timeline__dot {
  background: var(--dd-doodle);
}

.timeline__label {
  font-size: 0.9375rem;
  line-height: 1.35;
  color: var(--dd-white-a86);
  text-wrap: balance;
}

@media (prefers-reduced-motion: reduce) {
  .js .timeline::before {
    scale: 1 1;
    transition: none;
  }
}

@media (max-width: 640px) {
  .career {
    width: auto;
    margin-top: calc(var(--dd-space-10) - var(--dd-stack));
  }
  .timeline {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--dd-space-4);
    max-width: 20rem;
    margin-inline: auto;
    text-align: left;
  }
  .timeline::before {
    left: calc(var(--tl-dot) / 2 - 0.5px);
    right: auto;
    /* dot centre of the first row to dot centre of the last */
    top: 0.625rem;
    bottom: 0.625rem;
    width: 1px;
    height: auto;
    transform-origin: 50% 0;
  }
  .js .timeline::before {
    scale: 1 0;
  }
  .js .timeline.is-in::before {
    scale: 1 1;
  }
  .timeline__item {
    grid-template-columns: var(--tl-dot) 3.25rem minmax(0, 1fr);
    align-items: start;
    justify-items: start;
    column-gap: var(--dd-space-3);
    text-align: left;
  }
  /* every part of a row sits on the label's first 20px line */
  .timeline__dot {
    grid-column: 1;
    grid-row: 1;
    margin-top: calc((1.25rem - var(--tl-dot)) / 2);
  }
  .timeline__year {
    grid-column: 2;
    grid-row: 1;
    line-height: 1.25rem;
  }
  .timeline__label {
    grid-column: 3;
    grid-row: 1;
    line-height: 1.25rem;
    text-wrap: pretty;
  }
}

/* ---------------------------------------------------------------- footer */

/* The goodbye, on the same left edge: the room comes back behind it. */
.foot {
  padding-bottom: calc(var(--dd-space-8) + env(safe-area-inset-bottom));
}

.foot__line {
  color: var(--dd-fg-2);
}

/* footer beats: subline to email 32, email to socials 12, socials to © 40 */
.foot__keys {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--dd-space-4);
  margin-top: var(--dd-space-8);
}

/* the quiet second row: where else to find him */
.foot__social {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--dd-space-3);
  margin-top: var(--dd-space-3);
}

.foot__extra {
  display: grid;
  gap: var(--dd-space-2);
  margin-top: var(--dd-stack);
}

.foot__base {
  margin-top: var(--dd-space-10);
  color: var(--dd-fg-3);
}

/* ---------------------------------------------------------------- reveal */

/* Fades up out of a light blur, once, as it scrolls in. --i staggers. */
.js [data-reveal] {
  opacity: 0;
  translate: 0 var(--dd-reveal-y);
  filter: blur(var(--dd-reveal-blur));
  transition:
    opacity var(--dd-dur-reveal) var(--dd-ease-out),
    translate var(--dd-dur-reveal) var(--dd-ease-out),
    filter var(--dd-dur-reveal) var(--dd-ease-out);
  transition-delay: calc(var(--i, 0) * var(--dd-stagger));
}

.js [data-reveal].is-in {
  opacity: 1;
  translate: 0 0;
  filter: none;
}

/* a heading that says itself: each word rises a beat after the one before */
[data-words] .word {
  display: inline-block;
}

.js [data-words] .word {
  opacity: 0;
  translate: 0 var(--dd-reveal-y);
  filter: blur(var(--dd-reveal-blur));
  transition:
    opacity var(--dd-dur-reveal) var(--dd-ease-out),
    translate var(--dd-dur-reveal) var(--dd-ease-out),
    filter var(--dd-dur-reveal) var(--dd-ease-out);
  transition-delay: calc(var(--i, 0) * var(--dd-stagger) + var(--w, 0) * var(--dd-stagger-word));
}

.js [data-words].is-in .word {
  opacity: 1;
  translate: 0 0;
  filter: none;
}

/* ------------------------------------------------------------ preferences */

@media (prefers-reduced-motion: reduce) {
  .world__plate,
  .stage__card,
  .hero__side,
  .hero__dave {
    transform: none !important;
    opacity: 1 !important;
    filter: none !important;
  }
  .video--skeleton .video__thumb,
  .video--skeleton .bar {
    animation: none;
  }
}

@media (prefers-contrast: more) {
  [data-theme='navy'] {
    --dd-fg-2: var(--dd-white);
    --dd-fg-3: var(--dd-white);
  }
  .card,
  .cred {
    --dd-fg-2: var(--dd-navy);
  }
  .nav__links a {
    color: var(--dd-navy);
  }
  .world__plate {
    opacity: 0.4;
  }
}

@media (forced-colors: active) {
  .key,
  .card,
  .cred,
  .tile,
  .nav {
    border-color: CanvasText;
  }
  .world {
    display: none;
  }
}

/* ------------------------------------------------------------ responsive */

@media (max-width: 1080px) {
  .videos {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}


/* phones and tablets in portrait: Dave on top, cut at the chest with the
   courtroom behind him, the logo over his lower edge, then the line and
   the keys, all on the same left edge as the rest of the page */
@media (max-width: 900px) and (orientation: portrait), (max-width: 560px) {
  /* Phones and portrait tablets: one first screen that holds everything.
     Dave (whole, on his bar) 16px under the nav, the logo, the line, the
     key, and the top of the yellow band on the bottom edge. */
  .hero {
    /* at least 36svh, growing into whatever the screen has left over */
    --dave-h: clamp(36svh, calc(100svh - 29rem), 48svh);
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    min-height: 100svh;
    padding-top: calc(var(--dd-space-3) + var(--dd-nav-h) + var(--dd-space-4));
    padding-bottom: calc(var(--ticker-h, 2.75rem) / 2 + var(--dd-space-6));
  }
  .hero__lockup {
    flex-direction: column-reverse;
    gap: 0;
  }
  /* the logo sits under Dave's bar, never over it: white on white */
  .hero__logo {
    margin: calc(var(--dave-h) * 0.027 + 0.3125rem + var(--dd-space-6)) 0 0;
  }
  .hero {
    --logo-w: min(100%, 18.75rem);
  }
  /* everything stacked and centred again */
  .hero__side {
    width: 100%;
    margin-bottom: 0;
    justify-items: center;
    text-align: center;
  }
  .hero__logo img {
    width: min(78vw, 18.75rem);
  }
  .hero__copy {
    justify-items: center;
    margin-top: var(--dd-space-5);
    /* the .wrap around it already holds the gutter; only the notch insets
       here, so the line is not squeezed to 4 lines by a double gutter */
    padding-inline: env(safe-area-inset-left) env(safe-area-inset-right);
    box-sizing: border-box;
  }
  .hero .hero__lede {
    max-width: min(var(--dd-measure), 100%);
  }
  .hero__actions {
    justify-content: center;
    margin-top: var(--dd-space-5);
  }
}

@media (max-width: 760px) {
  /* on a phone only Request stays: it is a page of its own, not a scroll */
  .nav__links a:not(.nav__request) {
    display: none;
  }
}

@media (max-width: 640px) {
  /* phone rhythm: generous, and the gap between parts clearly bigger than
     anything inside one */
  :root {
    --dd-gutter: 20px;
    --dd-rhythm: 6.5rem;
    --dd-head-gap: 2rem;
    --dd-stack: 1.75rem;
    --dd-card-pad: 1rem;
    --dd-radius-card: 1.75rem;
    --dd-nav-h: 3.5rem;
    --dd-key-h-sm: 2.75rem;
  }
  body {
    line-height: 1.6;
  }
  .videos {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--dd-space-6);
  }
  /* every primary key: its own width, centred, never thinner than 240 */
  .key:not(.key--sm):not(.key--quiet):not(.stage__play) {
    min-width: 15rem;
    font-size: 1.0625rem;
  }
  .hero .hero__lede {
    font-size: var(--dd-size-body);
  }
  /* room above the things the phone doodles sit on */
  .count__row,
  .about__photo {
    margin-top: max(0px, var(--dd-room-top, 2.5rem) - var(--dd-head-gap));
  }
  /* the compact phone nav: 56 tall, 44 key */
  .nav {
    --pad: 0.375rem;
  }
  .nav__mark svg {
    height: auto;
    width: 1.875rem;
  }
  .nav__links a {
    font-size: 1rem;
  }
  .nav .key--sm {
    padding-inline: var(--dd-space-3);
    font-size: var(--dd-size-small);
  }
  .nav .key--sm .key__yt {
    width: 1.25rem;
    height: 0.875rem;
  }
  .stage__play {
    left: var(--dd-space-3);
    bottom: var(--dd-space-3);
  }
  .stage__caption {
    padding: var(--dd-space-4) var(--dd-space-2) var(--dd-space-2);
  }
  .tiles {
    --tile-w: 3rem;
    --tile-h: 4rem;
  }
  /* the same three career keys, tighter */
  .about__photo {
    width: min(100%, 20rem);
  }
  .creds {
    gap: var(--dd-space-2);
  }
  .cred {
    padding: var(--dd-space-3);
  }
  .cred b {
    font-size: 1.625rem;
  }
  .cred span {
    font-size: 0.90625rem;
  }
  /* footer beats x0.85 */
  .head-title:has(+ .foot__line) {
    margin-bottom: 0.875rem;
  }
  .foot__keys {
    margin-top: 1.6875rem;
  }
  .foot__social {
    margin-top: 0.625rem;
  }
  .foot__base {
    margin-top: 2.125rem;
  }
}

/* Phones under 600: one notch smaller than the tablet-phone scale above
   (Mees on a real iPhone). Same ratios, smaller sizes. */
@media (max-width: 599.98px) {
  :root {
    --dd-size-display: 1.625rem;
    --dd-size-large: 1.1875rem;
    --dd-size-body: 1.0625rem;
    --dd-size-small: 0.875rem;
    --dd-key-h: 3.25rem;
    --dd-nav-h: 3.25rem;
    --dd-key-h-sm: 2.5rem;
    --dd-rhythm: 6rem;
  }
  .nav {
    width: calc(100% - 1.5rem);
    --pad: 0.375rem;
  }
  .nav__mark svg {
    width: 1.625rem;
  }
  .nav__links a {
    font-size: 0.9375rem;
  }
  .nav .key--sm {
    padding-inline: 0.875rem;
    font-size: 0.875rem;
  }
  .nav .key--sm .key__yt {
    width: 1.125rem;
    height: 0.8125rem;
  }
  /* the group is smaller than the screen now: centre it between the nav
     (at least 16px under it) and the band */
  .hero {
    --dave-h: min(32svh, 15rem);
    --logo-w: min(100%, 15rem);
    justify-content: center;
  }
  .hero__logo img {
    width: min(70vw, 15rem);
  }
  .hero .hero__lede {
    font-size: 1.0625rem;
    line-height: 1.5;
  }
  .key:not(.key--sm):not(.key--quiet):not(.stage__play) {
    font-size: 1rem;
  }
  .key.key--quiet {
    min-height: var(--dd-key-h);
    font-size: 0.9375rem;
  }
  .stage__play {
    min-height: var(--dd-key-h);
    font-size: 1rem;
  }
  .about__pull {
    font-size: 1.1875rem;
  }
}

/* the narrowest phones: the nav keeps both words, the YouTube mark goes */
@media (max-width: 350px) {
  .nav__sub .key__yt {
    display: none;
  }
  .nav__links {
    margin-right: 0;
  }
  .nav__links .nav__request {
    padding-inline: var(--dd-space-2);
  }
}

@media (max-width: 340px) {
  .creds {
    grid-template-columns: minmax(0, 1fr);
    width: min(100%, 16rem);
  }
}

@media (max-width: 380px) {
  .key {
    padding-inline: var(--dd-space-4);
  }
  .key--sm {
    padding-inline: var(--dd-space-3);
  }
  .tiles {
    --tile-w: 2.625rem;
    --tile-h: 3.5rem;
    gap: var(--dd-space-1);
  }
}

/* landscape phones: little height, so Dave is sized from the height */
@media (max-height: 520px) and (orientation: landscape) {
  .hero {
    --dave-h: 70svh;
    min-height: auto;
  }
  .hero {
    --logo-w: min(38vw, 20rem);
  }
}

/* ------------------------------------------------------------------- 404 */

.lost {
  display: grid;
  align-content: center;
  text-align: center;
  min-height: 100svh;
  padding-block: var(--dd-space-16);
}

.lost .wrap {
  display: grid;
  justify-items: center;
}

.lost__logo {
  margin-bottom: var(--dd-head-gap);
}

.lost__logo img {
  width: 18rem;
  height: auto;
}

.lost .head-title {
  margin-bottom: var(--dd-stack);
}

.lost__line {
  max-width: 30em;
  margin-bottom: var(--dd-stack);
  font-size: var(--dd-size-large);
  color: var(--dd-fg-2);
}
