/* ───────────────────────────────────────────────────────────
   Black, white and grey. A framed column between rules, a sticky
   top bar and section bands. Every edge is square.
   ─────────────────────────────────────────────────────────── */

:root {
  color-scheme: dark;
  --bg: #000;
  --bg-2: #0a0a0a;
  --ink: #e4e4e4;
  --ink-hi: #ffffff;
  --text: #bdbdbd;
  --muted: #8a8a8a;
  --link: #5aa9ff;
  --line: rgba(255, 255, 255, 0.14);
  --line-strong: rgba(255, 255, 255, 0.34);
  --accent: #b5b5b5;

  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --frame: 1240px;
  --pad: clamp(18px, 4vw, 44px);
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --topbar: 64px;
}

*, *::before, *::after { box-sizing: border-box; border-radius: 0; }
html { scroll-behavior: smooth; scroll-padding-top: calc(var(--topbar) + 12px); -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
/* The gutters: a slow-drifting guilloche behind the frame. It moves by one 160x80 tile per loop, on the compositor. */
body::before {
  content: '';
  position: fixed;
  inset: -80px 0 0 -160px;
  z-index: -1;
  background: url('assets/guilloche.svg') 0 0 / 160px 80px;
  opacity: 0.07;
  animation: drift 22.5s linear infinite;
}
@keyframes drift { to { transform: translate3d(160px, 80px, 0); } }

::selection { background: var(--ink); color: var(--bg); }
a { color: var(--ink); text-decoration: none; }
a:hover { color: var(--ink-hi); }
img { max-width: 100%; }
h1, h2, h3, p, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.skip { position: absolute; left: -999px; top: 8px; z-index: 100; padding: 8px 14px; background: var(--ink); color: var(--bg); }
.skip:focus { left: 8px; }

.label {
  font: 500 11px/1.2 var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ───────── top bar ───────── */
.topbar {
  position: sticky; top: 0; z-index: 50; height: var(--topbar);
  background: rgba(0, 0, 0, 0.88); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line-strong);
}
.topbar__inner {
  max-width: var(--frame); height: 100%; margin: 0 auto; padding: 0 var(--pad);
  display: flex; align-items: center; gap: 28px; border-inline: 1px solid var(--line-strong);
}
.brand { white-space: nowrap; font: 500 17px/1 var(--sans); color: var(--ink); letter-spacing: -0.01em; }
.brand:hover { color: #fff; }
.topnav { margin-left: auto; display: flex; gap: 4px; }
.topnav a { position: relative; padding: 8px 12px; font: 500 14px/1 var(--sans); color: var(--muted); transition: color 0.25s; }
.topnav a::after {
  content: ''; position: absolute; left: 12px; right: 12px; bottom: 2px; height: 2px; background: #fff;
  transform: scaleX(0); transform-origin: left; transition: transform 0.35s var(--ease);
}
.topnav a:hover, .topnav a.is-active { color: #fff; }
.topnav a.is-active::after { transform: scaleX(1); }

/* ───────── frame: a column between rules, with a double-rule border ───────── */
.frame {
  position: relative;
  max-width: var(--frame); margin: 0 auto;
  background: var(--bg);
  border-inline: 1px solid var(--line-strong);
  min-height: 100vh;
  /* Hidden pop-ups near an edge and the zooming hero would otherwise widen the page, so phones could
     scroll sideways. clip (unlike hidden) makes no scroll box, so vertical overflow and sticky still work. */
  overflow-x: clip;
}
.frame::before, .frame::after {
  content: ''; position: absolute; top: 0; bottom: 0; width: 1px; background: var(--line); pointer-events: none; z-index: 3;
}
.frame::before { left: 6px; }
.frame::after { right: 6px; }

/* ───────── hero ───────── */
.hero { position: relative; aspect-ratio: 21 / 7; overflow: hidden; background: var(--bg); }
.hero__stack { position: absolute; inset: 0; -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 100%); mask-image: linear-gradient(to bottom, #000 72%, transparent 100%); }
.hero__stack img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transform: scale(1.04);
  transition: opacity 1.6s ease;
}
.hero__stack img.is-on { opacity: 1; animation: kenburns 24s ease-in-out infinite alternate; }
@keyframes kenburns { from { transform: scale(1.04) translate3d(0, 0, 0); } to { transform: scale(1.1) translate3d(-1.2%, -0.8%, 0); } }

/* ───────── sections ───────── */
.band {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px var(--pad);
  border-top: 1px solid var(--line-strong); border-bottom: 1px solid var(--line-strong);
  background:
    repeating-linear-gradient(135deg, transparent 0 7px, rgba(255, 255, 255, 0.07) 7px 8px),
    var(--bg-2);
}
.band h2 { font: 400 13px/1 var(--mono); letter-spacing: 0.08em; text-transform: lowercase; color: var(--ink); }
.band h2::before { content: '/ '; color: var(--muted); }
.band__tag {
  font: 500 clamp(26px, 3.4vw, 32px)/1 var(--sans);
  color: transparent; -webkit-text-stroke: 1px var(--ink); letter-spacing: 0.04em;
}
.block__body { padding: 34px var(--pad) 56px; }
.subhead { margin: 44px 0 18px; font: 400 13px/1 var(--mono); letter-spacing: 0.08em; text-transform: lowercase; color: var(--ink); }
.subhead::before { content: '/ '; color: var(--muted); }

/* about */
.identity { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 28px; }
.identity__name { font: 500 28px/1.15 var(--sans); color: #fff; letter-spacing: -0.02em; }
.identity__meta { margin: 8px 0 0; font: 400 15px/1.5 var(--sans); color: var(--muted); font-variant-numeric: tabular-nums; }
.prose p, .pronounce { margin-bottom: 20px; max-width: 64ch; font: 400 15px/1.7 var(--sans); color: #9c9c9c; }
.pronounce { margin: 4px 0 0; }
.prose a, .textlink {
  padding: 0; font: inherit; color: var(--link); background: none; border: 0; cursor: pointer;
  text-decoration: underline; text-decoration-color: rgba(90, 169, 255, 0.45); text-underline-offset: 3px;
  transition: color 0.2s, text-decoration-color 0.2s;
}
.prose a:hover, .textlink:hover { color: #fff; text-decoration-color: #fff; }
.prose mark { padding: 1px 6px; color: #ff6b5e; background: rgba(255, 90, 77, 0.16); }

/* about copy: brand logos */
.prose a.brand { white-space: nowrap; text-decoration: none; }
.brand__logo { display: inline-block; width: 1.1em; height: 1.1em; margin-right: 0.32em; vertical-align: -0.2em; object-fit: contain; transition: transform 0.45s var(--spring); }
.brand__name { text-decoration: underline; text-decoration-color: rgba(90, 169, 255, 0.45); text-underline-offset: 3px; transition: text-decoration-color 0.2s; }
.brand:hover .brand__name { text-decoration-color: #fff; }
.brand:hover .brand__logo { transform: rotate(-12deg) scale(1.25); }

/* about copy: buttons that read as words */
.popw__trigger, .buks, .pun { padding: 0; font: inherit; color: var(--ink); text-align: inherit; background: none; border: 0; cursor: pointer; }

/* about copy: phrases that open a card above them (below if there's no room). src/about.js sets .is-shown on
   the wrapper on hover, keyboard focus or tap, and every effect keys off it. --dir is 1 above, -1 below.
   A variant styles itself through --from / --to (the card's hidden and shown transforms), --gap, and the
   trigger colours --tc / --tu / --tc-on. */
.prose p { position: relative; }
.popw { position: relative; display: inline-block; --dir: 1; }
.popw.is-below { --dir: -1; }
.popw__trigger {
  color: var(--tc, var(--ink));
  text-decoration: underline dotted; text-decoration-color: var(--tu, rgba(255, 255, 255, 0.4)); text-underline-offset: 4px;
  transition: color 0.2s, text-decoration-color 0.2s;
}
.popw.is-shown .popw__trigger { color: var(--tc-on, #fff); text-decoration-color: var(--tc-on, #fff); }
.pop {
  position: absolute; left: 50%; bottom: calc(100% + var(--gap, 14px)); z-index: 30; display: block;
  translate: calc(-50% + var(--dx, 0px)) 0; text-align: left; white-space: normal;
  opacity: 0; visibility: hidden; pointer-events: none; transform-origin: 50% 100%;
  transform: var(--from, translateY(calc(var(--dir) * 10px)) scale(0.94));
  transition: opacity 0.18s, transform 0.45s var(--spring), visibility 0s 0.45s;
}
.popw.is-below .pop { bottom: auto; top: calc(100% + var(--gap, 14px)); transform-origin: 50% 0; }
/* A bridge over the gap, so the pointer can move from the phrase onto the card without it closing. */
.pop::after { content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 16px; }
.popw.is-below .pop::after { top: auto; bottom: 100%; }
.popw.is-shown .pop { opacity: 1; visibility: visible; pointer-events: auto; transform: var(--to, none); transition-delay: 0s; }

/* cities: each name in its own colour, popping up a postage stamp */
.place__name { --tc: var(--c); --tu: color-mix(in srgb, var(--c) 50%, transparent); --tc-on: var(--c); }
.popw.is-shown .place__name { text-decoration-style: solid; }
.pop--stamp {
  width: 128px; filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.7));
  --from: translateY(calc(var(--dir) * 12px)) rotate(calc(var(--dir) * -10deg)) scale(0.88); --to: rotate(-3deg);
}
.stamp__face {
  position: relative; display: grid; grid-template-rows: auto 1fr auto auto; height: 152px; padding: 12px 11px 11px;
  color: #161616; background: #efece3; box-shadow: inset 0 0 0 5px #efece3, inset 0 0 0 6px rgba(0, 0, 0, 0.5);
}
/* Perforations: a dotted border in the page colour, half over the paper's edge. */
.stamp__face::before { content: ''; position: absolute; inset: -3px; border: 6px dotted var(--bg); pointer-events: none; }
.stamp__value { justify-self: end; font: 600 12px/1 var(--mono); letter-spacing: 0.04em; }
.stamp__emblem { place-self: center; font-size: 44px; line-height: 1; }
.stamp__nick { font: italic 600 16px/1.1 Georgia, 'Times New Roman', serif; text-align: center; }
.stamp__name { margin-top: 5px; font: 500 8px/1 var(--mono); letter-spacing: 0.24em; text-transform: uppercase; text-align: center; opacity: 0.65; }
.stamp__postmark {
  position: absolute; top: 26px; right: -8px; display: grid; place-items: center; width: 56px; height: 56px;
  font: 700 10px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: rgba(196, 40, 40, 0.92);
  border: 2px solid currentColor; border-radius: 50%; outline: 1px solid currentColor; outline-offset: -7px;
  rotate: 16deg; opacity: 0; scale: 1.7; transition: opacity 0.15s 0.2s, scale 0.3s 0.2s cubic-bezier(0.5, 0, 0.75, 0);
}
.popw.is-shown .stamp__postmark { opacity: 1; scale: 1; }

/* list cards (saxophone exams, scholarships): rows sliding in one by one */
.pop--card { width: min(372px, calc(100vw - 40px)); padding: 16px; color: var(--text); background: #0b0b0b; border: 1px solid var(--line-strong); box-shadow: 0 16px 40px rgba(0, 0, 0, 0.6); }
.card__head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.card__logo { display: grid; place-items: center; flex: none; width: 40px; height: 40px; font-size: 22px; background: #161616; box-shadow: inset 0 0 0 1px var(--line); }
.card__titles { display: grid; gap: 3px; min-width: 0; }
.card__title { font: 500 15px/1.25 var(--sans); color: #fff; }
.card__sub { font: 400 12px/1.35 var(--sans); color: var(--muted); }
.card__row {
  display: grid; grid-template-columns: [meta] auto [label] minmax(0, 1fr) [tag] auto; align-items: center; gap: 10px; padding: 7px 0;
  font: 400 13px/1.3 var(--sans); border-top: 1px solid var(--line);
  opacity: 0; transform: translateX(-6px); transition: opacity 0.3s, transform 0.4s var(--ease); transition-delay: calc(var(--i) * 45ms + 80ms);
}
.popw.is-shown .card__row { opacity: 1; transform: none; }
/* Rows without a year drop that column, so they line up with the card's edge. */
.card__row:not(:has(.card__meta)) { grid-template-columns: [label] minmax(0, 1fr) [tag] auto; }
.card__meta { grid-column: meta; min-width: 36px; font: 400 12px/1 var(--mono); color: var(--muted); font-variant-numeric: tabular-nums; }
.card__label { grid-column: label; color: var(--ink); }
.card__prefix { font: 600 10px/1 var(--mono); letter-spacing: 0.06em; color: var(--muted); }
.card__tag { grid-column: tag; padding: 4px 6px; font: 600 9px/1 var(--mono); letter-spacing: 0.1em; text-transform: uppercase; border: 1px solid currentColor; }
.card__tag--gold { color: #f0c75e; }
.card__tag--silver { color: #c9d1db; }
.card__tag--bronze { color: #c9905f; }

/* "Temple School": its Instagram posts fan out above the name like an umbrella opening. No card, just photos. */
.fan__name { --tc: #f0c75e; --tu: rgba(240, 199, 94, 0.5); --tc-on: #ffd97a; }
/* Round crop: the crest is a circle, and this hides the corners of an image without transparency. */
.fan__crest { display: inline-block; width: 1.05em; height: 1.05em; margin-right: 0.3em; vertical-align: -0.2em; border-radius: 50%; transition: transform 0.5s var(--spring); }
.popw.is-shown .fan__crest { transform: rotate(-20deg) scale(1.12); }
.pop--fan { width: 330px; height: 124px; --gap: 6px; --from: none; }
.fan__post {
  position: absolute; left: 50%; bottom: 0; width: 84px; margin-left: -42px; aspect-ratio: 4 / 5; padding: 4px 4px 14px;
  background: #efece3; box-shadow: 0 10px 24px rgba(0, 0, 0, 0.65);
  opacity: 0; transform-origin: 50% calc(50% + var(--dir) * 110%); transform: translateY(calc(var(--dir) * 26px)) scale(0.5);
  transition: transform 0.55s var(--spring), opacity 0.2s, translate 0.25s var(--ease);
  transition-delay: calc(var(--i) * 45ms);
}
.popw.is-below .fan__post { top: 0; bottom: auto; }
.popw.is-shown .fan__post {
  opacity: 1; transform: translateX(calc(var(--k) * 80px)) translateY(calc(var(--dir) * var(--k) * var(--k) * 12px)) rotate(calc(var(--dir) * var(--k) * 14deg));
}
.fan__post:nth-child(2) { z-index: 1; }
.fan__post:hover { translate: 0 -8px; }
.fan__post img { display: block; width: 100%; height: 100%; object-fit: cover; background: #141414; }
.fan__badge { position: absolute; right: 8px; bottom: 18px; display: grid; color: #fff; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.8)); }

/* Texas to Atlanta: a plane flies between the two words, drawing its trail, and drops a pin */
.route--from { color: #fff; }
.route--to { color: #ffb38a; transition: text-shadow 0.4s; }
.route--to.is-landed { text-shadow: 0 0 14px rgba(255, 179, 138, 0.85); }
.flight { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; z-index: 2; transition: opacity 0.9s; }
.flight path { fill: none; stroke: rgba(255, 255, 255, 0.45); stroke-width: 1.2; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.flight.is-out { opacity: 0; }
.flight__plane { position: absolute; left: 0; top: 0; z-index: 3; font-size: 16px; line-height: 1; pointer-events: none; will-change: transform; }
.flight__pin { position: absolute; z-index: 3; font-size: 15px; line-height: 1; translate: -50% -100%; pointer-events: none; opacity: 0; transform: translateY(-16px); transition: opacity 0.2s, transform 0.5s var(--spring); }
.flight__pin.is-in { opacity: 1; transform: none; }

/* "Buks" reads "Books" on hover or tap */
.buks { display: inline-flex; align-items: baseline; border-bottom: 1px dotted rgba(255, 255, 255, 0.4); }
.buks__u, .buks__oo { display: inline-block; overflow: hidden; white-space: nowrap; transition: max-width 0.4s var(--ease), opacity 0.25s, transform 0.45s var(--spring); }
.buks__u { max-width: 0.7em; }
.buks__oo { max-width: 0; opacity: 0; color: #ffd36b; transform: translateY(0.5em); }
.buks:is(:hover, .is-on, :focus-visible) .buks__u { max-width: 0; opacity: 0; transform: translateY(-0.5em); }
.buks:is(:hover, .is-on, :focus-visible) .buks__oo { max-width: 1.3em; opacity: 1; transform: none; }

/* the family nickname: a redaction bar that scrambles and never tells */
.secret {
  display: inline-block; min-width: 7.4em; height: 1.3em; padding: 0 0.45em; vertical-align: -0.22em; overflow: hidden;
  font: 500 0.88em/1.3em var(--mono); color: transparent; background: var(--ink); border: 0; cursor: pointer;
  transition: background 0.2s, color 0.2s;
}
.secret.is-open { color: #ff8a7f; background: #1a1a1a; box-shadow: inset 0 0 0 1px var(--line-strong); animation: nope 0.4s; }
/* Hidden with opacity, not just a transparent colour: emoji are drawn in colour and ignore `color`. */
.secret__text { white-space: nowrap; opacity: 0; transition: opacity 0.2s; }
.secret.is-open .secret__text { opacity: 1; }
@keyframes nope { 20%, 60% { transform: translateX(-3px); } 40%, 80% { transform: translateX(3px); } }

/* about copy: a dream crossed out, with the correction written above */
.strike { position: relative; display: inline-block; white-space: nowrap; }
.strike__mark { position: relative; display: inline-block; }
.strike__text { transition: color 0.5s 0.45s; }
.strike.is-drawn .strike__text { color: var(--muted); }
.strike__line { position: absolute; left: -3%; top: 52%; width: 106%; height: 0.6em; translate: 0 -50%; overflow: visible; pointer-events: none; }
.strike__line path { fill: none; stroke: #ff6b5e; stroke-width: 1.7; stroke-linecap: round; vector-effect: non-scaling-stroke; stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 0.8s ease-in-out; }
.strike.is-drawn .strike__line path { stroke-dashoffset: 0; }
.strike__note {
  position: absolute; left: 50%; bottom: 78%; translate: -50% 0; rotate: -4deg; white-space: nowrap;
  font: 600 22px/1 'Caveat', 'Bradley Hand', cursive; color: #ff8a7f; text-shadow: 0 0 6px var(--bg), 0 0 2px var(--bg);
  opacity: 0; transform: translateY(5px); transition: opacity 0.4s 0.8s, transform 0.4s 0.8s var(--ease);
}
.strike.is-drawn .strike__note { opacity: 1; transform: none; }

/* about copy: "books" lifts the covers beside it */
.pun {
  text-decoration: underline wavy; text-decoration-color: rgba(255, 255, 255, 0.35); text-decoration-thickness: 1px; text-underline-offset: 4px;
  transition: color 0.2s, text-decoration-color 0.2s;
}
.pun:hover { color: #fff; text-decoration-color: #fff; }
.pun__emoji { display: inline-block; transition: transform 0.4s var(--spring); }
.pun:hover .pun__emoji, .is-books .pun__emoji { transform: translateY(-2px) rotate(-12deg) scale(1.15); }
.reading .cover--lg, .fav .cover { transition: transform 0.45s var(--spring); transition-delay: calc(var(--i, 0) * 60ms + 60ms); }
.is-books .reading .cover--lg { transform: translateY(-6px) rotate(-3deg); transition-delay: 0ms; }
.is-books .fav .cover { transform: translateY(-10px) rotate(-4deg); }
.is-books .favs li:nth-child(even) .fav .cover { transform: translateY(-10px) rotate(4deg); }

/* about: copy on the left, listening and reading on the right */
.about { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 44px; align-items: start; }
.about__side { display: grid; gap: 34px; padding-left: 32px; border-left: 1px solid var(--line); }
.side__label { padding-bottom: 12px; margin-bottom: 16px; border-bottom: 1px solid var(--line); font: 400 13px/1 var(--mono); letter-spacing: 0.08em; color: var(--muted); }
.side__sub, .side__kicker { font: 500 11px/1 var(--mono); letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
.side__sub { margin: 22px 0 12px; }
.side__kicker { display: block; margin-bottom: 6px; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* now playing: album art with a record that slides out and spins while a song is on */
.np { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 0 14px; color: inherit; }
.np:hover { color: inherit; }
.np__art { position: relative; width: 72px; height: 72px; margin-right: 0; transition: margin-right 0.6s var(--ease); }
.np.is-playing .np__art { margin-right: 30px; }
.np__art img { position: relative; z-index: 1; display: block; width: 100%; height: 100%; object-fit: cover; background: #141414; box-shadow: 0 0 0 1px var(--line); }
.np.is-empty .np__art img, .np.is-loading .np__art img { visibility: hidden; }
.np.is-empty .np__art, .np.is-loading .np__art { background: repeating-linear-gradient(135deg, transparent 0 7px, rgba(255, 255, 255, 0.07) 7px 8px), #0d0d0d; box-shadow: 0 0 0 1px var(--line); }
.np__disc {
  position: absolute; inset: 3px; border-radius: 50%;
  background: repeating-radial-gradient(circle, #121212 0 1.2px, #1f1f1f 1.2px 2.4px);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
  translate: 0 0; transition: translate 0.6s var(--ease);
  animation: spin 2.4s linear infinite paused;
}
.np__disc::after { content: ''; position: absolute; inset: 34%; border-radius: 50%; background: var(--art, #ddd) center / cover, #ddd; box-shadow: 0 0 0 2px #0a0a0a; }
.np.is-playing .np__disc { translate: 30px 0; animation-play-state: running; }
@keyframes spin { to { rotate: 360deg; } }

.np__text { display: grid; gap: 3px; min-width: 0; }
.np__status { display: inline-flex; align-items: center; gap: 7px; margin-bottom: 3px; font: 500 11px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.np__bars { display: none; align-items: flex-end; gap: 2px; height: 10px; }
.np.is-playing .np__bars { display: inline-flex; }
.np__bars i { width: 2px; height: 100%; background: #1ed760; transform-origin: bottom; animation: eq 0.9s ease-in-out infinite alternate; }
.np__bars i:nth-child(2) { animation-delay: -0.3s; animation-duration: 0.7s; }
.np__bars i:nth-child(3) { animation-delay: -0.6s; animation-duration: 1.1s; }
@keyframes eq { from { transform: scaleY(0.25); } to { transform: scaleY(1); } }
.np.is-playing .np__status { color: #1ed760; }
.np__title, .np__artist { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Titles and bylines in the column: the song and the book share one look. */
.np__title, .reading__title { font: 500 15px/1.3 var(--sans); color: #f2f2f2; transition: color 0.2s; }
.np__artist, .reading__author { font: 400 14px/1.3 var(--sans); color: var(--muted); }
.np:hover .np__title, a.reading:hover .reading__title { color: var(--link); }
.np.is-loading .np__title, .np.is-loading .np__artist { width: 70%; color: transparent; background: #161616; }
.np.is-loading .np__artist { width: 45%; }
.np__logo { align-self: start; color: #1ed760; }
.np__timeline { grid-column: 1 / -1; display: none; align-items: center; gap: 10px; margin-top: 14px; font: 400 11px/1 var(--mono); color: var(--muted); font-variant-numeric: tabular-nums; }
.np.is-playing .np__timeline { display: flex; }
.np__progress { flex: 1; height: 2px; background: var(--line); overflow: hidden; }
.np__progress span, .meter span { display: block; height: 100%; background: var(--ink); transform: scaleX(var(--p, 0)); transform-origin: left; transition: transform 1s linear; }

/* books */
.cover { position: relative; display: block; aspect-ratio: 2 / 3; overflow: hidden; background: #141414; box-shadow: 0 0 0 1px var(--line); }
.cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cover--lg { width: 76px; flex: none; box-shadow: 0 0 0 1px var(--line), 6px 6px 0 rgba(255, 255, 255, 0.06); }
.cover--type { display: flex; flex-direction: column; justify-content: space-between; padding: 7px 6px; background: #efece3; color: #111; }
.cover__title { font: 600 9px/1.15 var(--sans); letter-spacing: -0.01em; }
.cover__author { font: 400 7px/1.2 var(--mono); text-transform: uppercase; letter-spacing: 0.08em; opacity: 0.7; }
.cover--lg .cover__title { font-size: 11px; }

.reading { display: flex; align-items: center; gap: 16px; color: inherit; }
.reading__text { display: grid; gap: 3px; min-width: 0; flex: 1; }
.reading__series { margin-top: 6px; font: 400 11px/1.3 var(--mono); letter-spacing: 0.04em; color: var(--muted); }
.meter { display: block; height: 2px; margin-top: 10px; background: var(--line); overflow: hidden; }
.reading__page { margin-top: 4px; font: 400 11px/1 var(--mono); color: var(--muted); font-variant-numeric: tabular-nums; }

.favs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px 16px; }
.fav { display: block; transition: transform 0.35s var(--ease); }
.fav:hover { transform: translateY(-5px) rotate(-2deg); }
.favs li:nth-child(even) .fav:hover { transform: translateY(-5px) rotate(2deg); }

.links { display: flex; flex-wrap: wrap; gap: 14px 18px; margin-top: 30px; }
.linkbtn {
  position: relative; display: inline-flex; align-items: center; gap: 9px; height: 42px; padding: 0 16px;
  font: 500 14px/1 var(--sans); color: var(--text); background: var(--bg); border: 0; cursor: pointer;
  transition: color 0.2s, background 0.2s;
}
.linkbtn svg { flex: none; }
.linkbtn__arrow { color: var(--muted); font-size: 13px; transition: transform 0.25s var(--ease); }
.linkbtn::before, .linkbtn::after { content: ''; position: absolute; pointer-events: none; border: 0 solid rgba(255, 255, 255, 0.34); transition: border-color 0.2s; }
.linkbtn::before { inset: 0 -7px; border-top-width: 1px; border-bottom-width: 1px; }
.linkbtn::after { inset: -7px 0; border-left-width: 1px; border-right-width: 1px; }
.linkbtn:hover { color: #fff; }
.linkbtn:hover::before, .linkbtn:hover::after { border-color: rgba(255, 255, 255, 0.7); }
.linkbtn:hover .linkbtn__arrow { transform: translate(2px, -2px); color: #fff; }
.linkbtn--solid { color: #0a0a0a; background: #efece3; padding: 0 20px; }
.linkbtn--solid::before, .linkbtn--solid::after { display: none; }
.linkbtn--solid:hover { color: #000; background: #fff; }

.sect-head { display: flex; align-items: center; justify-content: space-between; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
.sect-head__label { font: 400 13px/1 var(--mono); letter-spacing: 0.08em; color: var(--muted); }
.pillbtn {
  background: none; cursor: pointer; flex: none;
  display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 16px;
  font: 400 14px/1 var(--sans); color: var(--text); border: 1px solid var(--line-strong);
  transition: color 0.2s, border-color 0.2s;
}
.pillbtn:hover { color: #fff; border-color: rgba(255, 255, 255, 0.6); }

/* github chart */
.gh { margin-top: 44px; }
.gh__chart { margin-top: 22px; }
.gh__scroll { overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
.gh__scroll::-webkit-scrollbar { display: none; }
.gh__table {
  display: grid; gap: 3px; min-width: 640px;
  grid-template-columns: 34px repeat(var(--weeks), minmax(0, 1fr));
  grid-template-rows: 24px repeat(7, auto);
  font: 400 13px/1 var(--sans); color: var(--muted);
}
.gh__month { grid-row: 1; align-self: start; white-space: nowrap; }
.gh__day { grid-column: 1; display: flex; align-items: center; }
.gh__table i, .gh__legend i { display: block; aspect-ratio: 1; border-radius: 3px; background: #1b1b1b; }
.gh__table i[data-l='1'], .gh__legend i[data-l='1'] { background: #0f2f57; }
.gh__table i[data-l='2'], .gh__legend i[data-l='2'] { background: #17508f; }
.gh__table i[data-l='3'], .gh__legend i[data-l='3'] { background: #2a7bd6; }
.gh__table i[data-l='4'], .gh__legend i[data-l='4'] { background: #4da3ff; }
.gh__foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 18px; font: 400 14px/1 var(--sans); color: var(--muted); }
.gh__legend { display: inline-flex; align-items: center; gap: 5px; }
.gh__legend i { width: 14px; height: 14px; }
.gh__legend i:first-of-type { margin-left: 4px; }
.gh__legend i:last-of-type { margin-right: 4px; }

/* experience */
.exp { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; align-items: center; gap: 4px 14px; padding: 10px var(--pad); border-bottom: 1px solid var(--line); }
.exp__tile { display: grid; place-items: center; width: 40px; height: 40px; }
.exp__tile img { display: block; max-width: 100%; max-height: 100%; width: auto; height: auto; }
.exp__title { font: 400 13px/1.3 var(--sans); color: var(--muted); }
.exp__org { font: 600 16px/1.3 var(--sans); color: #f4f4f4; letter-spacing: -0.01em; }
.exp__when { font: 400 13px/1.3 var(--sans); color: var(--muted); white-space: nowrap; }

/* work */
.case { padding: 34px var(--pad) 40px; border-bottom: 1px solid var(--line-strong); }
.case:last-child { border-bottom: 0; }
.case__brand { display: flex; align-items: center; gap: 14px; margin-bottom: 8px; }
.case__logo { display: block; width: auto; height: 56px; }
.case__title { margin: 0; font: 500 26px/1.1 var(--sans); letter-spacing: -0.02em; color: #f2f2f2; }
.case__lede { margin: 14px 0 0; max-width: 62ch; font-size: 16px; line-height: 1.7; color: var(--text); }
.case__title a { color: var(--link); transition: color 0.2s; }
.case__title a:hover { color: #fff; }
.case__arrow { display: inline-block; margin-left: 6px; font-size: 0.75em; vertical-align: 0.15em; transition: transform 0.25s var(--ease); }
.case__title a:hover .case__arrow { transform: translate(2px, -2px); }

/* thoughts */
.essays { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 240px)); gap: 28px 24px; }
.essay { display: block; align-self: start; width: 100%; padding: 0; text-align: left; cursor: pointer; background: none; border: 0; color: inherit; }
.essay__img { position: relative; display: block; aspect-ratio: 1; margin-bottom: 12px; overflow: hidden; background: #0b0b0b; }
.essay__img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
.essay:hover .essay__img img { transform: scale(1.04); }
.essay__date { display: block; font: 400 13px/1.3 var(--sans); color: var(--muted); }
.essay__title { display: block; margin-top: 4px; font: 400 16px/1.4 var(--sans); color: #f2f2f2; transition: color 0.2s; }
.essay:hover .essay__title, .essay:focus-visible .essay__title { color: var(--link); }

.notes { position: relative; display: grid; gap: 22px; padding-left: 28px; }
.notes::before { content: ''; position: absolute; left: 4px; top: 6px; bottom: 6px; width: 1px; background: var(--line-strong); }
.note { position: relative; }
.note::before { content: ''; position: absolute; left: -28px; top: 6px; width: 9px; height: 9px; background: var(--bg); border: 1px solid var(--link); }
.note time { display: block; margin-bottom: 8px; font: 500 11px/1 var(--mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
.note p { max-width: 62ch; font-size: 15px; line-height: 1.65; margin-bottom: 8px; }

/* footer */
.footer { overflow: hidden; background: var(--bg); color: var(--ink); border-top: 1px solid var(--ink); }
.footer__bg { display: block; width: 100%; height: auto; pointer-events: none; -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 28%); mask-image: linear-gradient(to bottom, transparent 0%, #000 28%); }

/* ───────── popups ───────── */
dialog { color: var(--text); padding: 0; border: 0; background: none; max-width: none; max-height: none; }
dialog::backdrop { background: rgba(0, 0, 0, 0.78); backdrop-filter: blur(4px); }
.modal { margin: auto; width: min(860px, 94vw); max-height: 94vh; }
.modal--essay { width: min(780px, 94vw); }
.modal--globe { width: min(640px, 94vw); }
.modal[open] { animation: pop 0.4s var(--ease); }
@keyframes pop { from { opacity: 0; transform: translateY(18px) scale(0.97); } }
.modal__panel { position: relative; max-height: 94vh; overflow: auto; background: var(--bg); border: 1px solid var(--ink); box-shadow: 10px 10px 0 var(--ink); }
.modal--resume .modal__panel img { display: block; width: 100%; height: auto; }
.modal__close {
  position: sticky; top: 12px; z-index: 2; float: right; margin: 12px 12px -50px 0; display: grid; place-items: center; width: 38px; height: 38px;
  color: var(--bg); background: var(--ink); border: 0; cursor: pointer; transition: transform 0.3s var(--ease), background 0.25s;
}
.modal__close svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: square; }
.modal__close:hover { transform: rotate(90deg); background: var(--accent); }

.piece { padding: 52px clamp(22px, 5vw, 48px) 56px; }
.piece__kicker { display: block; margin-bottom: 14px; font: 500 11px/1 var(--mono); letter-spacing: 0.18em; text-transform: uppercase; color: var(--accent); }
.piece__title { font: 500 clamp(26px, 4vw, 34px)/1.15 var(--sans); color: var(--ink); letter-spacing: -0.02em; }
.piece__dek { margin: 16px 0 14px; font: 400 17px/1.5 var(--sans); color: var(--muted); }
.piece__date { display: block; font: 500 11px/1 var(--mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
.piece__head { padding-bottom: 28px; margin-bottom: 30px; border-bottom: 1px solid var(--line-strong); }
.piece__body { display: grid; gap: 20px; }
.piece__p { font-size: 16px; line-height: 1.75; color: var(--text); }
.piece__p strong { color: var(--ink); }
.piece__h { margin-top: 18px; font: 500 20px/1.25 var(--sans); letter-spacing: -0.01em; color: var(--ink); }
.piece__list { display: grid; gap: 10px; padding-left: 4px; }
.piece__list li { position: relative; padding-left: 22px; font-size: 16px; line-height: 1.7; }
.piece__list li::before { content: ''; position: absolute; left: 2px; top: 0.8em; width: 9px; height: 2px; background: var(--accent); }
.piece a { text-decoration: underline; text-decoration-color: var(--line-strong); text-underline-offset: 3px; }

.globe { padding: 28px clamp(18px, 4vw, 32px); }
.globe__canvas { display: block; width: 100%; aspect-ratio: 1; cursor: grab; touch-action: none; }
.globe__canvas:active { cursor: grabbing; }
.globe__title { margin-bottom: 4px; font: 500 20px/1.25 var(--sans); color: #fff; letter-spacing: -0.01em; }
.globe__list { margin-top: 6px; font: 400 14px/1.6 var(--sans); color: var(--muted); }

/* ───────── motion ───────── */
.js .reveal { opacity: 0; transform: translateY(16px); transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); transition-delay: calc(var(--i, 0) * 70ms); }
.js .reveal.is-in { opacity: 1; transform: none; }

/* ───────── responsive ───────── */
@media (max-width: 980px) {
  .about { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .about__side { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 34px 44px; padding: 34px 0 0; border-left: 0; border-top: 1px solid var(--line); }
}
@media (max-width: 860px) {
  :root { --topbar: 92px; }
  .topbar__inner { flex-wrap: wrap; align-content: center; gap: 4px 12px; padding-block: 8px; }
  .topnav { order: 3; flex: 1 0 100%; margin: 0 -8px; overflow-x: auto; scrollbar-width: none; }
  .topnav::-webkit-scrollbar { display: none; }
  .topnav a { flex: none; padding: 8px; font-size: 13px; }
  .topnav a::after { left: 8px; right: 8px; }
  .hero { aspect-ratio: 16 / 8; }
}
@media (max-width: 620px) {
  .essays { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .exp { grid-template-columns: 40px minmax(0, 1fr); }
  .exp__when { grid-column: 2; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  body::before, .hero__stack img.is-on, .np__disc, .np__bars i, .secret.is-open { animation: none; }
  .js .reveal { opacity: 1; transform: none; transition: none; }
  * { transition-duration: 0.01ms !important; }
}

/* 404 page */
.notfound { min-height: 100vh; }
.notfound .band h1 { font: 400 13px/1 var(--mono); letter-spacing: 0.08em; text-transform: lowercase; color: var(--ink); }
.notfound .band h1::before { content: '/ '; color: var(--muted); }
.notfound__text { margin-bottom: 28px; max-width: 48ch; font: 400 17px/1.6 var(--sans); color: var(--text); }
