/* ===========================================================================
   Site styles.

   The site is an app shell: a fixed topbar, a left rail that IS the
   navigation, and a view pane. The rail's work list is an accordion —
   selecting a project expands its case-study section structure and swaps the
   view pane beside it. Case studies reuse the same rail so the navigation
   never changes shape between home and a project.

   Everything colours itself from the semantic vars in tokens.css
   (--page / --ink / --rule / --accent), so `body.t-blue` and `body.t-dark`
   are the only theme switches.
   =========================================================================== */

*{box-sizing:border-box}
/* clip (not hidden) so the 100vw transition doors can't spawn a horizontal
   scrollbar, without turning html into a scroll container (which would break
   the sticky case-study rail). */
html{scroll-behavior:smooth;overflow-x:clip}
body{
  margin:0;
  font-family:var(--font-body);
  color:var(--ink-2);
  background:var(--page);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
h1,h2,h3,h4{font-family:var(--font-display);color:var(--ink);letter-spacing:var(--tracking-tight);margin:0}
p{margin:0}
ul{margin:0;padding:0;list-style:none}
a{color:inherit;text-decoration:none;transition:color var(--dur-fast) ease,opacity var(--dur-fast) ease}
img,video{max-width:100%;display:block}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer;text-align:left}
:focus-visible{outline:2px solid var(--focus-ring);outline-offset:3px}

.eyebrow{
  font-family:var(--font-mono);font-size:var(--text-xs);font-weight:700;
  letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);
}

/* ---- Page transition (3D doors) ------------------------------------------
   The two home panels — blue left, navy right — are doors layered above the
   case study. They swing TOWARD the viewer (free inner edges rotate forward,
   out of the screen) to reveal it, and swing back to close. Hidden until JS
   activates them; reduced-motion users never see them.

   Divider position matches home exactly: the doors span the full viewport via
   `vw` (not clientWidth), and the blue door is `calc(100vw - var(--view-w))`,
   the same vw basis home uses — so a scrollbar on the case study behind can't
   shift the seam. */
.doors{
  position:fixed;left:0;top:0;width:100vw;height:100dvh;z-index:200;
  display:none;perspective:1300px;perspective-origin:50% 50%;pointer-events:none;
}
.doors.active{display:flex}
.door{height:100%;backface-visibility:hidden;transition:transform 860ms var(--ease-in-out)}
.door--l{width:calc(100vw - var(--view-w));background:var(--blue-500);transform-origin:left center;box-shadow:1px 0 0 var(--blue-500)}
.door--r{flex:1;background:var(--navy-950);transform-origin:right center}
.doors.is-instant .door{transition:none}
/* closed (default when active) = flat, covering. open = swung forward toward
   the viewer, hinged on the outer edges (free inner edges rotate out of the
   screen), past edge-on so backface-hidden clears them from view. */
.doors.is-open .door--l{transform:rotateY(-105deg)}
.doors.is-open .door--r{transform:rotateY(105deg)}
.doors.is-open .door{box-shadow:0 0 60px rgba(0,0,0,.25)}

/* Default (non-story) case study eases in on load: a gentle staggered fade-up,
   so the page settles in just as the doors finish opening. Story pages use
   scroll-reveal instead (below). */
body.t-dark .cs:not(.cs--story) > *{animation:ds-fade-up 720ms var(--ease-in-out) both}
body.t-dark .cs:not(.cs--story) .cs-hero{animation-delay:120ms}
body.t-dark .cs:not(.cs--story) .meta-strip{animation-delay:200ms}
body.t-dark .cs:not(.cs--story) .cs-section:nth-of-type(1){animation-delay:280ms}
body.t-dark .cs:not(.cs--story) .cs-section:nth-of-type(2){animation-delay:360ms}
body.t-dark .cs:not(.cs--story) .cs-section:nth-of-type(3){animation-delay:440ms}
body.t-dark .cs:not(.cs--story) .cs-section:nth-of-type(n+4){animation-delay:520ms}

/* ---- Scroll reveal (story pages) -----------------------------------------
   The block is just the trigger; its inner elements fade up with a stagger, so
   text and image enter on their own beat. Base state is visible, so no-JS users
   see everything; the pre-paint `js` class arms the hidden state. */
html.js .reveal > *,
html.js .cs-hero.reveal > *{
  opacity:0;transform:translateY(18px);
  transition:opacity .62s var(--ease-out),transform .62s var(--ease-out);
}
html.js .reveal.is-visible > *{opacity:1;transform:none}
/* stagger the immediate children */
html.js .reveal.is-visible > *:nth-child(2){transition-delay:.09s}
html.js .reveal.is-visible > *:nth-child(3){transition-delay:.18s}
html.js .reveal.is-visible > *:nth-child(4){transition-delay:.27s}
html.js .reveal.is-visible > *:nth-child(n+5){transition-delay:.34s}
/* and stagger the lines within a text column */
html.js .reveal .beat__text > *{
  opacity:0;transform:translateY(14px);
  transition:opacity .58s var(--ease-out),transform .58s var(--ease-out);
}
html.js .reveal.is-visible .beat__text > *{opacity:1;transform:none}
html.js .reveal.is-visible .beat__text > *:nth-child(2){transition-delay:.08s}
html.js .reveal.is-visible .beat__text > *:nth-child(3){transition-delay:.16s}
html.js .reveal.is-visible .beat__text > *:nth-child(4){transition-delay:.24s}
html.js .reveal.is-visible .beat__text > *:nth-child(n+5){transition-delay:.3s}
/* the figure enters a touch later and softer */
html.js .reveal .figure{transition-duration:.72s}
@media (prefers-reduced-motion:reduce){
  html.js .reveal > *,html.js .reveal .beat__text > *,html.js .cs-hero.reveal > *{
    opacity:1;transform:none;transition:none;
  }
}

/* ---- Story case study ----------------------------------------------------
   Single narrow column of narrative. Generous vertical rhythm; images stay
   small and left-aligned so nothing is stretched past its natural size. */
.cs--story{gap:clamp(64px,11vh,150px)}
.cs--story > *{max-width:760px}

/* kickers pick up the mint accent, matching the deck */
.cs .eyebrow{color:var(--accent)}

/* loose summary: a statement, a light meta line, then big headline metrics */
.cs-summary{display:flex;flex-direction:column;gap:var(--sp-6);padding-bottom:var(--sp-6);border-bottom:1px solid var(--rule)}
.cs-summary__statement{font-size:clamp(20px,1.4vw + .7vh,29px);line-height:1.42;color:var(--ink);max-width:40ch;font-weight:500}
.cs-summary__meta{display:flex;flex-wrap:wrap;gap:8px var(--sp-5);font-size:var(--text-sm);color:var(--ink-3)}
.cs-summary__fact b{color:var(--ink);font-weight:600;margin-right:5px}
.cs-metrics{display:flex;flex-wrap:wrap;gap:var(--sp-5) clamp(28px,5vw,72px);margin-top:var(--sp-2)}
.metric{display:flex;flex-direction:column;gap:5px}
.metric__value{font-family:var(--font-display);font-size:clamp(34px,3.4vw,54px);font-weight:800;color:var(--accent);letter-spacing:var(--tracking-tight);line-height:.95}
.metric__label{font-size:var(--text-sm);color:var(--ink-2);max-width:22ch;line-height:1.3}

/* narrative beat: a text column, then a small left-aligned figure */
.beat{display:flex;flex-direction:column;gap:var(--sp-6)}
.beat__text{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0;max-width:60ch}
.beat__title{font-size:var(--text-h2);font-weight:700;line-height:1.14;color:var(--ink);letter-spacing:var(--tracking-tight)}
.beat__body{font-size:var(--text-md);line-height:var(--leading-body);color:var(--ink-2);max-width:56ch}

/* figures: capped, left-aligned, no plate — the deck's screenshots are already
   built for a dark field, so they float directly on the page */
.figure{margin:0;width:fit-content;max-width:min(480px,100%)}
.figure img{width:100%;height:auto;display:block;border-radius:var(--radius-md)}
.figure figcaption{margin-top:12px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3)}
.figure--portrait{max-width:300px}
.figure--portrait img{border-radius:var(--radius-lg)}

/* persona: small portrait, then the trait list */
.beat--persona .persona__points{display:flex;flex-direction:column;gap:var(--sp-3);margin-top:var(--sp-2)}
.persona__points li{display:flex;flex-direction:column;gap:3px}
.persona__label{font-family:var(--font-mono);font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--accent)}
.persona__text{font-size:var(--text-sm);color:var(--ink-2);line-height:1.45}

/* pull quote */
.pullquote{margin:0;max-width:52ch;padding-left:clamp(16px,2vw,26px);border-left:3px solid var(--accent)}
.pullquote p{font-size:clamp(20px,1.6vw + .5vh,28px);line-height:1.34;color:var(--ink);font-weight:500;font-style:italic}
.pullquote cite{display:block;margin-top:16px;font-style:normal;font-family:var(--font-mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}

/* results block */
.cs-results{display:flex;flex-direction:column;gap:var(--sp-5)}

/* The corner monogram gives a little bob on load — same personality as its
   hover bob, a beat longer. `backwards` (not `both`) so it stays hidden during
   the delay yet releases transform afterwards, leaving the hover bob free. */
.monogram{animation:mono-bob 900ms var(--ease-out) 220ms backwards}
@keyframes mono-bob{
  0%{transform:translateY(-6px) rotate(-8deg);opacity:0}
  35%{transform:translateY(0) rotate(6deg);opacity:1}
  60%{transform:rotate(-4deg)}
  80%{transform:rotate(2deg)}
  100%{transform:none;opacity:1}
}
@media (prefers-reduced-motion:reduce){
  body.t-dark .cs > *,.monogram{animation:none}
}

/* ---- Monogram (case studies only) ----------------------------------------
   Sits at the very top of the rail so its top edge lines up with the article's
   first line; clicking returns home. */
.monogram{
  display:inline-flex;align-self:flex-start;
  transition:transform var(--dur-med) var(--ease-out),opacity var(--dur-fast) ease;
}
.monogram svg{height:30px;width:auto;display:block}
.monogram:hover{transform:translateY(-2px) rotate(-4deg)}

/* status chip — "not available for work" */
.statuswrap{position:relative;display:inline-flex}
.status{
  display:inline-flex;align-items:center;gap:5px;
  padding:3px 10px;border-radius:var(--radius-pill);
  font-family:var(--font-mono);font-size:9px;font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;white-space:nowrap;cursor:help;
  color:var(--coral-400);background:rgba(255,143,135,.14);border:1px solid rgba(255,143,135,.45);
  transition:background var(--dur-fast) ease,border-color var(--dur-fast) ease;
}
.status:hover,.statuswrap:hover .status{background:rgba(255,143,135,.22);border-color:rgba(255,143,135,.7)}
.status__dot{width:5px;height:5px;border-radius:50%;background:var(--coral-400);flex:none;animation:ds-pulse var(--pulse-dur) var(--ease-in-out) infinite}

/* Popover — the "why" behind the badge. Sits under the chip, hidden until
   the wrapper is hovered or the button focused, with a soft rise-and-fade. */
.popover{
  position:absolute;top:calc(100% + 9px);left:0;z-index:20;width:max-content;max-width:280px;
  padding:11px 13px;border-radius:var(--radius-md);
  background:var(--navy-950);border:1px solid rgba(157,179,245,.28);
  box-shadow:0 12px 34px rgba(2,11,38,.5);
  opacity:0;transform:translateY(-5px) scale(.98);transform-origin:top left;
  pointer-events:none;visibility:hidden;
  transition:opacity 220ms var(--ease-soft),transform 220ms var(--ease-soft),visibility 0s linear 220ms;
}
.popover::before{
  content:"";position:absolute;bottom:100%;left:16px;
  border:6px solid transparent;border-bottom-color:var(--navy-950);
}
.popover__body{font-size:12.5px;line-height:1.5;color:rgba(255,255,255,.82)}
.popover__body b{color:#fff;font-weight:700}
.statuswrap:hover .popover,
.statuswrap:focus-within .popover{
  opacity:1;transform:none;visibility:visible;pointer-events:auto;
  transition:opacity 260ms var(--ease-soft),transform 260ms var(--ease-soft);
}
@media (prefers-reduced-motion:reduce){
  .popover{transition:opacity 160ms linear,visibility 0s linear 160ms;transform:none}
  .statuswrap:hover .popover,.statuswrap:focus-within .popover{transform:none}
  .status__dot{animation:none}
}

/* ---- Shell --------------------------------------------------------------- */
.shell{
  display:grid;grid-template-columns:var(--rail-cs) 1fr;
  gap:clamp(20px,3vw,48px);
  min-height:100dvh;
  padding:var(--sp-8) var(--edge) var(--sp-6);
  max-width:var(--container);margin:0 auto;
}
/* Home runs full-bleed so the dark preview panel can sit flush against the
   right edge of the viewport — that hard edge is what separates it from the
   blue field. No topbar here, so the rail owns the identity. */
body.t-blue .shell{
  max-width:none;grid-template-columns:1fr var(--view-w);
  gap:clamp(24px,3.5vw,56px);
  padding:0 0 0 var(--edge);
  align-items:stretch;
}
body.t-blue .rail{
  max-width:min(600px,100%);
  /* right gutter so no line ever runs up to the blue/navy seam */
  padding:var(--sp-6) var(--sp-5) var(--sp-6) 0;
  display:flex;flex-direction:column;justify-content:center;gap:var(--sp-6);
}
/* identity block, top of the rail: name (large) with status + LinkedIn under it */
.rail__id{display:flex;flex-direction:column;gap:10px}
.rail__name{font-family:var(--font-display);font-weight:700;font-size:var(--text-h3);color:var(--ink);letter-spacing:var(--tracking-tight)}
.rail__meta{display:flex;align-items:center;gap:var(--sp-3)}
.rail__link{font-size:var(--text-xs);font-weight:600;color:var(--ink);letter-spacing:.02em}
.rail__link:hover{opacity:.72}
/* The display title sits directly under the identity, above the blurb. */
.rail__id .display{margin:var(--sp-3) 0 var(--sp-1)}
/* Background blurb — three short paragraphs, each opening with a bolded anchor.
   Capped at 100% so it can never spill past the rail into the navy panel. */
.rail__bio{max-width:min(58ch,100%);margin:0;display:flex;flex-direction:column;gap:.75em}
.rail__bio p{margin:0;font-size:clamp(14px,0.35vw + 12px,16px);line-height:1.55;color:var(--ink-3)}
.rail__bio strong{color:var(--ink);font-weight:600}
.rail__mid{display:flex;flex-direction:column;min-height:0}

/* ---- Rail (title + accordion nav) ---------------------------------------- */
.rail{display:flex;flex-direction:column;gap:var(--gap-unit);min-width:0}
.display{
  font-size:var(--text-display);font-weight:800;line-height:var(--leading-tight);
  text-transform:uppercase;letter-spacing:-0.015em;color:var(--ink);
}
/* everything after the first line steps down, per the mockup */
.display__sub,.display__loc{display:block;font-size:.72em;line-height:1.04}
.display__loc{color:var(--ink-3)}
.rail__back{
  font-family:var(--font-mono);font-size:var(--text-xs);font-weight:700;
  letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);
}
.rail__back:hover{color:var(--ink)}

/* work list — the accordion.
   On a case study the rail is a beige panel, distinct from the cream page, and
   sticks in view while you read. */
.worknav{display:flex;flex-direction:column;gap:var(--sp-3)}
@media (min-width:901px){
  /* Minimal: no panel, no frame. Just a sticky column whose text left-aligns
     with the monogram (both at the --edge gutter). */
  body.t-dark .rail{
    position:sticky;top:var(--sp-8);align-self:start;
    max-height:calc(100dvh - var(--sp-8) - var(--sp-5));overflow-y:auto;
    scrollbar-width:thin;
  }
}
body.t-dark .shell{gap:clamp(28px,4vw,64px)}
/* No rules or dividers — rhythm comes from spacing and weight alone. */
.wn{display:flex;flex-direction:column}
/* One line per project. Name flexes-none, hook truncates with an ellipsis
   rather than wrapping — a second line breaks the switcher's scan rhythm. */
.wn__row{
  display:flex;align-items:baseline;gap:9px;width:100%;padding:5px 0;
  white-space:nowrap;overflow:hidden;
  transition:opacity var(--dur-fast) ease;
}
.wn__name{
  font-family:var(--font-display);font-size:13px;font-weight:700;
  color:var(--ink);letter-spacing:0;flex:none;
}
.wn__hook{
  font-size:13px;color:var(--ink-3);line-height:1.3;
  min-width:0;overflow:hidden;text-overflow:ellipsis;
}

/* Home: dimmed until previewed. The description may wrap to two lines (the
   list is short now), so it never gets clipped at the seam. */
body.t-blue .worknav{gap:var(--sp-3)}
body.t-blue .worknav .eyebrow{font-size:11.5px;letter-spacing:.12em}
body.t-blue .wn__row{
  opacity:.6;flex-direction:column;align-items:flex-start;gap:3px;
  white-space:normal;overflow:visible;padding:9px 0;
}
body.t-blue .wn__name{font-size:clamp(15px,0.5vw + 12px,18px)}
body.t-blue .wn__hook{
  white-space:normal;overflow:visible;text-overflow:clip;line-height:1.4;
  font-size:clamp(14px,0.35vw + 12px,16px);
}
body.t-blue .wn__row:hover,
body.t-blue .wn__row:focus-visible{opacity:1}
body.t-blue .wn__item.is-open .wn__hook{color:var(--ink-2)}
body.t-blue .wn__sections{display:none}   /* accordion is a case-study affordance only */

/* Case study: compact three-level stub. Company (row) → Context + projects
   (wn__sec) → each project's sections (wn__sub). No connector lines; hierarchy
   reads through indent, size, and weight. Tight, to fit it all without scroll. */
body.t-dark .worknav .eyebrow{display:none}
body.t-dark .wn__name{white-space:normal;font-size:clamp(13px,0.4vw + 11px,15px);line-height:1.25;font-weight:700}
body.t-dark .wn__hook{display:none}
body.t-dark .wn__row{padding:3px 0;opacity:.45;transition:opacity var(--dur-fast) ease}
body.t-dark .wn__item.is-open .wn__row,
body.t-dark .wn__row:hover{opacity:1}
body.t-dark .wn__item + .wn__item{margin-top:1px}

/* expanded project list for the selected company. The grid 0fr→1fr trick only
   collapses cleanly if the item has NO padding of its own — pad the inner ul
   instead, so a closed section is a true 0px. */
.wn__sections{
  display:grid;grid-template-rows:0fr;
  transition:grid-template-rows var(--dur-med) var(--ease-out);
}
.wn__item.is-open .wn__sections{grid-template-rows:1fr}
.wn__sections > ul{overflow:hidden;min-height:0}
.wn__sections > ul > li:first-child{padding-top:3px}
.wn__sections > ul > li:last-child{padding-bottom:6px}

/* level 2 — Context + project names. NOT indented: aligned with the company
   name; hierarchy reads through weight and colour, not position. */
.wn__sec{
  display:block;padding:2.5px 0;
  font-size:clamp(12px,0.3vw + 10.5px,13.5px);font-weight:600;color:var(--ink-2);line-height:1.3;
  transition:color var(--dur-fast) ease;
}
.wn__sec:hover{color:var(--ink)}
.wn__sec[aria-current="true"]{color:var(--accent)}
.wn__sec--muted{color:var(--ink-3);opacity:.5;font-weight:500}

/* level 3 — a project's own sections. This is the only indented level. */
.wn__subs{padding:1px 0 4px}
.wn__sub{
  display:block;padding:2px 0 2px 14px;
  font-size:clamp(11px,0.25vw + 10px,12.5px);font-weight:500;color:var(--ink-3);line-height:1.3;
  transition:color var(--dur-fast) ease;
}
.wn__sub:hover{color:var(--ink)}
.wn__sub[aria-current="true"]{color:var(--accent);font-weight:600}

/* ---- View pane (home) ---------------------------------------------------- */
/* The preview lives on its own very dark blue surface — a distinct plane from
   the blue field, not a card floating on it. */
/* Every panel is stacked in the SAME grid cell so switching never reflows the
   column — the cell is sized to the tallest panel and the swap is a pure
   opacity crossfade. That kills the jump-and-restart glitch that display /
   per-element animation toggling caused. */
/* `safe center` centers the stack when it fits but pins it to the top when the
   tallest panel is taller than the viewport, so the well can never overflow
   above the navy panel. */
.view{min-width:0;display:grid;grid-template-columns:minmax(0,1fr);align-content:safe center}
body.t-blue .view{
  background:var(--navy-950);
  padding:var(--sp-6) clamp(20px,2.4vw,36px);
  --ink-3:rgba(157,179,245,.72);
}
.panel{
  grid-area:1/1;display:flex;flex-direction:column;gap:var(--sp-4);
  opacity:0;visibility:hidden;transform:translateY(6px);
  transition:opacity .38s var(--ease-soft),transform .5s var(--ease-soft),visibility .38s;
}
.panel.is-active{opacity:1;visibility:visible;transform:none}
/* The resting reel (no project hovered) has only a well + hint, so centre it in
   the panel's full height; project panels stay top-aligned as they're content-rich. */
.panel[data-view="__home__"]{justify-content:center}
@media (prefers-reduced-motion:reduce){
  .panel{transition:opacity .15s linear,visibility .15s;transform:none}
}
.well{
  width:100%;aspect-ratio:16/9;max-height:44vh;background:var(--navy-800);border-radius:var(--radius-lg);
  overflow:hidden;display:flex;align-items:center;justify-content:center;
  font-family:var(--font-mono);font-size:var(--text-xs);letter-spacing:var(--tracking-wide);
  text-transform:uppercase;color:rgba(157,179,245,.4);
}
.well img,.well video{width:100%;height:100%;object-fit:cover}
.panel__head{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--sp-3)}
.panel__name{font-size:var(--text-h2);font-weight:800;text-transform:uppercase;line-height:1.05;color:#fff}
.panel__hook{font-size:var(--text-md);line-height:var(--leading-snug);color:rgba(255,255,255,.86)}
/* The numbers a hiring manager scans first — big and bright on the navy panel. */
.panel__metrics{display:flex;flex-wrap:wrap;gap:clamp(18px,2.4vw,40px);margin:2px 0}
.pmetric{display:flex;flex-direction:column;gap:3px}
.pmetric__value{font-family:var(--font-display);font-weight:800;font-size:clamp(22px,2vw,30px);line-height:1;color:#fff}
.pmetric__label{font-size:12.5px;line-height:1.3;max-width:17ch;color:rgba(157,179,245,.9)}
.panel__facts{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-size:var(--text-sm);color:rgba(255,255,255,.82)}
.panel__dot{opacity:.4}
.panel__badges{display:flex;flex-wrap:wrap;gap:7px}
.panel__hint{
  font-family:var(--font-mono);font-size:var(--text-xs);font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);
}

/* ---- Badges -------------------------------------------------------------- */
.badge{
  display:inline-flex;align-items:center;gap:5px;
  padding:4px 11px;border-radius:var(--radius-pill);
  font-family:var(--font-mono);font-size:10px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;white-space:nowrap;
  color:var(--ink);border:1px solid var(--rule-strong);
}
.badge--solid{background:var(--ink);color:var(--page);border-color:var(--ink)}
.badge--quiet{color:var(--ink-3);border-color:var(--rule)}

/* ---- Buttons ------------------------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--font-display);font-weight:700;font-size:var(--text-md);
  padding:10px 22px;border-radius:var(--radius-pill);
  border:1px solid var(--ink);color:var(--ink);
  transition:background var(--dur-fast) ease,color var(--dur-fast) ease;
}
.btn:hover{background:var(--ink);color:var(--page)}
.btn--ghost{border-color:transparent;padding:10px 0;color:var(--ink)}
.btn--ghost:hover{background:none;opacity:.68}

/* ---- Case study (cream) -------------------------------------------------- */
.cs{min-width:0;display:flex;flex-direction:column;gap:var(--section-gap);padding-bottom:var(--sp-8)}
.cs-hero{display:flex;flex-direction:column;gap:var(--sp-3)}
.cs-hero__title{font-size:var(--text-h1);font-weight:800;text-transform:uppercase;line-height:1.02}
.cs-hero__lead{font-size:var(--text-lg);line-height:var(--leading-snug);color:var(--ink-2);max-width:62ch}
.cs-hero__badges{display:flex;flex-wrap:wrap;gap:7px;padding-top:var(--sp-2)}

.meta-strip{
  display:flex;flex-wrap:wrap;gap:var(--sp-4) var(--sp-6);
  padding:var(--sp-4) 0;border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
}
.meta{display:flex;flex-direction:column;gap:2px}
.meta__label{font-family:var(--font-mono);font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.meta__value{color:var(--ink);font-size:var(--text-sm);font-weight:600}
.meta__value--accent{color:var(--accent)}
.cs-skills{display:flex;gap:6px;flex-wrap:wrap;align-items:center}

.cs-section{display:flex;flex-direction:column;gap:var(--sp-4);scroll-margin-top:var(--sp-8)}
.cs-overview{max-width:78ch;font-size:var(--text-md);line-height:var(--leading-body);color:var(--ink-2)}

/* Each project reads as a standalone mini case study: a heading, then Problem
   / Approach / Solution side by side, Impact stats, optional media. */
.proj{gap:var(--sp-5)}
.proj__head{display:flex;flex-direction:column;gap:3px}
.proj__name{font-size:var(--text-h2);font-weight:700;line-height:1.12;color:var(--ink)}
.proj__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-5)}
.block{display:flex;flex-direction:column;gap:5px}
.block__label{font-family:var(--font-mono);font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.block__text{color:var(--ink-2);font-size:var(--text-sm);line-height:1.55}

.impact{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-3)}
.stat{background:var(--surface);border-radius:var(--radius-md);padding:var(--sp-4);display:flex;flex-direction:column;gap:2px}
.stat__value{font-family:var(--font-display);font-size:26px;font-weight:800;color:var(--accent);line-height:1.1;letter-spacing:var(--tracking-tight)}
.stat__label{color:var(--ink-2);font-size:var(--text-xs);line-height:1.35}

.media-slot{width:100%;aspect-ratio:16/9;background:var(--well);border-radius:var(--radius-lg);overflow:hidden}
.media-slot video,.media-slot img{width:100%;height:100%;object-fit:cover}

.cs-foot{display:flex;justify-content:space-between;gap:var(--sp-4);flex-wrap:wrap;padding-top:var(--sp-5);border-top:1px solid var(--rule)}
.cs-foot__meta{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.cs-foot__links{display:flex;gap:var(--sp-5);font-size:var(--text-sm);font-weight:600;color:var(--ink)}
.cs-foot__links a:hover{color:var(--accent)}

/* ---- Responsive ---------------------------------------------------------- */
@media (max-width:1000px){
  .proj__grid{grid-template-columns:1fr;gap:var(--sp-4)}
}
/* Below 900 the two-column shell collapses to a single scrolling column on
   both themes — the rail/identity stacks above the preview or article.
   `body.t-blue` overrides need the same specificity to win. */
@media (max-width:900px){
  body.t-blue .shell,
  body.t-dark .shell{
    grid-template-columns:1fr;min-height:0;gap:var(--sp-6);
    padding:calc(var(--topbar-h) + var(--sp-5)) var(--edge) var(--sp-6);
    max-width:var(--container);align-items:start;
  }
  /* home has no topbar, so it doesn't need the top clearance */
  body.t-blue .shell{padding-top:var(--sp-6)}
  body.t-blue .rail{max-width:none;display:flex;flex-direction:column;gap:var(--sp-6)}
  body.t-blue .rail__mid{justify-content:flex-start;gap:var(--sp-5)}
  body.t-blue .view{padding:var(--sp-5);border-radius:var(--radius-lg)}
  .view{align-content:start}
  .well{max-height:none}
  .meta-strip{gap:var(--sp-4)}
  /* One line can't hold a hook at phone widths — wrap instead of clipping it
     off the edge. The name stays on the first line with the hook flowing after. */
  .wn__row{white-space:normal;overflow:visible;flex-wrap:wrap}
  .wn__hook{overflow:visible;text-overflow:clip;white-space:normal}
}
@media (max-width:520px){
  .rail__name{font-size:var(--text-md)}
  .cs-hero__title,.panel__name{font-size:var(--text-h2)}
}
