/* ════════════════════════════════════════════════════════════════════════
   Site chrome — reset, nav, footer, case-study cross-nav, landing page.
   Each case study page (work/*.html) carries its own component CSS inline;
   this file holds only what is shared. See DESIGN-SYSTEM.md.
   ════════════════════════════════════════════════════════════════════════ */

/* ─── Reset & Base ─────────────────────────────────────────────────── */

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

:root {
  --black:       #111111;
  --gray-dark:   #444444;
  --gray-mid:    #888888;
  --gray-light:  #E8E8E8;
  --white:       #FFFFFF;
  --off-white:   #F9F9F9;

  --font-serif: 'DM Sans', system-ui, sans-serif;
  --font-sans:  'DM Sans', system-ui, sans-serif;

  --max-width:     1280px;
  --reading-width: 700px;
  --gutter:        56px;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
}

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

body {
  font-family: var(--font-sans);
  color: var(--black);
  background: var(--white);
  line-height: 1.6;
}

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

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

/* ─── Typography ───────────────────────────────────────────────────── */

h1, h2, h3 {
  font-family: var(--font-serif);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(2.25rem, 5vw, 4.5rem); }
h2 { font-size: clamp(1.6rem, 3vw, 2.5rem); }
h3 { font-size: clamp(1.15rem, 1.75vw, 1.5rem); }

p {
  font-size: 1rem;
  color: var(--gray-dark);
  max-width: var(--reading-width);
}

/* ─── Layout ───────────────────────────────────────────────────────── */

.container {
  width: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ─── Nav (case pages only — landing has no nav) ───────────────────── */

nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
}

.nav-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 60px;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.nav-name {
  font-family: var(--font-serif);
  font-size: 1.1rem;
  font-weight: 400;
  color: var(--white);
}

/* ─── Footer ─────────────────────────────────────────────────────────── */

footer {
  padding: 40px 0;
  background: var(--black);
}

.footer-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.footer-site {
  font-family: var(--font-sans); font-size: 0.9rem; letter-spacing: 0.02em;
  color: rgba(255,255,255,0.6); text-decoration: none; transition: color 0.2s;
}
.footer-site:hover { color: var(--white); }

/* ─── Case-study cross-nav (bottom of each case page) ────────────────── */

.case-nav {
  padding: 40px 0 44px;
  border-top: 1px solid var(--gray-light);
  background: var(--off-white);
}
/* Align the "More case studies" band to the same 1040px rail as the page content
   (its .container defaults to the wider 1280px shell, which overhangs to the left). */
.case-nav .container { max-width: var(--col-wide, 1040px); padding: 0 32px; }

.case-nav-kicker {
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--gray-mid); margin-bottom: 6px;
}

.case-nav-inner {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0 40px;
  border-top: 1px solid var(--gray-light);
  border-bottom: 1px solid var(--gray-light);
}

/* Compact thumbnail + text link, side by side — reads intentional at small sizes, unlike a
   shrunk version of the homepage's big overlay-text photo cards (tried that; too much dead
   space around tiny cards, and overlay text got cramped). A stacked single-column list
   (tried that too) left the row hugging the left edge with empty space beside it. */
.case-nav-item {
  display: flex; align-items: center; gap: 16px;
  padding: 20px 0;
  text-decoration: none; color: inherit;
}
.case-nav-item:not(:first-child) { border-left: 1px solid var(--gray-light); padding-left: 40px; }

@media (max-width: 640px) {
  .case-nav-inner { grid-template-columns: 1fr; }
  .case-nav-item:not(:first-child) { border-left: none; padding-left: 0; border-top: 1px solid var(--gray-light); }
}

.case-nav-thumb {
  flex: none; width: 60px; height: 60px; border-radius: 10px;
  background-size: cover; background-position: center;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
  transition: transform 0.3s ease;
}
.case-nav-item:hover .case-nav-thumb { transform: scale(1.05); }

.case-nav-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.case-nav-kick {
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--gray-mid);
}
.case-nav-title {
  font-family: var(--font-serif); font-weight: 700; font-size: 1.05rem; line-height: 1.3;
  color: var(--black); border-bottom: 1px solid transparent; transition: border-color 0.2s ease;
}
.case-nav-item:hover .case-nav-title { border-color: var(--black); }

.case-nav-arrow {
  margin-left: auto; flex: none; color: var(--gray-mid); font-size: 1.1rem; line-height: 1;
  transition: transform 0.25s ease, color 0.25s ease;
}
.case-nav-item:hover .case-nav-arrow { transform: translateX(4px); color: var(--black); }

/* ─── Case-page accents — one variant class per study ─────────────────── */

body.case-page--blue {
  --accent:      #3B69FF;
  --accent-dark: #1a3a8f;
  --accent-bg:   rgba(59, 105, 255, 0.06);
}

body.case-page--red {
  --accent:      #C41E1E;
  --accent-dark: #C41E1E;
  --accent-bg:   rgba(196, 30, 30, 0.06);
}

body.case-page--orchid {
  --accent:      #A650DB;
  --accent-dark: #692590;
  --accent-bg:   rgba(166, 80, 219, 0.06);
}

/* Nav — static home-page identity treatment, identical at every scroll position and consistent
   across all case pages. Theme-aware (see dark-mode block below). The scroll flip was removed
   (js/case-scroll.js no longer toggles .nav--light); the .nav--light rules below are inert. */

body.case-page nav {
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--gray-light);
}

body.case-page .nav-name { color: #111; font-family: var(--font-sans); font-weight: 800; letter-spacing: -0.01em; transition: color 0.2s ease; }

body.case-page nav.nav--light {
  background: rgba(255,255,255,0.96);
  border-bottom-color: var(--gray-light);
}
body.case-page nav.nav--light .nav-name { color: var(--black); }

/* Tagline beside the name — the homepage .d-tag treatment, but at the
   nav-name's size and light weight. Hidden on small screens. */
/* translateY: DM Sans's ascent (17px) far outweighs its descent (5px), so the glyph ink
   sits ~1.7px below the bar's geometric center — nudge up so the identity reads centered */
/* align-items: center, NOT baseline — the tag is 0.72rem against the name's 1.1rem, so a
   shared baseline hangs the smaller text off the name's bottom edge */
.nav-id { display: flex; align-items: center; gap: 10px; min-width: 0; transform: translateY(-1.5px); }
body.case-page .nav-tag {
  font-family: var(--font-sans); font-size: 0.72rem; font-weight: 300;
  letter-spacing: -0.01em; white-space: nowrap;
  color: var(--black); transition: color 0.2s ease;
}
body.case-page nav.nav--light .nav-tag { color: var(--black); }
:root[data-theme="dark"] body.case-page nav.nav--light .nav-tag { color: rgba(255, 255, 255, 0.55); }
@media (max-width: 640px) { body.case-page .nav-tag { display: none; } }

/* ─── Case-page top-nav links (About me · Case studies ▾ · Resume) ────── */

.navlinks { display: flex; align-items: center; gap: clamp(16px, 2.2vw, 30px); }
.navlink {
  font-family: var(--font-sans); font-size: 0.9rem; font-weight: 700;
  color: #111; text-decoration: none; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 5px; transition: color 0.2s ease;
}
.navlink:hover { color: #000; }
/* Underline on hover for the three primary nav links (About me / Resume / Reach out),
   mirroring the home-page .d-email:hover interaction. Scoped to direct children so the
   nested "Case Studies" dropdown trigger is excluded. Color is left to each nav state. */
.navlinks > .navlink:hover { text-decoration: underline; text-underline-offset: 3px; }
.navlink svg { width: 1em; height: 1em; }
/* Hamburger toggle — hidden on desktop, revealed under 640px (see media query below).
   Pure CSS: a visually-hidden checkbox holds open/closed state; the label is the icon. */
.navtoggle { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.navburger { display: none; }
/* After scroll the nav frosts white — links flip to dark ink, hover to black (gold is weak on white) */
body.case-page nav.nav--light .navlink { color: var(--gray-dark); }
body.case-page nav.nav--light .navlink:hover { color: var(--black); }

/* "Case studies" dropdown */
.navdrop { position: relative; }
.navcaret { transition: transform 0.2s ease; }
.navdrop:hover .navcaret, .navdrop:focus-within .navcaret { transform: rotate(180deg); }
.navdrop-menu {
  position: absolute; top: calc(100% + 12px); right: 0; min-width: 236px;
  background: rgba(20,20,22,0.97); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255,255,255,0.1); border-radius: 12px; padding: 7px;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  box-shadow: 0 18px 50px rgba(0,0,0,0.5);
}
.navdrop:hover .navdrop-menu, .navdrop:focus-within .navdrop-menu { opacity: 1; visibility: visible; transform: translateY(0); }
/* Invisible bridge across the 12px gap so :hover survives the trip from the trigger down to
   the items — without it the cursor crosses empty space and the menu vanishes before you click. */
.navdrop-menu::before { content: ''; position: absolute; left: 0; right: 0; top: -16px; height: 16px; }
.navdrop-item { display: flex; gap: 11px; align-items: baseline; padding: 9px 11px; border-radius: 8px; text-decoration: none; transition: background 0.18s ease; }
.navdrop-item:hover { background: rgba(255,255,255,0.07); }
.navdrop-num { font-size: 0.64rem; font-weight: 700; letter-spacing: 0.1em; color: #FFC000; flex: none; width: 16px; }
.navdrop-t { display: flex; flex-direction: column; gap: 1px; }
.navdrop-name { font-size: 0.85rem; font-weight: 600; color: #fff; line-height: 1.2; }
.navdrop-sub { font-size: 0.66rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: #9a9a9e; }
.navdrop-item.is-current { opacity: 0.45; pointer-events: none; } /* the study you're already on */

/* ── Mobile: collapse the links into a tap-to-open panel (≤640px) ──────── */
@media (max-width: 640px) {
  .navburger {
    display: flex; flex-direction: column; justify-content: center; gap: 5px;
    width: 40px; height: 40px; padding: 9px; margin-right: -9px; cursor: pointer;
  }
  .navburger span {
    display: block; height: 2px; border-radius: 2px; background: var(--black);
    transition: transform 0.25s ease, opacity 0.2s ease, background 0.35s ease;
  }
  /* burger morphs to an X when the menu is open */
  .navtoggle:checked ~ .navburger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .navtoggle:checked ~ .navburger span:nth-child(2) { opacity: 0; }
  .navtoggle:checked ~ .navburger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .navlinks {
    display: none;
    position: absolute; top: 100%; right: 12px; margin-top: 6px;
    flex-direction: column; align-items: stretch; gap: 2px;
    min-width: 240px; padding: 10px;
    background: rgba(20,20,22,0.98); border: 1px solid rgba(255,255,255,0.1); border-radius: 12px;
    box-shadow: 0 18px 50px rgba(0,0,0,0.5);
  }
  .navtoggle:checked ~ .navlinks { display: flex; }
  /* links stay light on the dark panel even when the bar itself is frosted white */
  .navlink, body.case-page nav.nav--light .navlink { color: rgba(255,255,255,0.9); padding: 10px 11px; }
  .navlink:hover, body.case-page nav.nav--light .navlink:hover { color: #FFC000; }
  .navcaret { display: none; }

  /* case studies shown expanded inline — hover popovers don't work on touch */
  .navdrop-menu {
    position: static; opacity: 1; visibility: visible; transform: none;
    min-width: 0; margin: 0; padding: 2px 0 6px;
    background: transparent; border: 0; box-shadow: none;
  }
  .navdrop-menu::before { display: none; }
  .navdrop-item { padding: 8px 11px 8px 14px; }
}

body.case-page .case-nav {
  background: var(--off-white);
  border-top: 1px solid var(--gray-light);
}

body.case-page footer { background: var(--black); }

/* ── Timeline horizontal-scroll affordance ─────────────────────────────────
   The Gantt timelines scroll sideways on narrow screens. js/timeline-scroll.js
   wraps each one in a .tl-frame and toggles state classes from scroll position;
   here we draw the edge fades (only toward content that exists) and a one-time
   "Swipe →" hint. --tl-bg is set per-timeline in JS to match its section bg. */
.tl-frame { position: relative; }
.tl-fade {
  position: absolute; top: 0; bottom: 0; width: 46px; z-index: 4;
  pointer-events: none; opacity: 0; transition: opacity 0.3s ease;
}
.tl-fade--right { right: 0; background: linear-gradient(to right, transparent, var(--tl-bg, #fff)); }
.tl-fade--left  { left: 0;  background: linear-gradient(to left,  transparent, var(--tl-bg, #fff)); }
.tl-frame.is-scrollable:not(.at-end)   .tl-fade--right { opacity: 1; }
.tl-frame.is-scrollable:not(.at-start) .tl-fade--left  { opacity: 1; }

.tl-hint {
  display: none; margin-top: 10px; padding-inline: 32px; text-align: right;
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.06em;
  color: var(--accent, #555); transition: opacity 0.35s ease;
}
.tl-frame.is-scrollable + .tl-hint { display: block; }   /* only when it actually scrolls */
.tl-frame.scrolled + .tl-hint { opacity: 0; }             /* fade out after the first swipe */
.tl-hint-arrow { display: inline-block; }
@media (prefers-reduced-motion: no-preference) {
  .tl-hint-arrow { animation: tl-nudge 1.3s ease-in-out infinite; }
}
@keyframes tl-nudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(4px); } }
/* the written hint is a touch cue — keep it to narrow screens; the fade stands on wider ones */
@media (min-width: 901px) { .tl-frame + .tl-hint { display: none !important; } }

/* ── Mobile: let the hero grow to fit its content ──────────────────────────
   Each page's inline hero is a fixed 86–88vh box with overflow:hidden and its
   content bottom-anchored (align-items:flex-end). On short/standard phones the
   kicker + headline + dek + meta stack taller than that box, so the top of the
   content (kicker + whole headline) clipped up behind the fixed nav. height:auto
   lets the box grow to fit; a min-height keeps it a full hero when content is
   short; padding-top clears the nav. This rule outspecifies the inline `.hero`. */
@media (max-width: 700px) {
  body.case-page .hero { height: auto; min-height: 84vh; padding-top: 74px; }
  body.case-page .hero-content { padding: 0 24px 9vh; }
  /* Every hero fact stays on phones, markets and flags included. Two columns keeps the
     labels legible at 390px. A multi-market fact spans the full row so its flag pills wrap
     across the width; a single-market fact (just one flag) stays in its grid cell so it
     doesn't waste a whole row — keeps the block to two rows instead of three. */
  body.case-page .hero-facts { gap: 16px 24px; }
  body.case-page .hf:has(.hf-mkt .mkt + .mkt) { grid-column: 1 / -1; }
  body.case-page .hf-mkt { flex-wrap: wrap; }
}

/* ─── Landing page (index.html — identity + three featured plates) ────── */

/* Rainbow animation primitives — no longer used by the landing cards (the red
   progress-bar treatment replaced the ring), but the XR case page's ring and
   the .rf-spark AI mark still animate with these. Keep. */
@keyframes rainbow-shimmer {
  0%   { background-position: 0% center; }
  100% { background-position: 200% center; }
}

@property --border-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

@keyframes spin-border {
  to { --border-angle: 360deg; }
}

body.landing {
  background: #FFFFFF;
}

.dstage {
  height: 100vh;
  display: flex;
  flex-direction: column;
  padding: clamp(36px, 5vh, 60px) clamp(40px, 4vw, 72px);
  overflow: hidden;
  background: #fff;
}

.d-id { flex: 0 0 auto; display: flex; justify-content: space-between; align-items: center; gap: 24px; }
/* Header right group: nav links + dark-mode toggle, vertically centered against the
   whole name block (.d-idlock is two rows tall: name/tag, then "currently @"). */
.d-id-nav {
  flex: 0 0 auto; align-self: center;
  display: flex; align-items: center; gap: clamp(16px, 2.2vw, 30px);
}
.d-links {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: clamp(16px, 1.6vw, 22px);
}
/* On narrow screens the nav can't share the row with the name/roles — wrap it below. */
@media (max-width: 860px) {
  .d-id { flex-wrap: wrap; }
  .d-id-nav { align-self: flex-start; margin-top: 14px; }
}
.d-email {
  font-size: clamp(1rem, 1.3vw, 1.12rem); font-weight: 700;
  color: #111; text-decoration: none; white-space: nowrap; transition: color 0.2s;
}
.d-email:hover { color: #000; text-decoration: underline; text-underline-offset: 3px; }
/* Current section — faded, non-interactive ("Case Studies" on the homepage, which is this page) */
.d-email--current { color: var(--gray-mid); opacity: 0.55; pointer-events: none; cursor: default; }
:root[data-theme="dark"] .d-email--current { color: rgba(255,255,255,0.5); }
/* Copy-to-clipboard confirmation box for "Reach out" links (homepage + about).
   box-shadow (not padding) draws the box so neighboring text doesn't shift. */
.d-email-copy { border-radius: 6px; transition: color 0.2s, background-color 0.2s, box-shadow 0.2s; }
.d-email-copy.is-copied {
  color: var(--gray-dark); background: var(--gray-light); box-shadow: 0 0 0 6px var(--gray-light);
}
.d-sep { font-size: clamp(1rem, 1.3vw, 1.12rem); font-weight: 300; color: #6a6a6a; user-select: none; }
.d-email-face { width: 1.05em; height: 1.05em; vertical-align: -0.16em; margin-left: 2px; }
.d-at { vertical-align: 0.04em; }
/* Masthead lockup: name + roles share one line, matched in size — name bold, roles light. */
.d-idlock { position: relative; display: flex; align-items: center; flex-wrap: wrap; column-gap: clamp(10px, 1vw, 18px); row-gap: 4px; }
.d-name { font-family: var(--font-serif); font-size: clamp(1.3rem, 1.8vw, 1.85rem); font-weight: 800; letter-spacing: -0.01em; line-height: 1.2; color: #111; }
/* Tagline beside the name — light weight, muted; baseline-aligned via .d-idlock */
.d-tag { font-family: var(--font-sans); font-size: clamp(1.3rem, 1.8vw, 1.85rem); font-weight: 300; letter-spacing: -0.01em; line-height: 1.2; color: var(--gray-mid); }
:root[data-theme="dark"] .d-tag { color: #FFC000; }
/* Role/affiliation line — small, lightweight; black in light mode, gold in dark
   (matches the name/nav). Sits on its own line beneath the name, left-aligned. */
/* Sized to its own content, not the lockup: .d-idlock is only as wide as the name,
   so without this the line would wrap into a narrow column beneath it. Capped to the
   page's content width so it still wraps (rather than overflowing) on small screens. */
.d-now { position: absolute; top: 100%; left: 0; margin-top: 3px; width: max-content; max-width: calc(100vw - 2 * clamp(40px, 4vw, 72px)); font-family: var(--font-sans); font-size: 0.98rem; font-weight: 300; letter-spacing: -0.01em; line-height: 1.2; color: #111; }
:root[data-theme="dark"] .d-now { color: #FFC000; }
/* Narrow screens wrap the line to two lines, and an absolutely positioned element
   reserves no height — it would sit on top of the nav. In-flow on its own row
   (flex-basis:100% forces the wrap) it pushes the nav down instead. Must come after
   the base rule above: same specificity, so source order decides. */
@media (max-width: 860px) {
  .d-now { position: static; flex: 0 0 100%; width: auto; max-width: none; margin-top: 6px; }
}
/* The "currently @" link shimmers so it reads as clickable at rest. A bright
   band sweeps across the text via background-clip:text, and a faint underline
   sits beneath it (solid on hover) to confirm it's a link. Base/highlight
   colours are set per-theme below. */
.d-now-link { text-decoration: none; border-bottom: 1px solid color-mix(in srgb, currentColor 35%, transparent); transition: border-color 0.2s ease; background-image: linear-gradient(100deg, var(--shimmer-base) 0%, var(--shimmer-base) 40%, var(--shimmer-glow) 50%, var(--shimmer-base) 60%, var(--shimmer-base) 100%); background-size: 200% auto; background-clip: text; -webkit-background-clip: text; color: transparent; -webkit-text-fill-color: transparent; }
.d-now-link { --shimmer-base: #111; --shimmer-glow: #9a9a9a; }
:root[data-theme="dark"] .d-now-link { --shimmer-base: #FFC000; --shimmer-glow: #FFF3C4; }
.d-now-link:hover { border-bottom-color: currentColor; }
@media (prefers-reduced-motion: no-preference) {
  .d-now-link { animation: d-now-shimmer 3.2s linear infinite; }
}
@keyframes d-now-shimmer {
  0%   { background-position: 100% center; }
  100% { background-position: -100% center; }
}

/* Editorial hero statement — the page's opening line. Regular weight, one colour;
   only the method phrase ("how I scope and execute research") is bolded for emphasis. */
.d-statement {
  flex: 0 0 auto;
  font-family: var(--font-serif); font-weight: 400; line-height: 1.18; letter-spacing: -0.015em;
  color: #111; text-wrap: pretty;
  /* End the statement at the right edge of the middle thumbnail: cols 1+2 of the
     1.5fr/1.12fr/1.12fr grid = 2.62/3.74 ≈ 70.05%, plus the one gap between them. */
  max-width: calc(70.05% - 0.401 * clamp(16px, 1.6vw, 26px));
  /* Same type size as the thumbnail titles (.d-head) */
  font-size: clamp(1.3rem, 1.8vw, 1.85rem);
  /* Sit low, near the cards: the extra space goes ABOVE the statement so the
     cards keep their original height (this margin + .d-body's sum to the original gap). */
  margin: clamp(60px, 11vh, 124px) 0 0;
}
.d-statement strong { font-weight: 700; }
/* "A few recent studies:" — upright, light-weight, and inherits the statement
   color (near-white in dark mode) rather than a muted grey. The 300 weight keeps
   it distinct from the 400 statement without italic. */
.d-statement em { font-style: normal; font-weight: 300; color: inherit; }
/* Lede variant above the case-study cards: same size and slot as the statement,
   but the masthead .d-tag treatment — sans, light weight, muted. */
.d-statement--lede {
  font-family: var(--font-sans); font-weight: 300; line-height: 1.2;
  letter-spacing: -0.01em; color: var(--gray-mid);
}

/* Roles: same size as the name, light weight, muted — sits inline right after "Kate Crotty". */
.d-roles { font-size: clamp(1.02rem, 1.15vw, 1.2rem); font-weight: 300; color: #6a6a6a; letter-spacing: -0.01em; max-width: none; }
.d-aff {
  position: relative; font-size: inherit; font-weight: inherit; text-decoration: none;
}
.d-aff-name {
  color: inherit;
}
.d-name-link {
  color: inherit; text-decoration: none;
}

/* Body: three featured plates of equal weight */
.d-body {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
  /* Modest breathing room below the statement — kept tight so it sits near the cards. */
  margin-top: clamp(12px, 2.5vh, 28px);
}
.d-feats-kick {
  flex: 0 0 auto; max-width: none;
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: #a6a6a6;
  margin-bottom: clamp(12px, 1.6vh, 18px);
}
.d-feats {
  flex: 1 1 auto; min-height: 0;
  /* Plate 01 is the hero — wider than 02 & 03, which stay equal and slightly narrower */
  display: grid; grid-template-columns: 1.5fr 1.12fr 1.12fr; gap: clamp(16px, 1.6vw, 26px);
}

/* Each featured study — one clickable, lit plate */
.d-feat { display: flex; min-height: 0; text-decoration: none; color: inherit; cursor: pointer; }
.d-plate {
  position: relative; flex: 1 1 auto; width: 100%; min-height: 300px; border-radius: 16px; overflow: hidden;
  filter: saturate(1.06);
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.4s ease, filter 0.4s ease;
}
/* Plates render at full brightness in both themes so the overlaid title reads pure white.
   Dark mode re-darkens the IMAGE ONLY via a uniform layer in .d-plate::before (below the text),
   preserving the dimmer at-rest look without greying the type (a filter would dim the text too). */
.d-plate--xr     { background: url('../images/xr-mixed-reality-hero.jpg') 32% center / cover; }
.d-plate--search { background: url('../images/search-inclusion-banner.jpg') 46% top / cover; }
/* Older-adults portrait — framed on the two faces; warm tone as fallback. */
.d-plate--access { background: url('../images/accessibility-older-adults.jpg') center 38% / cover no-repeat, linear-gradient(150deg, #6b5744 0%, #4a3c30 60%, #2c2420 100%); }
/* Hover: the plate stays put — the gold progress bar fills, the title lights gold, and the description brightens */
/* Bottom scrim so the title + description stay legible over the photo */
.d-plate::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to top, rgba(0,0,0,0.72) 0%, rgba(0,0,0,0.3) 34%, rgba(0,0,0,0) 55%);
}
/* Dark mode: uniform ~18% darken over the image (sits below the z-index:3 text, so the title
   stays pure white) — replaces the old brightness(0.82) filter that greyed the type. */
:root[data-theme="dark"] .d-plate::before {
  background: linear-gradient(rgba(0,0,0,0.18), rgba(0,0,0,0.18)),
              linear-gradient(to top, rgba(0,0,0,0.72) 0%, rgba(0,0,0,0.3) 34%, rgba(0,0,0,0) 55%);
}
/* Progress-bar track along the bottom edge. Must sit BELOW the .d-line gold fill:
   a pseudo-element paints after child elements at equal z-index, so an equal
   z-index would veil the gold with 45% white (washing it out). */
.d-plate::after {
  content: ''; position: absolute; inset: auto 0 0 0; height: 4px; z-index: 1;
  background: rgba(255, 255, 255, 0.45); pointer-events: none;
}
:root[data-theme="dark"] .d-plate::after { background: rgba(255, 255, 255, 0.28); }
/* Red fill: stub at rest, stretches slowly across on hover, retracts quickly on
   exit (asymmetric durations — slow rewind reads as lag). scaleX, not width,
   so the grow animates on the compositor. */
.d-line {
  position: absolute; left: 0; right: 0; bottom: 0; height: 4px; z-index: 2;
  background: #FFC000; pointer-events: none;
  transform: scaleX(0.18); transform-origin: left;
  transition: transform 0.3s ease;
}
.d-feat:hover .d-line { transform: scaleX(1); transition: transform 0.9s cubic-bezier(0.25, 1, 0.5, 1); }
@media (prefers-reduced-motion: reduce) {
  .d-line, .d-feat:hover .d-line { transition: none; }
}
/* Title + description flow together in one bottom-anchored group above the bar */
.d-plate-foot {
  position: absolute; z-index: 3; left: 18px; right: 18px; bottom: 16px;
}
.d-title {
  /* Same size and tracking as the masthead name and the lede above the cards. */
  font-size: clamp(1.3rem, 1.8vw, 1.85rem); font-weight: 800; line-height: 1.05;
  letter-spacing: -0.01em; text-transform: uppercase; color: #fff;
  text-shadow: 0 1px 12px rgba(0,0,0,0.5);
  transition: color 0.3s ease;
}
.d-feat:hover .d-title { color: #FFC000; }
.d-desc {
  margin-top: 7px; max-width: 42ch;
  font-size: 0.98rem; font-weight: 400; line-height: 1.45; letter-spacing: 0.01em;
  color: rgba(255,255,255,0.88); text-shadow: 0 1px 10px rgba(0,0,0,0.55);
  transition: color 0.3s ease;
}
.d-feat:hover .d-desc { color: #fff; }

@media (max-width: 900px) {
  .dstage { height: auto; min-height: 100vh; overflow: visible; padding: clamp(28px, 4vh, 48px) clamp(22px, 5vw, 40px) 40px; }
  .d-feats { grid-template-columns: 1fr; gap: 18px; }
  /* Stacked full-width cards: only a short title + two-line description sit on the
     photo now, so 4:3 gives enough clearance without the old portrait height. */
  .d-feat { display: block; }
  .d-plate { min-height: 0; aspect-ratio: 4 / 3; }
}

/* ─── Responsive ─────────────────────────────────────────────────────── */

@media (max-width: 960px) {
  :root { --gutter: 32px; }
}

@media (max-width: 600px) {
  :root { --gutter: 20px; }
}

/* ════════════════════════════════════════════════════════════════════════
   THEME TOGGLE — pill switch, top-right of the landing header.
   ════════════════════════════════════════════════════════════════════════ */
.theme-toggle-wrap { position: relative; flex: 0 0 auto; align-self: center; line-height: 0; }
.theme-toggle-arrow {
  position: absolute; left: 50%; bottom: calc(100% + 2px); transform: translateX(-50%);
  color: #FFC000; pointer-events: none;
}
.theme-toggle-arrow svg { display: block; width: 20px; height: 29px; }
@keyframes theme-arrow-bob { 0%, 100% { transform: translate(-50%, 0); } 50% { transform: translate(-50%, 5px); } }
@media (prefers-reduced-motion: no-preference) {
  .theme-toggle-arrow { animation: theme-arrow-bob 1.5s ease-in-out infinite; }
}
.theme-toggle {
  flex: 0 0 auto; align-self: center; padding: 0; border: none; background: none;
  cursor: pointer; line-height: 0; -webkit-tap-highlight-color: transparent;
}
.theme-toggle-track {
  position: relative; display: flex; align-items: center; justify-content: center;
  width: 150px; height: 34px; border-radius: 999px; background: #e7e7e7;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.09); transition: background 0.35s ease, box-shadow 0.35s ease;
}
.theme-toggle-label {
  position: relative; z-index: 1; margin: 0 8px 0 33px;
  font-family: var(--font-sans); font-size: 0.82rem; font-weight: 500; letter-spacing: -0.01em;
  color: #6a6a6a; white-space: nowrap; transition: color 0.35s ease, margin 0.35s ease;
}
.theme-toggle-knob {
  position: absolute; left: 3px; top: 3px; width: 28px; height: 28px; border-radius: 50%; z-index: 2;
  background: #ffffff; box-shadow: 0 2px 6px rgba(0,0,0,0.25);
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), background 0.35s ease;
}
.theme-toggle:focus-visible .theme-toggle-track { outline: 2px solid #4d96ff; outline-offset: 3px; }

/* Compact icon-only toggle — used in the case-study nav bar (the long labelled pill lives on the
   homepage only). Sun/moon swap is driven purely by the :root[data-theme] the shared theme.js sets. */
.theme-mini {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; border: none; border-radius: 50%;
  background: rgba(255, 255, 255, 0.14); color: rgba(255, 255, 255, 0.82);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background 0.2s ease, color 0.2s ease;
}
.theme-mini:hover { color: #FFC000; background: rgba(255, 255, 255, 0.24); }
.theme-mini:focus-visible { outline: 2px solid #4d96ff; outline-offset: 2px; }
.theme-mini svg { display: block; width: 16px; height: 16px; }
.theme-mini .icon-sun { display: none; }
.theme-mini .icon-moon { display: block; }
:root[data-theme="dark"] .theme-mini .icon-sun { display: block; }
:root[data-theme="dark"] .theme-mini .icon-moon { display: none; }
/* Static case-page nav: home-style chip — ink-on-faint-dark in light, light-on-faint-light in dark */
body.case-page .theme-mini { color: var(--gray-dark); background: rgba(0, 0, 0, 0.06); }
body.case-page .theme-mini:hover { color: var(--black); background: rgba(0, 0, 0, 0.1); }
:root[data-theme="dark"] body.case-page .theme-mini { color: rgba(255, 255, 255, 0.82); background: rgba(255, 255, 255, 0.12); }
:root[data-theme="dark"] body.case-page .theme-mini:hover { color: #FFC000; background: rgba(255, 255, 255, 0.22); }
/* Homepage: the toggle sits on the page background (not a dark hero), so invert the chip —
   ink-on-faint-dark in light mode, light-on-faint-light in dark mode. */
.d-id-nav .theme-mini { color: var(--gray-dark); background: rgba(0, 0, 0, 0.06); }
.d-id-nav .theme-mini:hover { color: var(--black); background: rgba(0, 0, 0, 0.1); }
:root[data-theme="dark"] .d-id-nav .theme-mini { color: rgba(255, 255, 255, 0.82); background: rgba(255, 255, 255, 0.12); }
:root[data-theme="dark"] .d-id-nav .theme-mini:hover { color: #FFC000; background: rgba(255, 255, 255, 0.22); }

/* ════════════════════════════════════════════════════════════════════════
   DARK MODE — set data-theme="dark" on <html> (js/theme.js).
   Light values live throughout the file; this block re-points the surfaces.
   ════════════════════════════════════════════════════════════════════════ */
:root[data-theme="dark"] {
  --gray-dark:  #bcc1c9;
  --gray-mid:   #9096a0;
  --gray-light: #363c48;   /* hairlines/borders — lifted so dividers read on dark */
  --off-white:  #14171d;
}
:root[data-theme="dark"] body { background: #0f1116; color: #e8eaee; }

/* Landing */
:root[data-theme="dark"] body.landing,
:root[data-theme="dark"] .dstage { background: #0f1116; }
:root[data-theme="dark"] .d-name,
:root[data-theme="dark"] .d-name-link { color: #FFC000; }
:root[data-theme="dark"] .d-statement { color: #eceef1; }
:root[data-theme="dark"] .d-statement em { color: inherit; }
/* The lede keeps the .d-tag gold rather than the statement's near-white. */
:root[data-theme="dark"] .d-statement--lede { color: #FFC000; }
:root[data-theme="dark"] .d-roles,
:root[data-theme="dark"] .d-sep,
:root[data-theme="dark"] .d-aff-name { color: #969ca5; }
:root[data-theme="dark"] .d-email { color: #FFC000; }
:root[data-theme="dark"] .d-email:hover,
:root[data-theme="dark"] .d-name-link:hover { color: #FFD24A; }

/* Toggle in dark */
:root[data-theme="dark"] .theme-toggle-label { color: #c8ccd2; margin: 0 33px 0 8px; }
:root[data-theme="dark"] .theme-toggle-track { background: #3a4150; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.12); }
:root[data-theme="dark"] .theme-toggle-knob { transform: translateX(116px); background: #f2f3f5; }

/* Case-page component surfaces: flip the shared/inline vars.
   --black is used only as text here (footer/navburger bg overridden below). */
:root[data-theme="dark"] .feature {
  --black: #f1f2f4;
  --ink:   #d6dae0;
  --paper: #15181e;
  --white: #1f232c;
  --accent-bg: rgba(255,255,255,0.05);
  --accent-lt: var(--accent);
}
/* Dark mode: every case study rides the site's gold accent regardless of its light-mode hue
   (blue / red / orchid). Overriding --accent alone recolors kickers, section rules, numbers,
   borders, drop-caps, and me-tags — because --accent-dark, --accent-lt, and the outcome
   numbers all point back at --accent in dark mode. */
:root[data-theme="dark"] body.case-page--blue,
:root[data-theme="dark"] body.case-page--red,
:root[data-theme="dark"] body.case-page--orchid {
  --accent: #FFC000;
}
/* Lessons band + concept results use --accent-dark (a dark shade for light bg);
   on dark, point it at the bright accent so it matches the section kickers. */
:root[data-theme="dark"] body.case-page { --accent-dark: var(--accent); }
/* Timeline grid + pod-list dividers are hardcoded black hairlines — flip to light */
:root[data-theme="dark"] body.case-page--blue .tl-lanes { background-image: repeating-linear-gradient(to right, rgba(255,255,255,0.055) 0, rgba(255,255,255,0.055) 1px, transparent 1px, transparent 5%); }
:root[data-theme="dark"] body.case-page--orchid .tl-lanes { background-image: repeating-linear-gradient(to right, rgba(255,255,255,0.055) 0, rgba(255,255,255,0.055) 1px, transparent 1px, transparent 5.5556%); }
/* Timeline phase rules are hardcoded purple shades in the page CSS — ride gold shades on dark */
:root[data-theme="dark"] body.case-page--orchid .tl-phase--p2 { border-top-color: #FFC000; }
:root[data-theme="dark"] body.case-page--orchid .tl-phase--p3 { border-top-color: rgba(255, 192, 0, 0.55); }
:root[data-theme="dark"] body.case-page--red  .tl-lanes { background-image: repeating-linear-gradient(to right, rgba(255,255,255,0.055) 0, rgba(255,255,255,0.055) 1px, transparent 1px, transparent 8.33%); }
:root[data-theme="dark"] .pods-list { border-top-color: rgba(255,255,255,0.14); }
:root[data-theme="dark"] .pod-line  { border-bottom-color: rgba(255,255,255,0.14); }
:root[data-theme="dark"] .outcome { background: #08090c; }
/* Outcome act-number + impact-numbers use a lighter accent for the light-mode dark band;
   on dark, match them to the section accent (same as the "03" act number). */
:root[data-theme="dark"] .outcome .act-num { -webkit-text-stroke-color: var(--accent); }
:root[data-theme="dark"] .outcome .impact-num { color: var(--accent); }
:root[data-theme="dark"] body.case-page footer { background: #0a0b0e; }

/* Case-page nav in dark mode — solid dark bar, gold name + links (mirrors the homepage identity nav) */
:root[data-theme="dark"] body.case-page nav { background: rgba(14,15,19,0.94); border-bottom-color: #2c313a; }
:root[data-theme="dark"] body.case-page .nav-name { color: #FFC000; }
:root[data-theme="dark"] body.case-page .nav-tag  { color: rgba(255,255,255,0.55); }
:root[data-theme="dark"] body.case-page .navlink  { color: #FFC000; }
:root[data-theme="dark"] body.case-page .navlink:hover { color: #FFD24A; }
:root[data-theme="dark"] body.case-page .navburger span { background: #e8eaee; }
:root[data-theme="dark"] .navdrop-menu { background: #171a20; box-shadow: 0 18px 40px rgba(0,0,0,0.5); }

/* Small light-chip surfaces on the case pages → muted dark. The glyph tokens (--gy-ink line/screen,
   --gy-lens lens fill) flip too: light ink + a tinted-dark lens so each device reads on its dark tile
   (the hardcoded #2b2b2b ink used to vanish here). */
:root[data-theme="dark"] .spectrum-icon { --gy-ink: #d4d9e1; }
:root[data-theme="dark"] .spectrum-icon--immersive { background: #1a2030; --gy-lens: #333e63; }
:root[data-theme="dark"] .spectrum-icon--blend     { background: #16241f; --gy-lens: #294138; }

/* Page navigation is plain native MPA — no view transitions. The animated
   crossfade read as choppy/fragmented (the fixed nav ghosting against the
   homepage's inline header), so navigations now just swap instantly. */
:root[data-theme="dark"] .spectrum-icon--ambient   { background: #241f14; --gy-lens: #423a22; }

/* ════════════════════════════════════════════════════════════════
   QUICK SUMMARY — the paper band under each case hero. Summary prose
   left (the study, role, and impact in one paragraph); "Read this
   study for" right as a compact icon list of claim labels.
════════════════════════════════════════════════════════════════ */
/* A paper band — the site's "step outside the narrative" plane — so the strip
   reads as an aside to the reader, not more data (the stat stacks own the
   tick + number vocabulary). Full-bleed background, content on the 1040 rail. */
.readfor {
  background: var(--paper, #F7F4EE);
  padding: 26px max(32px, calc((100% - 1040px) / 2 + 32px)) 30px;
  display: grid; grid-template-columns: 7fr 5fr; gap: 48px;
}
.readfor-lab {
  font-family: var(--font-sans); font-size: var(--t-label, 0.72rem); font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent); margin-bottom: 12px;
}
.readfor-sum p:not(.readfor-lab) {
  font-size: var(--t-body, 1rem); line-height: 1.62; max-width: 640px;
  text-wrap: pretty; color: var(--ink);
}
.readfor-sum strong { font-weight: 700; color: var(--black); }
.readfor-side {
  border-left: 1px solid rgba(0, 0, 0, 0.12); padding-left: 28px; align-self: center;
}
.rf-row { display: flex; align-items: center; gap: 10px; }
.rf-row + .rf-row { margin-top: 10px; }
.rf-row p { font-size: var(--t-caption, 0.8125rem); font-weight: 700; color: var(--black); line-height: 1.35; }
/* Claim glyphs — line icons in the case pages' device-glyph language
   (accent strokes, rounded geometry), inline at list size. */
.rf-icon { width: 22px; height: 22px; flex: 0 0 22px; }
.rf-icon svg { width: 100%; height: 100%; display: block; }
/* The AI claim wears the site's AI mark: the spark, masked and filled with
   the flowing rainbow (rainbow-shimmer keyframes above). */
/* A spark pair cut from the ring treatment's ROTATING conic rainbow —
   color flows around each shape (no sweep direction), and each spark
   twinkles on its own beat. Soft halo via drop-shadow follows the stars. */
.rf-spark { position: relative; display: block; width: 22px; height: 22px;
  filter: drop-shadow(0 1px 5px rgba(120, 110, 255, 0.28)); }
.rf-spark::before, .rf-spark::after {
  content: ''; position: absolute;
  background: conic-gradient(from var(--border-angle), #ff6b6b, #ffa858, #ffd93d, #6bcb77, #4d96ff, #a855f7, #ff6b6b);
  -webkit-mask: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"%3E%3Cpath d="M12 2l2.2 7.8L22 12l-7.8 2.2L12 22l-2.2-7.8L2 12l7.8-2.2z"/%3E%3C/svg%3E') center / contain no-repeat;
  mask: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"%3E%3Cpath d="M12 2l2.2 7.8L22 12l-7.8 2.2L12 22l-2.2-7.8L2 12l7.8-2.2z"%2F%3E%3C/svg%3E') center / contain no-repeat;
  animation: spin-border 5s linear infinite, rf-twinkle 3.4s ease-in-out infinite;
}
.rf-spark::before { left: 0; bottom: 0; width: 15px; height: 15px; }
.rf-spark::after  { right: 1px; top: 0; width: 8px; height: 8px; animation-delay: 0s, -1.7s; }
@keyframes rf-twinkle {
  0%, 100% { transform: scale(1) rotate(0deg); opacity: 1; }
  50%      { transform: scale(0.8) rotate(-10deg); opacity: 0.72; }
}
@media (prefers-reduced-motion: reduce) {
  .rf-spark::before, .rf-spark::after { animation: none; }
}
:root[data-theme="dark"] .readfor-side { border-color: rgba(255, 255, 255, 0.14); }
@media (max-width: 900px) {
  .readfor { grid-template-columns: 1fr; gap: 24px; }
  .readfor-side { border-left: 0; padding-left: 0; border-top: 1px solid rgba(0, 0, 0, 0.12); padding-top: 20px; align-self: auto; }
}

/* ════════════════════════════════════════════════════════════════
   ABOUT MODAL — "About me" links open /about embedded in an iframe here
   instead of navigating (js/about-modal.js). The × button, a click on the
   backdrop, or Esc all close it.
════════════════════════════════════════════════════════════════ */
.about-overlay {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(16px, 4vw, 48px);
  background: rgba(17, 17, 17, 0.42);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  opacity: 0; visibility: hidden;
  transition: opacity 0.22s ease, visibility 0.22s ease;
}
.about-overlay.open { opacity: 1; visibility: visible; }

.about-dialog {
  position: relative;
  width: min(1040px, 100%); height: 70vh;
  background: #fff; border-radius: 20px; overflow: hidden;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.32);
  transform: translateY(10px) scale(0.99);
  transition: transform 0.22s ease;
}
.about-overlay.open .about-dialog { transform: none; }
.about-frame { width: 100%; height: 100%; border: 0; display: block; }

.about-close {
  position: absolute; top: 14px; right: 14px; z-index: 2;
  width: 38px; height: 38px; border-radius: 999px; border: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.06); color: #232323;
  transition: background 0.2s, color 0.2s;
}
.about-close:hover { background: rgba(0, 0, 0, 0.12); }

body.about-modal-open { overflow: hidden; }

:root[data-theme="dark"] .about-dialog { background: #0f1116; box-shadow: 0 24px 70px rgba(0, 0, 0, 0.6); }
:root[data-theme="dark"] .about-close { background: rgba(255, 255, 255, 0.10); color: #eef0f2; }
:root[data-theme="dark"] .about-close:hover { background: rgba(255, 255, 255, 0.18); }

@media (prefers-reduced-motion: reduce) {
  .about-overlay, .about-dialog { transition: none; }
}
