/* josephali.com — OFF+BRAND system implementation.
   Tokens live in variables.css. This file only maps tokens to components.
   No shadows. No fills. Hairlines only. One chromatic event: the hero sphere. */

@import url("/assets/variables.css");

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  color-scheme: light;
}

body {
  margin: 0;
  background: var(--surface-parchment-canvas);
  color: var(--color-ink);
  font-family: var(--font-ataero-retina-ob-edition);
  font-size: var(--text-body);
  font-weight: var(--font-weight-regular);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img { max-width: 100%; height: auto; display: block; }

a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--ink-12);
  transition: border-color 260ms var(--ease), color 260ms var(--ease);
}
a:hover { border-bottom-color: var(--color-ink); }

:focus-visible {
  outline: 1px solid var(--color-ink);
  outline-offset: 4px;
  border-radius: var(--radius-links);
}

h1, h2, h3, h4 {
  margin: 0;
  font-weight: var(--font-weight-regular);
  text-wrap: balance;
}

p { margin: 0; }

.skip {
  position: absolute;
  left: var(--spacing-19);
  top: -120px;
  z-index: 999;
  background: var(--surface-paper);
  border: 1px solid var(--color-ink);
  padding: var(--spacing-8) var(--spacing-15);
  border-radius: var(--radius-links);
  font-size: var(--text-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  transition: top 240ms var(--ease);
}
.skip:focus { top: var(--spacing-19); }

/* ============================================================
   LAYOUT
   Page max 1400. Section rhythm 76–119px.
   ============================================================ */
.wrap {
  width: min(100% - (var(--spacing-30) * 2), var(--page-max-width));
  margin-inline: auto;
}
.wrap-narrow {
  width: min(100% - (var(--spacing-30) * 2), 820px);
  margin-inline: auto;
}
.section { padding-block: var(--section-gap-max); }
.section-tight { padding-block: var(--section-gap-min); }

@media (max-width: 700px) {
  .wrap, .wrap-narrow { width: min(100% - (var(--spacing-19) * 2), var(--page-max-width)); }
  .section { padding-block: var(--spacing-76); }
  .section-tight { padding-block: var(--spacing-46); }
}

.rule {
  border: 0;
  border-top: 1px solid var(--color-ash);
  margin: 0;
}

/* Stone panel — surface level 2, quiet structural separation. */
.panel-stone {
  background: var(--surface-stone-panel);
}

/* ============================================================
   TYPOGRAPHY ROLES
   Fluid down for small screens; each tops out at its token value.
   ============================================================ */
.display {
  font-size: clamp(48px, 0.4rem + 8.6vw, var(--text-display));
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
}
.display-lg {
  font-size: clamp(44px, 1rem + 6vw, var(--text-heading-lg));
  line-height: var(--leading-heading-lg);
  letter-spacing: var(--tracking-heading-lg);
  text-transform: uppercase;
}
.display-sm {
  font-size: clamp(42px, 1rem + 5.4vw, var(--text-heading));
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  text-transform: uppercase;
}
.headline {
  font-size: clamp(32px, 1.1rem + 3.1vw, var(--text-heading-sm));
  line-height: var(--leading-heading-sm);
  letter-spacing: var(--tracking-heading-sm);
}
.subhead {
  font-size: clamp(26px, 1.05rem + 1.9vw, var(--text-subheading));
  line-height: var(--leading-subheading);
  letter-spacing: var(--tracking-subheading);
}
.body-lg {
  font-size: var(--text-body);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
}
.body-sm {
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
}
.dim { color: var(--ink-60); }

/* Section Label — museum signage. 11px, uppercase, 0.05em. */
.label {
  font-size: var(--text-caption);
  font-weight: var(--font-weight-regular);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-ink);
}
.label-quiet { color: var(--ink-45); }

/* Founder-intro left column label — 15px uppercase variant. */
.label-lead {
  font-size: var(--text-body-sm);
  font-weight: var(--font-weight-regular);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-ink);
}

/* ============================================================
   HEADER
   ============================================================ */
.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--color-parchment) 90%, transparent);
  backdrop-filter: saturate(120%) blur(10px);
  -webkit-backdrop-filter: saturate(120%) blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color 300ms var(--ease);
}
.site-header.is-stuck { border-bottom-color: var(--color-ash); }

.nav {
  display: flex;
  align-items: center;
  gap: var(--spacing-30);
  min-height: var(--spacing-76);
}
.brand {
  font-size: var(--text-body-sm);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  border: 0;
}
.brand:hover { border: 0; color: var(--ink-60); }

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--spacing-30);
  margin-left: auto;
}
.nav-links a {
  font-size: var(--text-caption);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  border: 0;
  color: var(--ink-45);
  transition: color 240ms var(--ease);
}
.nav-links a:hover,
.nav-links a[aria-current="page"] { color: var(--color-ink); border: 0; }

.nav-toggle {
  display: none;
  margin-left: auto;
  background: none;
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-buttons);
  color: var(--color-ink);
  font-family: inherit;
  font-size: var(--text-caption);
  font-weight: var(--font-weight-regular);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding: var(--spacing-8) var(--spacing-19);
  cursor: pointer;
}

@media (max-width: 860px) {
  .nav-toggle { display: block; }
  .nav-links {
    position: fixed;
    inset: var(--spacing-76) 0 auto;
    margin: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: var(--spacing-15) var(--spacing-19) var(--spacing-46);
    background: var(--color-parchment);
    border-bottom: 1px solid var(--color-ash);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity 260ms var(--ease), transform 260ms var(--ease), visibility 260ms;
  }
  .nav-links.open { opacity: 1; visibility: visible; transform: none; }
  .nav-links a {
    width: 100%;
    padding: var(--spacing-15) 0;
    font-size: var(--text-body-sm);
    border-bottom: 1px solid var(--ink-12);
  }
  .nav-links a:last-child { border-bottom: 0; }
}

/* ============================================================
   GHOST TEXT LINK
   The only clickable style. 15px, no fill, 10px radius hit area,
   5px vertical / 0 horizontal padding, trailing arrow, hover underline.
   ============================================================ */
.ghost {
  display: inline-flex;
  align-items: baseline;
  gap: var(--spacing-8);
  padding: var(--spacing-5) 0;
  border: 0;
  border-radius: var(--radius-links);
  background: none;
  color: var(--color-ink);
  font-family: inherit;
  font-size: var(--text-body-sm);
  font-weight: var(--font-weight-regular);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  cursor: pointer;
  transition: color 260ms var(--ease);
}
.ghost::after {
  content: "→";
  display: inline-block;
  transition: transform 300ms var(--ease);
}
.ghost > span {
  box-shadow: inset 0 -1px 0 0 transparent;
  transition: box-shadow 260ms var(--ease);
}
.ghost:hover { border: 0; }
.ghost:hover > span { box-shadow: inset 0 -1px 0 0 currentColor; }
.ghost:hover::after { transform: translateX(5px); }
.ghost-quiet { color: var(--ink-60); }
.ghost-quiet:hover { color: var(--color-ink); }
.ghost-back::after { content: none; }
.ghost-back::before {
  content: "←";
  display: inline-block;
  transition: transform 300ms var(--ease);
}
.ghost-back:hover::before { transform: translateX(-5px); }

/* Pill filter button — the only state-change button in the system.
   1px ink border, 10px radius, 8px/19px padding, 11px caps.
   Hover fills ink, text goes parchment. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-8);
  padding: var(--spacing-8) var(--spacing-19);
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-buttons);
  background: none;
  color: var(--color-ink);
  font-family: inherit;
  font-size: var(--text-caption);
  font-weight: var(--font-weight-regular);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  cursor: pointer;
  transition: background 280ms var(--ease), color 280ms var(--ease);
}
.pill::after { content: "→"; }
.pill:hover,
.pill[aria-pressed="true"] {
  background: var(--color-ink);
  color: var(--color-parchment);
  border-color: var(--color-ink);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-30);
  align-items: baseline;
}

/* ============================================================
   HERO
   Full-viewport. Display text overlaps a gradient sphere
   positioned right-of-center. Scroll cue bottom-right, 30px inset.
   ============================================================ */
.hero {
  position: relative;
  padding-block: var(--spacing-76) var(--spacing-119);
  min-height: min(88vh, 900px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.hero-inner {
  position: relative;
  z-index: 2;
  transform: translate3d(0, var(--heroY, 0px), 0);
  opacity: var(--heroFade, 1);
  will-change: transform, opacity;
}
.hero h1 { margin-block: var(--spacing-30); }
.hero-lede {
  max-width: 46ch;
  font-size: var(--text-body);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  color: var(--ink-60);
}
.hero .actions { margin-top: var(--spacing-46); }

/* Hero Gradient Sphere — the singleton chromatic event.
   ~50% of viewport height. No border, no shadow, no interaction state.
   CSS gradient is the base layer; WebGL canvas overlays it when supported. */
.sphere-field {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 58%;
  width: min(50vh, 560px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  pointer-events: none;
  transform:
    translate(-50%, -50%)
    translate3d(0, var(--par, 0px), 0)
    rotate(var(--parRot, 0deg))
    scale(var(--parScale, 1));
}
.sphere {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--gradient-iridescent-sphere);
  animation: drift 26s var(--ease) infinite;
}
/* WebGL takes over: hide the CSS gradient, let the shader render the ball. */
.sphere.gl-on {
  background: none;
  animation: none;
}
.sphere-gl {
  position: absolute;
  inset: -14%;
  width: 128%;
  height: 128%;
  display: block;
  animation: drift 26s var(--ease) infinite;
}
@keyframes drift {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50% { transform: translate3d(0, -15px, 0); }
}

/* Concentric Circle Ornament — 1px, never filled, never animated. */
.ring {
  position: absolute;
  border: 1px solid var(--color-ash);
  border-radius: 50%;
  pointer-events: none;
}
.ring-1 { inset: -8%; }
.ring-2 { inset: -22%; border-color: var(--ink-20); }
.ring-3 { inset: -40%; border-color: var(--ink-12); }

.sphere-caption {
  position: absolute;
  bottom: calc(var(--spacing-46) * -1);
  left: 50%;
  translate: -50% 0;
  white-space: nowrap;
  color: var(--ink-45);
}

@media (max-width: 940px) {
  .hero { min-height: 0; }
  .sphere-field { top: 22%; left: 78%; width: min(46vh, 380px); }
  .sphere-caption { display: none; }
}
@media (max-width: 600px) {
  .sphere-field { top: 14%; left: 84%; width: 260px; }
}

/* Scroll Indicator — bottom-right, 30px inset, fades once scrolled. */
.scroll-cue {
  position: absolute;
  right: var(--spacing-30);
  bottom: var(--spacing-30);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-15);
  border: 0;
  border-radius: var(--radius-links);
  padding: var(--spacing-5) 0;
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-ink);
  transition: opacity 400ms var(--ease);
}
.scroll-cue:hover { border: 0; }
.scroll-cue.is-hidden { opacity: 0; pointer-events: none; }
.scroll-cue .cue-line {
  display: block;
  width: var(--spacing-46);
  height: 1px;
  background: var(--color-ink);
  transform-origin: left center;
  animation: cue 3.2s var(--ease) infinite;
}
@keyframes cue {
  0%, 100% { transform: scaleX(0.35); opacity: 0.5; }
  50% { transform: scaleX(1); opacity: 1; }
}
@media (max-width: 940px) { .scroll-cue { display: none; } }

/* ============================================================
   FOUNDER INTRO BLOCK
   Left: 15px uppercase label + ghost link. Right: 18px body.
   Column gap 19px, 76px vertical padding.
   ============================================================ */
.intro {
  display: grid;
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
  gap: var(--element-gap);
  padding-block: var(--spacing-76);
}
.intro-aside { display: grid; gap: var(--spacing-19); align-content: start; }
.intro-body {
  font-size: var(--text-body);
  line-height: var(--leading-body);
  letter-spacing: var(--tracking-body);
  max-width: var(--measure);
}
.intro-body > * + * { margin-top: var(--spacing-19); }
@media (max-width: 860px) {
  .intro { grid-template-columns: 1fr; gap: var(--spacing-30); }
}

/* ============================================================
   CLIENT LOGO CELL — strict 2 × 5, hairline dividers, no padding
   ============================================================ */
.logo-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  border-top: 1px solid var(--color-ash);
  border-left: 1px solid var(--color-ash);
}
.logo-grid > * {
  border-right: 1px solid var(--color-ash);
  border-bottom: 1px solid var(--color-ash);
  background: var(--surface-paper);
  border-radius: var(--radius-cards);
  min-height: 132px;
  display: grid;
  place-items: center;
  text-align: center;
  font-size: var(--text-caption);
  font-weight: var(--font-weight-bold);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-60);
  transition: color 300ms var(--ease);
}
.logo-grid > * > * { width: 60%; }
.logo-grid > *:hover { color: var(--color-ink); }
@media (max-width: 900px) { .logo-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) { .logo-grid { grid-template-columns: repeat(2, 1fr); } }

/* ============================================================
   EDITORIAL INDEX ROWS
   ============================================================ */
.index-list { list-style: none; margin: 0; padding: 0; }
.index-list li { border-top: 1px solid var(--color-ash); }
.index-list li:last-child { border-bottom: 1px solid var(--color-ash); }

.index-row {
  display: grid;
  grid-template-columns: var(--spacing-76) 1fr minmax(0, 30ch) var(--spacing-119);
  gap: var(--spacing-30);
  align-items: baseline;
  padding: var(--spacing-30) 0;
  border: 0;
  transition: padding 320ms var(--ease);
}
.index-row:hover { border: 0; padding-left: var(--spacing-15); }
.index-row .num {
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  color: var(--ink-45);
  font-variant-numeric: tabular-nums;
}
.index-row .title {
  font-size: clamp(26px, 1.05rem + 1.9vw, var(--text-subheading));
  line-height: var(--leading-subheading);
  letter-spacing: var(--tracking-subheading);
}
.index-row .desc {
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--ink-60);
}
.index-row .when {
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-45);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 900px) {
  .index-row { grid-template-columns: var(--spacing-46) 1fr; row-gap: var(--spacing-6); }
  .index-row .desc { grid-column: 2; }
  .index-row .when { grid-column: 2; text-align: left; }
}

/* ============================================================
   FEATURED WORK CARD — grid-paper on white, 0 radius, no border
   ============================================================ */
.paper-card {
  position: relative;
  background: var(--surface-paper);
  border: 0;
  border-radius: var(--radius-cards);
  padding: var(--card-padding);
  overflow: hidden;
}
.paper-card::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--color-parchment) 1px, transparent 1px),
    linear-gradient(to bottom, var(--color-parchment) 1px, transparent 1px);
  background-size: var(--spacing-30) var(--spacing-30);
}
.paper-card > * { position: relative; z-index: 1; }

.cards {
  display: grid;
  gap: var(--spacing-8);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}
.card-title {
  font-size: clamp(32px, 1.1rem + 3.1vw, var(--text-heading-sm));
  line-height: var(--leading-heading-sm);
  letter-spacing: var(--tracking-heading-sm);
  margin-bottom: var(--element-gap);
}

/* ============================================================
   TWO-COLUMN EDITORIAL BLOCK
   ============================================================ */
.split {
  display: grid;
  grid-template-columns: minmax(0, 16ch) minmax(0, 1fr);
  gap: var(--spacing-30) var(--spacing-46);
  align-items: start;
}
@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; gap: var(--element-gap); }
}

/* ============================================================
   CV
   ============================================================ */
.cv-entry { padding-block: var(--spacing-30); border-top: 1px solid var(--color-ash); }
.cv-entry:last-of-type { border-bottom: 1px solid var(--color-ash); }
.cv-role {
  font-size: clamp(26px, 1.05rem + 1.9vw, var(--text-subheading));
  line-height: var(--leading-subheading);
  letter-spacing: var(--tracking-subheading);
  margin-bottom: var(--spacing-6);
}
.cv-org {
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--ink-60);
  margin-bottom: var(--element-gap);
  font-variant-numeric: tabular-nums;
}
.cv-points { margin: 0; padding: 0; list-style: none; max-width: var(--measure); }
.cv-points li {
  position: relative;
  padding-left: var(--spacing-30);
  margin-bottom: var(--spacing-8);
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--ink-60);
}
.cv-points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.66em;
  width: var(--spacing-15);
  height: 1px;
  background: var(--color-ink);
}

.tags { display: flex; flex-wrap: wrap; gap: var(--spacing-8); list-style: none; margin: 0; padding: 0; }
.tags li {
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-60);
  border: 1px solid var(--color-ash);
  border-radius: var(--radius-links);
  padding: var(--spacing-6) var(--spacing-15);
  background: none;
}

/* ============================================================
   PROSE / WRITING — left-aligned always
   ============================================================ */
.prose {
  max-width: var(--measure);
  font-size: var(--text-body);
  line-height: 1.62;
  letter-spacing: var(--tracking-body);
  text-align: left;
}
.prose > * + * { margin-top: var(--element-gap); }
.prose h2 {
  font-size: clamp(26px, 1.05rem + 1.9vw, var(--text-subheading));
  line-height: var(--leading-subheading);
  letter-spacing: var(--tracking-subheading);
  margin-top: var(--spacing-76);
}
.prose h3 {
  font-size: var(--text-body);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-body);
  margin-top: var(--spacing-46);
}
.prose strong { font-weight: var(--font-weight-bold); }
.prose a { border-bottom-color: var(--ink-45); }
.prose blockquote {
  margin: var(--spacing-46) 0;
  padding-left: var(--spacing-30);
  border-left: 1px solid var(--color-ink);
  font-size: clamp(26px, 1.05rem + 1.9vw, var(--text-subheading));
  line-height: var(--leading-subheading);
  letter-spacing: var(--tracking-subheading);
}
.prose ul, .prose ol { padding-left: var(--element-gap); }
.prose li { margin-bottom: var(--spacing-6); }
.prose li::marker { color: var(--ink-45); }
.prose hr { border: 0; border-top: 1px solid var(--color-ash); margin: var(--spacing-76) 0; }
.prose figure { margin: var(--spacing-46) 0; }
.prose figcaption {
  margin-top: var(--spacing-8);
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-45);
}

/* Code — blog is code-first. Cards are sharp, so code blocks are too. */
.prose code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  letter-spacing: 0;
  background: var(--surface-paper);
  border: 1px solid var(--color-ash);
  border-radius: var(--radius-cards);
  padding: 0.1em 0.36em;
}
.codeblock {
  margin: var(--spacing-46) 0;
  border: 1px solid var(--color-ash);
  border-radius: var(--radius-cards);
  background: var(--surface-paper);
  overflow: hidden;
}
.codeblock figcaption {
  margin: 0;
  padding: var(--spacing-8) var(--spacing-15);
  border-bottom: 1px solid var(--color-ash);
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-60);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--element-gap);
}
.codeblock pre {
  margin: 0;
  padding: var(--element-gap);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: var(--text-body-sm);
  line-height: 1.62;
  letter-spacing: 0;
  tab-size: 2;
}
.codeblock pre code {
  background: none;
  border: 0;
  padding: 0;
  font-size: inherit;
}
.copy-btn {
  border: 1px solid var(--color-ash);
  border-radius: var(--radius-buttons);
  background: none;
  font-family: inherit;
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-60);
  padding: var(--spacing-5) var(--spacing-8);
  cursor: pointer;
  transition: background 240ms var(--ease), color 240ms var(--ease), border-color 240ms var(--ease);
}
.copy-btn:hover {
  background: var(--color-ink);
  color: var(--color-parchment);
  border-color: var(--color-ink);
}

/* Callout — hairline only, sharp corners. */
.note {
  border: 1px solid var(--color-ash);
  border-radius: var(--radius-cards);
  padding: var(--card-padding);
  background: var(--surface-paper);
}
.note .label { display: block; margin-bottom: var(--spacing-8); }

/* Editorial placeholder marker. */
.todo {
  border: 1px dashed var(--ink-45);
  border-radius: var(--radius-cards);
  padding: var(--element-gap) var(--spacing-30);
  font-size: var(--text-body-sm);
  line-height: var(--leading-body-sm);
  letter-spacing: var(--tracking-body-sm);
  color: var(--ink-60);
}
.todo b { color: var(--color-ink); font-weight: var(--font-weight-bold); }

/* ============================================================
   MARQUEE — infinite ticker, speed reacts to scroll velocity
   ============================================================ */
.marquee {
  overflow: hidden;
  border-top: 1px solid var(--color-ash);
  border-bottom: 1px solid var(--color-ash);
  padding-block: var(--spacing-30);
  user-select: none;
}
.marquee-track {
  display: flex;
  width: max-content;
  will-change: transform;
}
.marquee-track > span {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-46);
  padding-right: var(--spacing-46);
  white-space: nowrap;
  font-size: clamp(32px, 1.1rem + 3.1vw, var(--text-heading-sm));
  line-height: var(--leading-heading-sm);
  letter-spacing: var(--tracking-heading-sm);
  text-transform: uppercase;
  color: var(--color-ink);
}
.marquee-track > span::after {
  content: "";
  width: var(--spacing-8);
  height: var(--spacing-8);
  border-radius: 50%;
  background: var(--gradient-iridescent-sphere);
  flex: none;
}

/* ============================================================
   SPLIT TEXT — display lines rise out of a clip mask
   ============================================================ */
.tl-line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.06em;
  margin-bottom: -0.06em;
}
.tl-line > span {
  display: block;
  transform: translateY(105%);
  transition:
    transform 1100ms cubic-bezier(0.16, 1, 0.3, 1),
    opacity 900ms var(--ease);
  opacity: 0;
}
.tl.in .tl-line > span { transform: translateY(0); opacity: 1; }

/* Character-level stagger — hero headline only.
   The line wrapper stops animating; each glyph carries the motion. */
.tl-chars .tl-line > span.ch-host {
  transform: none;
  opacity: 1;
  transition: none;
}
.ch {
  display: inline-block;
  transform: translateY(105%) rotate(4deg);
  opacity: 0;
  transition:
    transform var(--dur-slow) var(--ease-out-expo),
    opacity 760ms var(--ease);
  will-change: transform, opacity;
}
.tl-chars.in .ch { transform: translateY(0) rotate(0deg); opacity: 1; }

/* Section labels stay with their section while it scrolls past. */
.label-pin {
  position: sticky;
  top: calc(var(--nav-h) + var(--spacing-30));
  align-self: start;
}
@media (max-width: 860px) { .label-pin { position: static; } }

/* ============================================================
   REVEAL
   ============================================================ */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.reveal.in { opacity: 1; transform: none; }

/* Cells clip-wipe up rather than fade. */
.logo-grid > * {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 620ms var(--ease), transform 620ms var(--ease), color 300ms var(--ease);
}
.logo-grid.in > * { opacity: 1; transform: none; }

/* Index rows cascade. */
.index-list.in li:nth-child(1) .index-row { animation: rowIn 700ms var(--ease) both 40ms; }
.index-list.in li:nth-child(2) .index-row { animation: rowIn 700ms var(--ease) both 120ms; }
.index-list.in li:nth-child(3) .index-row { animation: rowIn 700ms var(--ease) both 200ms; }
.index-list.in li:nth-child(4) .index-row { animation: rowIn 700ms var(--ease) both 280ms; }
.index-list.in li:nth-child(5) .index-row { animation: rowIn 700ms var(--ease) both 360ms; }
@keyframes rowIn {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: none; }
}

/* ============================================================
   NATIVE SCROLL — DELIBERATE
   The page is never moved into a fixed transform shell and body
   overflow is never touched. The browser owns scrolling outright.
   Motion reads scroll position; it never takes control of it.
   ============================================================ */

/* ============================================================
   CUSTOM CURSOR
   ============================================================ */
.has-cursor,
.has-cursor a,
.has-cursor button,
.has-cursor .ghost,
.has-cursor .pill { cursor: none; }

.cursor-dot,
.cursor-ring {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 900;
  pointer-events: none;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 240ms var(--ease);
}
.cursor-dot {
  width: var(--spacing-6);
  height: var(--spacing-6);
  background: var(--color-ink);
}
.cursor-ring {
  width: var(--spacing-32);
  height: var(--spacing-32);
  border: 1px solid var(--color-ink);
  display: grid;
  place-items: center;
  transition:
    opacity 240ms var(--ease),
    width var(--dur-fast) var(--ease),
    height var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.cursor-dot.on, .cursor-ring.on { opacity: 1; }
.cursor-ring.wide {
  width: var(--spacing-76);
  height: var(--spacing-76);
  border-color: var(--ink-45);
}
.cursor-ring.down { width: var(--spacing-19); height: var(--spacing-19); }
.cursor-ring.labelled {
  width: var(--spacing-119);
  height: var(--spacing-119);
  background: var(--color-ink);
  border-color: var(--color-ink);
}
.cursor-label {
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-parchment);
  opacity: 0;
  transition: opacity 200ms var(--ease);
  white-space: nowrap;
}
.cursor-ring.labelled .cursor-label { opacity: 1; }

/* ============================================================
   SECTION COUNTER — bottom-left chrome
   ============================================================ */
.sec-counter {
  position: fixed;
  left: var(--spacing-30);
  bottom: var(--spacing-30);
  z-index: 200;
  display: flex;
  align-items: baseline;
  gap: var(--spacing-5);
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--ink-45);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease);
}
.sec-counter .cur {
  color: var(--color-ink);
  display: inline-block;
  transition: transform var(--dur-fast) var(--ease-out-expo);
}
.sec-counter.flip .cur { transform: translateY(-3px); }
.sec-counter.is-hidden { opacity: 0; }
@media (max-width: 940px) { .sec-counter { display: none; } }

/* ============================================================
   SCROLL PROGRESS — 2px iridescent hairline, top of viewport
   ============================================================ */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 200;
  pointer-events: none;
}
.scroll-progress > span {
  display: block;
  height: 100%;
  background: var(--gradient-iridescent-sphere);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

/* Header retracts on scroll-down, returns on scroll-up. */
.site-header {
  transition:
    border-color 300ms var(--ease),
    transform 480ms var(--ease);
}
.site-header.is-hidden { transform: translateY(-100%); }

/* ============================================================
   PAGE VEIL — parchment wipe between pages
   ============================================================ */
.page-veil {
  position: fixed;
  inset: 0;
  z-index: 800;
  background: var(--color-parchment);
  transform-origin: 50% 100%;
  transform: scaleY(1);
  pointer-events: none;
  display: grid;
  place-items: center;
}
.veil-mark {
  font-size: clamp(42px, 1rem + 5.4vw, var(--text-heading));
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  text-transform: uppercase;
  color: var(--color-ink);
  opacity: 1;
  transition: opacity 380ms var(--ease);
}
.is-loaded .page-veil {
  transform: scaleY(0);
  transition: transform 860ms var(--ease-in-out-quint);
}
.is-loaded .veil-mark { opacity: 0; }
.is-leaving .page-veil {
  transform-origin: 50% 0;
  transform: scaleY(1);
  transition: transform 480ms var(--ease-in-out-quint);
}
.is-leaving .veil-mark { opacity: 1; transition-delay: 180ms; }

/* Cards get depth only while tilting — still no shadow, ever. */
.paper-card, .note { transform-style: preserve-3d; will-change: transform; }

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer {
  border-top: 1px solid var(--color-ash);
  margin-top: var(--spacing-119);
  padding-block: var(--spacing-46) var(--spacing-30);
}
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--spacing-30);
  align-items: end;
}
.footer-grid nav { display: flex; flex-wrap: wrap; gap: var(--spacing-30); }
.footer-grid nav a {
  font-size: var(--text-caption);
  font-weight: var(--font-weight-bold);
  line-height: var(--leading-caption);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  border: 0;
  color: var(--ink-45);
}
.footer-grid nav a:hover { color: var(--color-ink); border: 0; }
.footer-mark {
  font-size: clamp(42px, 1rem + 5.4vw, var(--text-heading));
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  text-transform: uppercase;
}
@media (max-width: 700px) {
  .footer-grid { grid-template-columns: 1fr; align-items: start; }
}

/* ============================================================
   REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal, .logo-grid > * { opacity: 1; transform: none; }
  .tl-line > span, .ch { opacity: 1; transform: none; }
  .page-veil, .cursor-dot, .cursor-ring,
  .scroll-progress, .sec-counter { display: none; }
  .label-pin { position: static; }
  .hero-inner { opacity: 1; transform: none; }
  .has-cursor, .has-cursor a, .has-cursor button { cursor: auto; }
}

/* ============================================================
   PRINT — clean resume from /cv/
   ============================================================ */
@media print {
  body { background: #fff; font-size: 10pt; line-height: 1.34; }
  .site-header, .site-footer, .actions, .no-print, .todo,
  .sphere-field, .scroll-cue, .marquee, .sec-counter,
  .page-veil, .cursor-dot, .cursor-ring, .scroll-progress { display: none !important; }
  .tl-line > span, .ch { opacity: 1 !important; transform: none !important; }
  .label-pin { position: static !important; }
  .hero-inner { opacity: 1 !important; transform: none !important; }
  .logo-grid > * { opacity: 1 !important; transform: none !important; }
  .wrap, .wrap-narrow { width: 100%; }
  .section, .section-tight { padding-block: 0.3in 0; }
  .hero { min-height: 0; padding-block: 0; }
  a { border: 0; }
  .display, .display-lg, .display-sm { font-size: 22pt; line-height: 1; }
  .headline { font-size: 15pt; }
  .subhead, .cv-role, .card-title { font-size: 12pt; }
  .prose, .body-lg, .cv-points li { font-size: 10pt; }
  .cv-entry { break-inside: avoid; padding-block: 9pt; }
  .paper-card { padding: 0; }
  .paper-card::before { display: none; }
  .reveal { opacity: 1; transform: none; }
}
