/* =====================================================================
   Self-hosted webfonts (Spectral + Inter)
   Previously loaded from fonts.googleapis.com, which put a render-blocking
   request to a third-party origin ahead of first paint on every page.
   Serving them from our own origin removes that origin hop entirely and lets
   the files inherit our own Cache-Control + brotli from _headers.
   Only the weights actually used are shipped: Spectral 400/500 (roman +
   italic) and Inter as a variable font covering 400-600.
   latin-ext faces are only downloaded when a page actually uses those
   characters, so a typical English page fetches ~77KB of font, not 248KB.
   ===================================================================== */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('fonts/inter-400-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('fonts/inter-400-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Spectral';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/spectral-400-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Spectral';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/spectral-400-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Spectral';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/spectral-500-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Spectral';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/spectral-500-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/spectral-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/spectral-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/spectral-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/spectral-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* =====================================================================
   Casually Digital — homepage styles
   Edit the variables below to retune the whole site at once.
   ===================================================================== */

:root {
  --bg:        #eeeef1;   /* page background, soft cool grey */
  --bg-card:   #f7f7f9;   /* lifted cards */
  --ink:       #14161c;   /* primary text, near-black */
  --ink-soft:  #4a4d57;   /* secondary text */
  --ink-faint: #5c5f6b;   /* labels, captions — darkened to meet WCAG AA 4.5:1 */
  --accent:    #2f44b3;   /* royal blue — italics, buttons, numerals */
  --accent-dim:#aab2dd;   /* faded blue for big background numerals */
  --line:      #d6d7dd;   /* decorative hairline rules — not a contrast-bearing edge */
  --line-ui:   #7e8291;   /* borders that are the ONLY indicator of a control's
                             edge (inputs, ghost buttons). Meets WCAG 1.4.11
                             non-text contrast of 3:1 against #fff, --bg-card
                             and --bg; --line does not (1.4:1) so never use it
                             where the border is doing the work. */
  --tint-blue: #e7e9f7;   /* soft on-brand blue band */
  --tint-white:#f8f8fb;   /* near-white band */
  --dark:      #11141b;   /* dark CTA + footer */
  --dark-soft: #9a9eaa;   /* text on dark */
  --dark-line: #2a2e38;

  --serif: "Spectral", Georgia, "Times New Roman", serif;
  --sans:  "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --max: 1320px;
  --pad: clamp(18px, 4vw, 44px);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

em { font-family: var(--serif); font-style: italic; }

a { color: inherit; text-decoration: none; }

/* ---------- accessibility ---------- */
/* Skip link — visually hidden until it receives keyboard focus. */
.skip-link {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* Un-hide on keyboard focus. Without this the link is reachable by screen
   readers but invisible to sighted keyboard users, so the first Tab on every
   page produced no visible feedback at all (WCAG 2.4.7). */
.skip-link:focus {
  position: fixed;
  top: 12px;
  left: 12px;
  width: auto;
  height: auto;
  margin: 0;
  padding: 10px 18px;
  overflow: visible;
  clip: auto;
  z-index: 200;
  background: var(--dark);
  color: #fff;
  border-radius: 6px;
  font-size: 14px;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

a:focus-visible,
button:focus-visible,
.service-item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
.btn-primary:focus-visible,
.nav-cta:focus-visible,
.btn-light:focus-visible {
  outline-color: #fff;
}

/* ---------- full-bleed colour bands ----------
   Paints a section background edge-to-edge while keeping its centered
   content, by extending the background horizontally via box-shadow and
   clipping the vertical bleed. Used to break up the page with rhythm. */
.band { background: var(--band-bg); box-shadow: 0 0 0 100vmax var(--band-bg); clip-path: inset(0 -100vmax); position: relative; }
.band-blue  { --band-bg: var(--tint-blue); }
.band-white { --band-bg: var(--tint-white); }

/* ---------- shared bits ---------- */
.eyebrow {
  display: inline-block;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.eyebrow-light { color: var(--dark-soft); }
/* Section-specific eyebrow spacing on the About page. These were two inline
   style="" attributes; moved here so the CSP can drop 'unsafe-inline' from
   style-src. */
.ab-head-inner .eyebrow  { margin-bottom: 28px; }
.ab-values-head .eyebrow { margin-bottom: 24px; }

h1, h2, h3 { font-family: var(--serif); font-weight: 500; letter-spacing: -0.01em; }
h1 em, h2 em, h3 em { color: var(--accent); }

.btn {
  display: inline-block;
  font-size: 14px;
  font-weight: 500;
  padding: 13px 22px;
  border-radius: 7px;
  transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: #25379a; }
.btn-ghost { color: var(--ink); border: 1px solid var(--line-ui); }
.btn-ghost:hover { border-color: var(--ink); }
.btn-light { background: #fff; color: var(--dark); }
.btn-light:hover { background: #e9e9ee; }

/* =====================================================================
   NAV
   ===================================================================== */
.nav {
  max-width: var(--max);
  margin: 0 auto;
  padding: 26px var(--pad);
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;
}
.logo { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }
.logo em { color: var(--accent); font-weight: 500; }
.logo-plus { color: var(--accent); }
.nav-links { display: flex; align-items: center; gap: 28px; }
.nav-links a { font-size: 14px; color: var(--ink-soft); }
.nav-links a:hover { color: var(--ink); }
.nav-cta {
  background: var(--dark);
  color: #fff !important;
  padding: 9px 16px;
  border-radius: 6px;
}
.nav-cta:hover { background: #000; }

/* mobile hamburger */
.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 42px;
  height: 42px;
  padding: 9px;
  background: none;
  border: none;
  cursor: pointer;
}
.nav-toggle span {
  display: block;
  height: 2px;
  width: 100%;
  background: var(--ink);
  border-radius: 2px;
  transition: transform 0.22s ease, opacity 0.22s ease;
}
.nav-toggle.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle.is-open span:nth-child(2) { opacity: 0; }
.nav-toggle.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* =====================================================================
   HERO
   ===================================================================== */
.hero {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(40px, 7vw, 90px) var(--pad) clamp(60px, 8vw, 110px);
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}
.badges { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-bottom: 30px; }
.badge {
  font-size: 12px;
  font-weight: 500;
  color: var(--accent);
  background: #e3e5f4;
  padding: 6px 13px;
  border-radius: 100px;
}
.badge-dot::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  margin-right: 8px;
  vertical-align: middle;
}
.badge-plain { font-size: 12px; color: var(--ink-faint); }

.hero h1 {
  font-size: clamp(40px, 6vw, 68px);
  line-height: 1.04;
  margin-bottom: 26px;
}
/* Standalone statement under the h1. Kept in the sans face at full ink so it
   reads as a declaration rather than competing with the serif headline above
   or blending into the softer lede below. */
.hero-statement {
  font-size: clamp(17px, 1.9vw, 20px);
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink);
  max-width: 24em;
  margin-bottom: 18px;
}
.hero-lede {
  font-size: 16px;
  color: var(--ink-soft);
  max-width: 30em;
  margin-bottom: 32px;
}
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; }

.hero-photo {
  position: relative;
  aspect-ratio: 4 / 4.4;
  border-radius: 12px;
  overflow: hidden;
  background: linear-gradient(160deg, #dfe1ea, #c9ccd9);
  display: flex;
  align-items: center;
  justify-content: center;
}
.hero-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* No-photo fallback: the same italic "J" monogram the About portrait uses, so an
   empty hero panel reads as deliberate instead of broken. */
.hero-photo.photo-empty::after {
  content: "J";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(120px, 18vw, 220px);
  line-height: 1;
  color: var(--accent);
  opacity: 0.28;
}

/* =====================================================================
   CALLED IN FOR
   ===================================================================== */
.called-in {
  max-width: var(--max);
  margin: 0 auto;
  padding: 30px var(--pad);
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 28px;
}
.called-list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 14px 26px;
}
.called-list li {
  position: relative;
  font-size: 14px;
  color: var(--ink-soft);
  padding-left: 26px;
  white-space: nowrap;
}
.called-list li::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 14px; height: 1px;
  background: var(--line);
}
.called-list li:first-child { padding-left: 0; }
.called-list li:first-child::before { display: none; }

/* =====================================================================
   STATS
   ===================================================================== */
.stats {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(50px, 7vw, 90px) var(--pad);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 28px;
}
.stat { display: flex; flex-direction: column; gap: 14px; }
.stat-num {
  font-family: var(--serif);
  font-size: clamp(38px, 5vw, 54px);
  font-weight: 500;
  line-height: 1;
}
.stat-num .plus { color: var(--accent); }
.stat-num em { color: var(--accent); }
.stat-label { font-size: 13px; color: var(--ink-faint); max-width: 18em; }

/* =====================================================================
   MANIFESTO
   ===================================================================== */
.manifesto {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(40px, 6vw, 80px) var(--pad) clamp(60px, 8vw, 110px);
}
.manifesto-grid {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: clamp(40px, 6vw, 88px);
  align-items: start;
}
@media (max-width: 860px) {
  .manifesto-grid { grid-template-columns: 1fr; gap: 48px; }
}
.manifesto .eyebrow { margin-bottom: 28px; }
.manifesto-body {
  font-family: var(--serif);
  font-size: clamp(26px, 3.6vw, 40px);
  line-height: 1.28;
  font-weight: 400;
  max-width: 17em;
}
.manifesto-body em { color: var(--accent); }
.manifesto-foot {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 36px;
  font-size: 13px;
  color: var(--ink-faint);
}
.rule { width: 36px; height: 1px; background: var(--ink-faint); flex: none; }

/* what's-always-included checklist */
.manifesto-included .eyebrow { margin-bottom: 28px; }
.included-list { list-style: none; }
.included-list li {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 14px;
  padding: 20px 0;
  border-top: 1px solid var(--line);
  align-items: baseline;
}
.included-list li:last-child { border-bottom: 1px solid var(--line); }
/* Decorative status marker, not a control. A "+" here read as tap-to-expand,
   especially in the accent colour at the head of a bordered row. A checkmark is
   unambiguous for "included", so the accent colour is safe to keep. No serif
   stack: Spectral has no glyph for U+2713, so let it fall through to the
   system face rather than render an inconsistent fallback. */
.included-mark {
  font-size: 15px;
  line-height: 1;
  color: var(--accent);
  font-weight: 500;
}
.included-text { font-size: 15px; line-height: 1.55; color: var(--ink-soft); }
.included-text strong { font-weight: 600; color: var(--ink); }
.included-text em { color: var(--accent); }
.included-cta { margin-top: 32px; }

/* =====================================================================
   SCROLL REVEAL SYSTEM  (progressive enhancement; see reveal.js)
   One cohesive family — same fade + easing everywhere — with per-section
   variation via direction (rv-left/right/zoom), speed (rv-slow/fast) and
   staggered groups (.rv-group > .rv-item). The shared easing curve and
   opacity fade keep it all feeling related without being identical.
   ===================================================================== */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity 0.9s ease, transform 0.9s cubic-bezier(0.22, 1, 0.36, 1); }
.reveal.d1 { transition-delay: 0.12s; }

/* single-element direction variants (initial offset before settling) */
.reveal.rv-left  { transform: translateX(-36px); }
.reveal.rv-right { transform: translateX(36px); }
.reveal.rv-zoom  { transform: scale(0.94); }
.reveal.rv-up-sm { transform: translateY(18px); }

/* speed variants (kept within a narrow range for cohesion) */
.reveal.rv-slow { transition-duration: 1.05s; }
.reveal.rv-fast { transition-duration: 0.65s; }

/* settle state — declared AFTER the direction variants so it wins the
   equal-specificity tie and the element animates fully into place */
.reveal.is-in { opacity: 1; transform: none; }

/* staggered group: container = .rv-group (observed), children = .rv-item */
.rv-group > .rv-item {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.75s ease, transform 0.75s cubic-bezier(0.22, 1, 0.36, 1);
}
.rv-group.rv-left  > .rv-item { transform: translateX(-30px); }
.rv-group.rv-right > .rv-item { transform: translateX(30px); }
.rv-group.rv-zoom  > .rv-item { transform: scale(0.92); }
.rv-group.rv-slow  > .rv-item { transition-duration: 0.9s; }
.rv-group.is-in > .rv-item { opacity: 1; transform: none; }

/* default cascade step (~0.08s) */
.rv-group.is-in > .rv-item:nth-child(1) { transition-delay: 0.05s; }
.rv-group.is-in > .rv-item:nth-child(2) { transition-delay: 0.13s; }
.rv-group.is-in > .rv-item:nth-child(3) { transition-delay: 0.21s; }
.rv-group.is-in > .rv-item:nth-child(4) { transition-delay: 0.29s; }
.rv-group.is-in > .rv-item:nth-child(5) { transition-delay: 0.37s; }
.rv-group.is-in > .rv-item:nth-child(6) { transition-delay: 0.45s; }
.rv-group.is-in > .rv-item:nth-child(7) { transition-delay: 0.53s; }
.rv-group.is-in > .rv-item:nth-child(8) { transition-delay: 0.61s; }
/* looser cascade (~0.13s step) for a slower, more deliberate ripple */
.rv-group.rv-loose.is-in > .rv-item:nth-child(1) { transition-delay: 0.08s; }
.rv-group.rv-loose.is-in > .rv-item:nth-child(2) { transition-delay: 0.21s; }
.rv-group.rv-loose.is-in > .rv-item:nth-child(3) { transition-delay: 0.34s; }
.rv-group.rv-loose.is-in > .rv-item:nth-child(4) { transition-delay: 0.47s; }
.rv-group.rv-loose.is-in > .rv-item:nth-child(5) { transition-delay: 0.60s; }
.rv-group.rv-loose.is-in > .rv-item:nth-child(6) { transition-delay: 0.73s; }

/* shown instantly because already on screen at load — no animation */
.reveal.no-anim,
.reveal.no-anim .included-list li,
.rv-group.no-anim > .rv-item { transition: none !important; }
.reveal.no-anim .included-list li,
.rv-group.no-anim > .rv-item { transition-delay: 0s !important; }

/* stagger the checklist items as the right column enters */
.manifesto-included.reveal .included-list li {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.8s ease, transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
.manifesto-included.reveal.is-in .included-list li { opacity: 1; transform: none; }
.manifesto-included.reveal.is-in .included-list li:nth-child(1) { transition-delay: 0.15s; }
.manifesto-included.reveal.is-in .included-list li:nth-child(2) { transition-delay: 0.30s; }
.manifesto-included.reveal.is-in .included-list li:nth-child(3) { transition-delay: 0.45s; }
.manifesto-included.reveal.is-in .included-list li:nth-child(4) { transition-delay: 0.60s; }
.manifesto-included.reveal.is-in .included-list li:nth-child(5) { transition-delay: 0.75s; }
.manifesto-included.reveal.is-in .included-list li:nth-child(6) { transition-delay: 0.90s; }

@media (prefers-reduced-motion: reduce) {
  .reveal,
  .manifesto-included.reveal .included-list li,
  .rv-group > .rv-item {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* =====================================================================
   SECTION HEAD (shared)
   ===================================================================== */
.section-head { margin-bottom: clamp(36px, 5vw, 56px); }
.section-head .eyebrow { margin-bottom: 20px; }
.section-head h2 {
  font-size: clamp(26px, 3.4vw, 38px);
  line-height: 1.18;
  max-width: 14em;
}

/* =====================================================================
   SERVICES
   ===================================================================== */
.services {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(40px, 6vw, 70px) var(--pad);
}
.services .section-head h2 { margin-left: auto; max-width: 16em; text-align: left; }
.services-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
.service-list { list-style: none; }
/* .service-item is a real <button> so Enter/Space and focus come from the
   platform. These first four lines strip the native button chrome; everything
   after is the original row styling. */
.service-item {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  width: 100%;
  display: grid;
  grid-template-columns: 36px 1fr auto;
  align-items: baseline;
  gap: 14px;
  padding: 26px 4px;
  border-top: 1px solid var(--line);
  cursor: pointer;
  transition: padding-left 0.18s ease;
}
.service-row:last-child .service-item { border-bottom: 1px solid var(--line); }
.service-item:hover { padding-left: 10px; }
.service-idx { font-size: 13px; color: var(--ink-faint); }
.service-name { font-family: var(--serif); font-size: 21px; }
.service-dur { font-size: 12px; color: var(--ink-faint); letter-spacing: 0.04em; }
.service-item.is-active {
  border-left: 2px solid var(--accent);
  margin-left: -2px;
  padding-left: 14px;
}
.service-item.is-active .service-name { color: var(--accent); }

.service-card {
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: clamp(28px, 3.5vw, 44px);
  overflow: hidden;
  min-height: 340px;
}
.card-eyebrow {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  display: block;
  margin-bottom: 22px;
}
.card-headline {
  font-family: var(--serif);
  font-size: clamp(22px, 2.6vw, 29px);
  line-height: 1.24;
  margin-bottom: 18px;
}
.card-headline em { color: var(--accent); }
.card-body {
  font-size: 15px;
  color: var(--ink-soft);
  max-width: 30em;
  margin-bottom: 26px;
}
.card-tags { display: flex; flex-wrap: wrap; gap: 8px; }
.card-tags span {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border: 1px solid var(--line);
  padding: 6px 11px;
  border-radius: 5px;
}
.card-bignum {
  position: absolute;
  right: 18px; bottom: -18px;
  font-family: var(--serif);
  font-size: 150px;
  line-height: 1;
  font-style: italic;
  color: var(--accent-dim);
  opacity: 0.5;
  pointer-events: none;
}

/* =====================================================================
   PROCESS
   ===================================================================== */
.process {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(50px, 7vw, 90px) var(--pad);
  text-align: center;
}
.process .section-head { display: flex; flex-direction: column; align-items: center; }
.process .section-head h2 { max-width: none; }
.steps {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(24px, 3vw, 44px);
  text-align: left;
  margin-top: 20px;
}
.step-num { font-family: var(--serif); font-style: italic; font-size: 30px; color: var(--accent); display: block; margin-bottom: 18px; }
.steps h3 { font-size: 18px; margin-bottom: 10px; }
.steps p { font-size: 14px; color: var(--ink-soft); }

/* =====================================================================
   SELECTED WORK
   ===================================================================== */
.work {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(50px, 7vw, 90px) var(--pad);
}
/* Hairline under the process section, whichever section now follows it. */
.process + .work,
.process + .ab-creds { border-top: 1px solid var(--line); }
.work .section-head { text-align: center; display: flex; flex-direction: column; align-items: center; }
.work .section-head h2 { max-width: none; }
.work-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.work-card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 30px 28px;
  display: flex;
  flex-direction: column;
}
.work-year { font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 18px; }
.work-card h3 { font-size: 21px; line-height: 1.25; margin-bottom: 14px; }
.work-card > p { font-size: 14px; color: var(--ink-soft); margin-bottom: 24px; flex: 1; }
.work-result { margin-bottom: 18px; }
/* Metrics are short phrases rather than bare numerals, so they need room to wrap
   cleanly in a third-width card. Scales down on narrow columns; line-height set
   so a two-line wrap still reads as one unit. */
.work-metric {
  font-family: var(--serif);
  font-size: clamp(22px, 2.2vw, 28px);
  line-height: 1.15;
  display: block;
  text-wrap: balance;
  margin-bottom: 4px;
}
/* Same size as the rest of the phrase: colour alone carries the emphasis. The
   old smaller size worked when the metric was a single numeral, but reads as a
   mistake now that both halves are words. */
.work-metric em { color: var(--accent); font-size: 1em; }
.work-metric-label { font-size: 13px; color: var(--ink-faint); }
.work-link { font-size: 13px; color: var(--accent); font-weight: 500; }
.work-link:hover { text-decoration: underline; }

/* =====================================================================
   CTA
   ===================================================================== */
.cta { background: var(--dark); color: #fff; }
.cta-inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(60px, 8vw, 110px) var(--pad);
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(40px, 6vw, 90px);
  align-items: start;
}
.cta-left .eyebrow { margin-bottom: 28px; }
.cta-left h2 { font-size: clamp(34px, 4.4vw, 50px); line-height: 1.05; color: #fff; margin-bottom: 28px; text-wrap: balance; }
.cta-left h2 em { color: #fff; }
.cta-left p { font-size: 15px; color: var(--dark-soft); max-width: 32em; margin-bottom: 32px; }
.cta-actions { display: flex; flex-wrap: wrap; gap: 12px; }

.cta-right {
  background: #171b24;
  border: 1px solid var(--dark-line);
  border-radius: 14px;
  padding: clamp(28px, 3.5vw, 40px);
}
.card-eyebrow-light { color: var(--dark-soft); }
.expect-headline { font-family: var(--serif); font-size: clamp(20px, 2.4vw, 26px); margin-bottom: 26px; }
.expect-headline em { color: #fff; }
.expect-list { list-style: none; display: flex; flex-direction: column; gap: 16px; margin-bottom: 28px; }
.expect-list li { display: flex; gap: 12px; font-size: 14px; color: var(--dark-soft); }
.expect-list li span { font-family: var(--serif); font-style: italic; color: #fff; flex: none; }
.card-tags-light span { color: var(--dark-soft); border-color: var(--dark-line); }

/* =====================================================================
   FOOTER
   ===================================================================== */
.footer {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(50px, 6vw, 80px) var(--pad);
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 40px 24px;
}
.footer .logo { color: var(--ink); margin-bottom: 16px; display: inline-block; }
.footer-brand p { font-size: 14px; color: var(--ink-faint); }
.footer-head { display: block; font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 16px; }
.footer-col a { display: block; font-size: 14px; color: var(--ink-soft); margin-bottom: 10px; }
.footer-col a:hover { color: var(--ink); }
.footer-meta {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  padding-top: 28px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--ink-faint);
}
.footer-meta a { color: var(--ink-faint); }
.footer-meta a:hover { color: var(--ink); }

/* =====================================================================
   LEGAL PAGES
   ===================================================================== */
.legal {
  max-width: 800px;
  margin: 0 auto;
  padding: clamp(48px, 8vw, 96px) var(--pad);
}
.legal .eyebrow { display: block; margin-bottom: 18px; }
.legal h1 { font-size: clamp(34px, 5vw, 52px); line-height: 1.05; letter-spacing: -0.01em; }
.legal-updated { font-size: 13px; color: var(--ink-faint); margin: 14px 0 44px; }
.legal h2 { font-size: 20px; margin: 40px 0 12px; }
.legal p, .legal li { font-size: 15px; line-height: 1.7; color: var(--ink-soft); }
.legal p { margin-bottom: 14px; }
.legal ul { margin: 0 0 16px 20px; }
.legal li { margin-bottom: 8px; }
.legal a { color: var(--accent); }
.legal strong { color: var(--ink); font-weight: 600; }

/* =====================================================================
   RESPONSIVE
   ===================================================================== */
@media (max-width: 860px) {
  .hero { grid-template-columns: 1fr; }
  .hero-photo { aspect-ratio: 4 / 3.4; max-width: 360px; }
  .stats { grid-template-columns: repeat(2, 1fr); gap: 36px 24px; }
  .called-in { display: block; text-align: center; }
  .called-list { justify-content: center; }
  .stat { align-items: center; text-align: center; }
  .stat-label { max-width: none; }
  .manifesto-lead { text-align: center; }
  .manifesto-body { max-width: none; }
  .manifesto-foot { justify-content: center; }
  .services-grid { grid-template-columns: 1fr; }
  .service-card { min-height: 0; margin: 6px 0 18px; }
  .steps { grid-template-columns: repeat(2, 1fr); row-gap: 36px; }
  .work-grid { grid-template-columns: 1fr; }
  .cta-inner { grid-template-columns: 1fr; }
  .footer { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 640px) {
  .nav-toggle { display: flex; }
  .nav-links {
    display: none;
    position: absolute;
    top: calc(100% - 6px);
    left: var(--pad);
    right: var(--pad);
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 10px;
    box-shadow: 0 14px 34px rgba(17, 20, 27, 0.12);
    z-index: 60;
  }
  .nav-links.is-open { display: flex; }
  .nav-links a { padding: 12px 14px; font-size: 15px; border-radius: 8px; }
  .nav-links a:not(.nav-cta):hover { background: var(--bg); }
  .nav-cta { text-align: center; }
}

@media (max-width: 520px) {
  .called-list { gap: 10px 20px; flex-basis: 100%; justify-content: center; }
  .called-list li { padding-left: 0; }
  .called-list li::before { display: none; }
  .stats { grid-template-columns: 1fr 1fr; }
  .steps { grid-template-columns: 1fr; }
  .footer { grid-template-columns: 1fr; }
  .footer-meta { flex-direction: column; }
}

/* respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; scroll-behavior: auto !important; }
}

/* =====================================================================
   ABOUT PAGE
   Rebuilt on the shared tokens above so it matches the homepage.
   Sections: head · story · facts · creds · values · cta
   ===================================================================== */
.nav-links a.is-active { color: var(--ink); }

/* mono accent used for tags / numerals on this page */
:root { --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace; }

/* ---- head ---- */
.ab-head {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(40px, 6vw, 80px) var(--pad) clamp(48px, 6vw, 80px);
}
.ab-head-inner {
  display: grid;
  grid-template-columns: 1.5fr 0.85fr;
  gap: clamp(32px, 5vw, 64px);
  align-items: end;
}
.ab-head h1 {
  font-size: clamp(38px, 5vw, 80px);
  line-height: 1.0;
  letter-spacing: -0.02em;
}
.ab-head-portrait {
  position: relative;
  aspect-ratio: 1 / 1;
  max-width: 340px;
  width: 100%;
  justify-self: end;
  border-radius: 16px;
  overflow: hidden;
  background: linear-gradient(160deg, #dfe1ea, #c9ccd9);
  box-shadow: 0 30px 60px -30px rgba(20, 22, 28, 0.4);
}
.ab-head-portrait img { width: 100%; height: 100%; object-fit: cover; display: block; position: relative; z-index: 1; }
.ab-head-portrait::after {
  content: "J";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: 200px;
  color: var(--accent);
  opacity: 0.28;
}

/* ---- story ---- */
.ab-story { padding: clamp(48px, 7vw, 80px) var(--pad); }
.ab-story-inner { max-width: 760px; margin: 0 auto; }
.ab-story p {
  font-size: 18px;
  line-height: 1.65;
  color: var(--ink-soft);
  margin-bottom: 26px;
  text-wrap: pretty;
}
.ab-story p:first-of-type::first-letter {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 82px;
  line-height: 0.82;
  float: left;
  margin: 8px 12px 0 0;
  color: var(--accent);
}
.ab-story h2 {
  font-size: clamp(28px, 2.6vw + 12px, 42px);
  line-height: 1.1;
  margin: 52px 0 20px;
  text-wrap: balance;
}

/* ---- facts ---- */
.ab-facts {
  padding: clamp(48px, 7vw, 80px) var(--pad);
}
.ab-facts-inner {
  max-width: var(--max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: clamp(32px, 5vw, 48px);
  align-items: start;
}
.ab-facts h2 { font-size: clamp(32px, 2.8vw + 12px, 46px); line-height: 1.05; text-wrap: balance; }
.ab-fact-list { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.ab-fact { padding: 22px 0; border-top: 1px solid var(--line); }
.ab-fact-num { font-family: var(--serif); font-style: italic; font-size: 40px; color: var(--accent); line-height: 1; margin-bottom: 8px; }
.ab-fact-label { color: var(--ink-soft); font-size: 14px; line-height: 1.45; }

/* ---- creds ---- */
.ab-creds { max-width: var(--max); margin: 0 auto; padding: clamp(48px, 7vw, 80px) var(--pad); }
.ab-creds-head {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: clamp(16px, 4vw, 40px);
  margin-bottom: 44px;
  align-items: baseline;
}
.ab-creds-head h2 { font-size: clamp(28px, 2.4vw + 12px, 40px); line-height: 1.1; text-wrap: balance; }
.ab-creds-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.ab-cred {
  padding: 24px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 12px;
}
.ab-cred-tag {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-faint);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 10px;
}
.ab-cred-title { font-family: var(--serif); font-weight: 500; font-size: 18px; line-height: 1.2; margin-bottom: 5px; }
.ab-cred-org { font-size: 13px; color: var(--ink-faint); }

/* ---- values ---- */
.ab-values { max-width: var(--max); margin: 0 auto; padding: clamp(56px, 8vw, 96px) var(--pad); }
.ab-values-head { margin-bottom: 44px; max-width: 720px; }
.ab-values-head h2 { font-size: clamp(36px, 4vw + 8px, 60px); line-height: 1.02; letter-spacing: -0.02em; text-wrap: balance; }
.ab-value {
  display: grid;
  grid-template-columns: 64px 1fr 2fr;
  gap: clamp(16px, 3vw, 32px);
  padding: 30px 0;
  border-top: 1px solid var(--line);
  align-items: baseline;
}
.ab-value:last-child { border-bottom: 1px solid var(--line); }
.ab-value-num { font-family: var(--mono); font-size: 13px; color: var(--accent); letter-spacing: 0.06em; }
.ab-value-title { font-family: var(--serif); font-weight: 500; font-size: 26px; line-height: 1.12; letter-spacing: -0.01em; }
.ab-value-desc { color: var(--ink-soft); font-size: 16px; line-height: 1.6; }

/* ---- cta ---- */
.ab-cta { padding: clamp(56px, 8vw, 96px) var(--pad) clamp(80px, 10vw, 128px); text-align: center; }
.ab-cta-inner { max-width: 680px; margin: 0 auto; }
.ab-cta h2 { font-size: clamp(36px, 4vw + 8px, 60px); line-height: 1.02; letter-spacing: -0.02em; margin-bottom: 18px; text-wrap: balance; }
.ab-cta p { color: var(--ink-soft); font-size: 18px; margin-bottom: 30px; }

@media (max-width: 820px) {
  .ab-head-inner { grid-template-columns: 1fr; gap: 32px; }
  .ab-head-portrait { justify-self: start; order: -1; }
  .ab-facts-inner { grid-template-columns: 1fr; gap: 24px; }
  .ab-creds-head { grid-template-columns: 1fr; gap: 14px; }
  .ab-creds-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 760px) {
  .ab-value { grid-template-columns: 1fr; gap: 8px; }
}
@media (max-width: 620px) {
  .ab-fact-list { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .ab-creds-grid { grid-template-columns: 1fr; }
}

/* =====================================================================
   CONTACT MODAL
   Opened by any element with class .open-contact (Book a call / intro).
   Submits to Formspree via AJAX, then shows an inline thank-you state.
   ===================================================================== */
.cf-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: clamp(16px, 5vh, 64px) 20px;
  overflow-y: auto;
  background: rgba(17, 20, 27, 0.55);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.cf-overlay.is-open { display: flex; opacity: 1; }

.cf-modal {
  position: relative;
  width: 100%;
  max-width: 520px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: clamp(28px, 4vw, 44px);
  box-shadow: 0 40px 80px -30px rgba(17, 20, 27, 0.55);
  transform: translateY(12px);
  transition: transform 0.25s ease;
}
.cf-overlay.is-open .cf-modal { transform: translateY(0); }

.cf-close {
  position: absolute;
  top: 16px; right: 16px;
  width: 36px; height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  line-height: 1;
  color: var(--ink-faint);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease;
}
.cf-close:hover { color: var(--ink); background: rgba(0,0,0,0.05); }

.cf-modal h2 {
  font-size: clamp(26px, 3vw, 34px);
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin-bottom: 8px;
}
.cf-intro { color: var(--ink-soft); font-size: 15px; margin-bottom: 26px; }

/* Spam honeypot. display:none keeps it out of the layout, the tab order, and the
   accessibility tree; only a bot filling every field will populate it, which
   tells Formspree to discard the submission. */
.cf-gotcha { display: none; }

.cf-field { margin-bottom: 18px; }
.cf-field label {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 7px;
}
.cf-field label .cf-opt { color: var(--ink-faint); font-weight: 400; }
.cf-field input,
.cf-field textarea {
  width: 100%;
  font-family: var(--sans);
  font-size: 15px;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line-ui);
  border-radius: 8px;
  padding: 12px 14px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.cf-field input::placeholder,
.cf-field textarea::placeholder { color: var(--ink-faint); }
.cf-field input:focus,
.cf-field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(47, 68, 179, 0.14);
}
.cf-field textarea { resize: vertical; min-height: 120px; line-height: 1.5; }

.cf-submit { width: 100%; border: none; cursor: pointer; margin-top: 6px; }
.cf-submit[disabled] { opacity: 0.6; cursor: default; transform: none; }

.cf-error {
  display: none;
  margin-top: 14px;
  font-size: 14px;
  color: #b3261e;
}
.cf-error.is-visible { display: block; }

/* thank-you state */
.cf-thanks { display: none; text-align: center; padding: 12px 0 4px; }
.cf-modal.is-sent .cf-form { display: none; }
.cf-modal.is-sent .cf-thanks { display: block; }
.cf-thanks-mark {
  width: 56px; height: 56px;
  margin: 0 auto 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  color: var(--accent);
  background: #e3e5f4;
  border-radius: 50%;
}
.cf-thanks h2 { margin-bottom: 12px; }
.cf-thanks p { color: var(--ink-soft); font-size: 16px; line-height: 1.55; max-width: 32ch; margin: 0 auto; }

body.cf-lock { overflow: hidden; }

/* =====================================================================
   404 PAGE
   Moved out of an inline <style> block in 404.html so the CSP can use
   style-src 'self' with no 'unsafe-inline'.
   ===================================================================== */
.nf-wrap { max-width: var(--max); margin: 0 auto; padding: clamp(80px, 14vw, 180px) var(--pad); text-align: center; }
.nf-wrap .eyebrow { justify-content: center; }
.nf-wrap h1 { font-size: clamp(40px, 8vw, 88px); line-height: 1; margin: 12px 0 18px; }
.nf-wrap p { color: var(--ink-soft); max-width: 46ch; margin: 0 auto 28px; }
.nf-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* =====================================================================
   MOTION LAYER
   Scroll-driven parallax and entrance animation.

   Three rules govern everything below:

   1. Purely additive. The whole layer sits inside
      @media (prefers-reduced-motion: no-preference) and
      @supports (animation-timeline: view()). A visitor who asks for
      reduced motion, or a browser without scroll-driven animation,
      gets exactly the page as it was. Nothing here is load-bearing.
   2. CSS only. The CSP is script-src 'self' with no 'unsafe-inline',
      so a CDN animation library would be blocked outright, and a
      hand-rolled scroll listener would risk jank. Scroll-driven CSS
      runs off the main thread instead.
   3. Compositor properties only (translate, scale, opacity). Nothing
      here can move layout, so none of it can cause CLS.
   ===================================================================== */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {

    /* ---- parallax: portrait monograms drift inside their clipped frames ---- */
    @keyframes cd-drift {
      from { translate: 0 -7%; }
      to   { translate: 0 7%; }
    }
    .hero-photo.photo-empty::after,
    .ab-head-portrait::after,
    .hero-photo img,
    .ab-head-portrait img {
      animation-name: cd-drift;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-duration: auto;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
    /* a real photo needs headroom so the drift never exposes an edge */
    .hero-photo img,
    .ab-head-portrait img { scale: 1.16; }

    /* ---- parallax: the oversized decorative numeral on the service card ---- */
    @keyframes cd-drift-sm {
      from { translate: 0 16px; }
      to   { translate: 0 -16px; }
    }
    .card-bignum {
      animation-name: cd-drift-sm;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-duration: auto;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }

    /* ---- scroll progress: a hairline accent across the top of the page ---- */
    body::before {
      content: "";
      position: fixed;
      inset: 0 0 auto 0;
      height: 2px;
      /* below the modal overlay (z-index 100) so it does not sit on top of
         the dimmed backdrop when the contact form is open */
      z-index: 90;
      background: var(--accent);
      transform-origin: 0 50%;
      scale: 0 1;
      animation-name: cd-progress;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-duration: auto;
      animation-timeline: scroll(root block);
    }
    @keyframes cd-progress {
      from { scale: 0 1; }
      to   { scale: 1 1; }
    }

    /* ---- entrance: hero settles on load, staggered ---- */
    @keyframes cd-rise {
      from { opacity: 0; translate: 0 18px; }
      to   { opacity: 1; translate: 0 0; }
    }
    .hero-copy > *,
    .ab-head-inner > div > * {
      animation: cd-rise 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
    }
    .hero-copy > :nth-child(1),
    .ab-head-inner > div > :nth-child(1) { animation-delay: 0.05s; }
    .hero-copy > :nth-child(2),
    .ab-head-inner > div > :nth-child(2) { animation-delay: 0.14s; }
    .hero-copy > :nth-child(3) { animation-delay: 0.23s; }
    .hero-copy > :nth-child(4) { animation-delay: 0.32s; }

    /* the portrait panel itself fades up alongside the copy */
    @keyframes cd-rise-panel {
      from { opacity: 0; translate: 0 26px; scale: 0.985; }
      to   { opacity: 1; translate: 0 0; scale: 1; }
    }
    .hero-photo,
    .ab-head-portrait {
      animation: cd-rise-panel 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.1s both;
    }
  }

  /* ---- hover: cards lift. Plain transitions, no scroll timeline needed. ---- */
  .ab-cred,
  .work-card {
    transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1),
                border-color 0.25s ease,
                box-shadow 0.25s ease;
  }
  .ab-cred:hover,
  .work-card:hover {
    transform: translateY(-3px);
    border-color: var(--line-ui);
    box-shadow: 0 18px 40px -28px rgba(20, 22, 28, 0.45);
  }
}
