/* ═══════════════════════════════════════════════════════════════════════
   CASE STUDY TEMPLATE — shared stylesheet
   ───────────────────────────────────────────────────────────────────────
   Canonical styles for every /<slug>-case-study/ page. Extracted VERBATIM
   from the shipped War Room page's inline <style> block (#340) so the
   locked design ports literally rather than being re-authored — see
   CLAUDE.md "Porting an approved external design → literal, never
   reinterpret."

   Layout: topbar · hero · brief · walk (feat blocks) · proof · pitch ·
   final · footer · contact modal. A new case study is CONTENT ONLY; it
   should need no CSS of its own.

   Section 1 below is the literal extraction. Sections 2-4 are additive
   overrides layered on top — the responsive pass, the topbar fix, and
   embed mode. Keep it that way: fix things in 2-4, never by editing 1,
   so the extraction stays diffable against the original.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1. LITERAL EXTRACTION — do not edit; override below ─────────────── */

:root {
  /* palette — mirrors site/src/index.css locked tokens exactly */
  --color-paper: #f3eee4;
  --color-paper-warm: #faf7ef;
  --color-ink: #0D1330;
  --color-ink-soft: #5a544c;
  --color-ink-faint: rgba(13, 19, 48, 0.14);
  --color-graph: rgba(13, 19, 48, 0.07);
  --color-bauhaus-blue: #0666A3;
  --color-bauhaus-yellow: #FFD400;
  --color-bauhaus-red: #CE2D18;
  --color-bauhaus-green: #006F54;
  --color-bauhaus-orange: #D8841C;
  --color-bauhaus-pink: #EFA1B8;
  /* type — mirrors locked font tokens; --fs-* is this page's ramp */
  --font-heading: "Inter", "Helvetica Neue", sans-serif;
  --font-display: "Big Shoulders Display", "Inter", sans-serif;
  --font-drama: "Instrument Serif", serif;
  --font-mono: "JetBrains Mono", monospace;
  /* type ramp v2 (2026-08-05, Roderic: "everything ~20-25% bigger") */
  --fs-mono: 14px;
  --fs-body-s: 18px;
  --fs-body: 19px;
  --fs-lede: clamp(19px, 1.8vw, 23px);
  --fs-drama-s: 24px;
  --fs-drama-m: 30px;
  --fs-drama-hero: clamp(29px, 4vw, 48px);
  --fs-drama-final: clamp(27px, 3.6vw, 41px);
  --fs-h3: clamp(36px, 4.3vw, 58px);
  --fs-h2: clamp(48px, 7.2vw, 91px);
  --fs-h1: clamp(77px, 13.8vw, 178px);
  --fs-final: clamp(62px, 10.8vw, 144px);
  --gutter: clamp(20px, 5vw, 72px);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html { background: var(--color-paper); }
body {
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-heading);
  font-size: var(--fs-body);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
.mono {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: var(--fs-mono);
  font-weight: 500;
}
.display {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 0.92;
  text-transform: uppercase;
}
.drama {
  font-family: var(--font-drama);
  font-style: italic;
  letter-spacing: -0.01em;
  text-transform: none;
  font-weight: 400;
}
.wrap { max-width: 1300px; margin: 0 auto; padding-left: var(--gutter); padding-right: var(--gutter); }

/* ── top bar ─────────────────────────────────────────── */
.topbar {
  background: var(--color-ink);
  color: var(--color-paper);
  height: 36px;
  display: flex;
  align-items: center;
}
.topbar .wrap { width: 100%; display: flex; justify-content: space-between; gap: 16px; }
.topbar a { color: var(--color-paper); text-decoration: none; }
.topbar .tb-left { display: inline-flex; align-items: center; gap: 14px; }
.topbar .tb-back { font-size: 26px; line-height: 1; font-weight: 500; color: var(--color-paper); padding: 0 6px; margin-left: -6px; transition: transform .15s ease; }
.topbar .tb-back:hover { transform: translateX(-4px); }
.hero .hero-mark { display: block; width: 72px; height: 72px; color: var(--color-ink); margin: 0 0 28px; }

/* ── hero ────────────────────────────────────────────── */
.hero { padding: clamp(56px, 9vh, 112px) 0 clamp(48px, 7vh, 84px); border-bottom: 2px solid var(--color-ink); }
.hero .eyebrow { color: var(--color-bauhaus-red); margin-bottom: 24px; display: block; }
.hero h1 { font-size: var(--fs-h1); }
.hero .drama-line { font-size: var(--fs-drama-hero); margin-top: 12px; }
.hero .lede {
  max-width: 740px;
  margin-top: 28px;
  font-size: var(--fs-lede);
  font-weight: 500;
}
.cta-row { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 36px; align-items: center; }
.btn {
  display: inline-block;
  background: var(--color-ink);
  color: var(--color-paper);
  text-decoration: none;
  padding: 16px 24px;
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: var(--fs-mono);
  font-weight: 700;
  border: 2px solid var(--color-ink);
}
.btn:hover { background: var(--color-bauhaus-red); border-color: var(--color-bauhaus-red); }
.btn-ghost { background: transparent; color: var(--color-ink); }
.btn-ghost:hover { background: var(--color-ink); color: var(--color-paper); }
.hero .live-chip { display: inline-flex; align-items: center; gap: 8px; margin-top: 32px; }
.live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-bauhaus-green); display: inline-block; }

/* ── the brief ───────────────────────────────────────── */
.brief { padding: clamp(56px, 9vh, 100px) 0; border-bottom: 2px solid var(--color-ink); }
.section-eyebrow { display: flex; justify-content: space-between; gap: 16px; color: var(--color-ink-soft); margin-bottom: 40px; }
.brief h2 { font-size: var(--fs-h2); margin-bottom: 48px; }
.brief h2 .drama { font-size: 1.06em; }
.brief-grid { display: grid; grid-template-columns: repeat(3, 1fr); border-top: 2px solid var(--color-ink); }
.brief-cell { padding: 28px 24px 32px 0; }
.brief-cell + .brief-cell { padding-left: 24px; border-left: 1px solid var(--color-ink-faint); }
.brief-cell .label { display: block; margin-bottom: 16px; color: var(--color-bauhaus-red); }
.brief-cell:nth-child(2) .label { color: var(--color-bauhaus-blue); }
.brief-cell:nth-child(3) .label { color: var(--color-bauhaus-green); }
.brief-cell p { font-size: var(--fs-body-s); font-weight: 500; }
.brief-cell .drama { font-size: var(--fs-drama-s); display: block; margin-bottom: 12px; }

/* ── walkthrough — big capture on top, two text cols below ── */
.walk { padding: clamp(56px, 9vh, 100px) 0; border-bottom: 2px solid var(--color-ink); }
.walk h2 { font-size: var(--fs-h2); margin-bottom: 16px; }
.walk .sub { max-width: 760px; font-weight: 500; margin-bottom: 56px; }
.walk-intro { max-width: 860px; margin-bottom: 56px; }
.walk-intro p { font-size: var(--fs-body); font-weight: 500; margin-bottom: 24px; }
.walk-intro .drama { font-size: var(--fs-drama-s); }
/* higher specificity than .feat-frame so the base flex never wins */
.feat-frame.feat-frame--split { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr; gap: 2px; aspect-ratio: 16 / 9; align-items: stretch; }
.feat-frame--split .cell { overflow: hidden; position: relative; }
.feat-frame--split img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.feat-frame--split img.pos-left { object-position: left center; }
/* center anchor trims the white page margins on the design-system sheets */
.feat-frame--split img.pos-center { object-position: center center; }
.feat { padding: clamp(48px, 7vh, 72px) 0; border-top: 1px solid var(--color-ink-faint); }
.feat:first-of-type { border-top: 2px solid var(--color-ink); }
.feat-frame {
  aspect-ratio: 16 / 9;
  background:
    linear-gradient(var(--color-graph) 1px, transparent 1px) 0 0 / 100% 28px,
    linear-gradient(90deg, var(--color-graph) 1px, transparent 1px) 0 0 / 28px 100%,
    var(--color-paper-warm);
  border: 2px solid var(--color-ink);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 32px;
  /* near-full-bleed: captures must dominate, not sit in the text column.
     Capped at 1440 CSS px so 1x-native captures never display above ~100%. */
  width: min(100vw - 48px, 1440px);
  left: 50%;
  transform: translateX(-50%);
}
/* uniform house shape: every frame 16:9, every capture fills it,
   anchored left so the meaningful columns survive the crop */
.feat-frame img { width: 100%; height: 100%; object-fit: cover; object-position: left center; display: block; }
/* top anchor where the app chrome (logo + top menu) must survive the crop */
.feat-frame img.pos-top { object-position: left top; }
.feat-frame .cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  background: var(--color-ink);
  color: var(--color-paper);
  padding: 8px 12px;
  display: flex;
  justify-content: space-between;
  gap: 12px;
}
.feat-frame .pending {
  color: var(--color-ink-soft);
  border: 1px dashed var(--color-ink-faint);
  background: var(--color-paper);
  padding: 12px 16px;
}
.feat-text {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 4vw, 56px);
  align-items: start;
  margin-top: 32px;
}
.feat-idx { display: block; margin-bottom: 16px; }
.accent-chip { width: 12px; height: 12px; display: inline-block; margin-right: 12px; vertical-align: baseline; }
.feat h3 { font-size: var(--fs-h3); margin-bottom: 8px; }
.feat .one-liner { font-size: var(--fs-drama-m); display: block; margin-bottom: 16px; }
.feat p.body { font-size: var(--fs-body-s); font-weight: 500; max-width: 560px; }
.usecase .label { display: block; margin-bottom: 16px; }
.usecase p { font-size: var(--fs-body-s); font-weight: 500; }
.usecase .drama { font-size: var(--fs-drama-s); display: block; margin-bottom: 12px; }

/* ── proof (dark) ────────────────────────────────────── */
.proof { background: var(--color-ink); color: var(--color-paper); padding: clamp(64px, 10vh, 112px) 0; }
.proof .section-eyebrow { color: rgba(243, 238, 228, 0.55); }
.proof h2 { font-size: var(--fs-h2); margin-bottom: 56px; }
.proof h2 .drama { color: var(--color-bauhaus-yellow); }
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid rgba(243, 238, 228, 0.25); }
.stat { padding: 24px 24px 32px 0; }
.stat + .stat { padding-left: 24px; border-left: 1px solid rgba(243, 238, 228, 0.25); }
.stat .num { font-family: var(--font-display); font-weight: 800; letter-spacing: -0.03em; line-height: 0.9; font-size: clamp(46px, 5.5vw, 77px); display: block; }
.stat .lbl { display: block; margin-top: 12px; color: rgba(243, 238, 228, 0.7); }
.proof .plain { max-width: 860px; margin-top: 52px; font-size: var(--fs-body); font-weight: 500; }
.proof .plain .drama { color: var(--color-bauhaus-yellow); font-size: 1.1em; }
.proof .operator { margin-top: 24px; color: rgba(243, 238, 228, 0.7); }

/* ── video strip ─────────────────────────────────────── */
.video { padding: clamp(56px, 9vh, 100px) 0; border-bottom: 2px solid var(--color-ink); }
.video h2 { font-size: var(--fs-h2); margin-bottom: 16px; }
.video .sub { max-width: 640px; font-weight: 500; margin-bottom: 48px; }
.reel { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(16px, 2vw, 28px); }
.reel-item { border: 2px solid var(--color-ink); background: var(--color-paper-warm); }
.reel-thumb {
  aspect-ratio: 16 / 9;
  display: flex; align-items: center; justify-content: center;
  background:
    linear-gradient(var(--color-graph) 1px, transparent 1px) 0 0 / 100% 24px,
    linear-gradient(90deg, var(--color-graph) 1px, transparent 1px) 0 0 / 24px 100%,
    var(--color-paper-warm);
  border-bottom: 2px solid var(--color-ink);
}
.play {
  width: 56px; height: 56px; border-radius: 50%;
  background: var(--color-ink); color: var(--color-paper);
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; padding-left: 4px;
}
.reel-item .cap { padding: 12px; display: flex; justify-content: space-between; gap: 12px; color: var(--color-ink-soft); }

/* ── pitch ───────────────────────────────────────────── */
.pitch { padding: clamp(56px, 9vh, 100px) 0; border-bottom: 2px solid var(--color-ink); }
.pitch h2 { font-size: var(--fs-h2); margin-bottom: 12px; }
.pitch-line { font-size: var(--fs-drama-hero); margin-bottom: 48px; }
.pitch-grid { display: grid; grid-template-columns: 6fr 6fr; gap: clamp(24px, 4vw, 56px); align-items: start; }
.pitch-copy p { font-size: var(--fs-body); font-weight: 500; max-width: 620px; }
.pitch-copy p + p { margin-top: 24px; }
.pitch-hats { color: var(--color-ink-soft); }
.pitch-frame { border: 2px solid var(--color-ink); position: relative; background: var(--color-paper-warm); }
.pitch-frame img { width: 100%; height: auto; display: block; }
.pitch-frame .cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: var(--color-ink); color: var(--color-paper);
  padding: 8px 12px; display: flex; justify-content: space-between; gap: 12px;
}
@media (max-width: 900px) { .pitch-grid { grid-template-columns: 1fr; } }

/* ── contact modal — mirrors rodericandrews.com ContactModal ── */
.modal { position: fixed; inset: 0; z-index: 100; display: none; align-items: center; justify-content: center; padding: 16px; }
.modal.open { display: flex; }
.modal-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(4px); border: none; cursor: pointer; }
.modal-panel { position: relative; background: var(--color-paper); border: 2px solid var(--color-ink); max-width: 576px; width: 100%; padding: 32px; max-height: 90vh; overflow-y: auto; }
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 24px; }
.modal-head .pill { color: var(--color-ink-soft); }
.modal-close { background: none; border: none; font-size: 24px; line-height: 1; cursor: pointer; color: var(--color-ink); }
.modal-panel h3 { font-family: var(--font-drama); font-style: italic; font-size: var(--fs-drama-m); margin-bottom: 8px; }
.modal-panel .tldr { font-size: var(--fs-body-s); color: var(--color-ink-soft); margin-bottom: 24px; }
.modal-panel form { display: grid; gap: 16px; }
.modal-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.modal-panel label span { display: block; font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 0.08em; font-size: 11px; color: var(--color-ink-soft); margin-bottom: 8px; }
.modal-panel input, .modal-panel textarea {
  width: 100%; border: 1px solid var(--color-ink-faint); background: transparent;
  padding: 12px 16px; font-family: var(--font-heading); font-size: var(--fs-body-s);
  color: var(--color-ink); outline: none; resize: none;
}
.modal-panel input:focus, .modal-panel textarea:focus { border-color: var(--color-ink); }
.modal-submit { width: 100%; cursor: pointer; }
.modal-mail { display: block; text-align: center; margin-top: 16px; color: var(--color-ink-soft); text-decoration: none; }
@media (max-width: 700px) { .modal-row { grid-template-columns: 1fr; } }
footer.site a { color: inherit; text-decoration: none; }
footer.site a:hover { color: var(--color-paper); }

/* ── final cta ───────────────────────────────────────── */
.final { padding: clamp(72px, 12vh, 140px) 0; }
.final h2 { font-size: var(--fs-final); }
.final .drama-line { font-size: var(--fs-drama-final); margin: 16px 0 36px; }
.final .note { margin-top: 24px; color: var(--color-ink-soft); }

footer.site { background: var(--color-ink); color: var(--color-paper); padding: 16px 0; }
footer.site .wrap { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; color: rgba(243, 238, 228, 0.7); }

@media (max-width: 900px) {
  .brief-grid { grid-template-columns: 1fr; }
  .brief-cell + .brief-cell { border-left: none; padding-left: 0; border-top: 1px solid var(--color-ink-faint); }
  .feat-text { grid-template-columns: 1fr; }
  .usecase { border-top: 1px solid var(--color-ink-faint); padding-top: 24px; }
  .stat-grid { grid-template-columns: 1fr 1fr; }
  .stat:nth-child(3) { border-left: none; padding-left: 0; }
  .stat:nth-child(n+3) { border-top: 1px solid rgba(243, 238, 228, 0.25); }
  .reel { grid-template-columns: 1fr; }
}

/* ── 2. TOPBAR FIX ───────────────────────────────────────────────────────
   BUG (Roderic, 2026-08-06): "rodericandrews.com and links and stuff —
   they're touching the very top edge." Cause: `.topbar` had a hard
   `height: 36px` while its content needed 40px once the label wrapped on
   narrow screens. With `align-items: center` the overflow bled equally
   above and below, so the first line sat flush at y=0 with no padding.

   Fix: the bar sizes to its content with real vertical padding and can
   never clip. `min-height` preserves the original 36px on wide screens. */
.topbar {
  height: auto;
  min-height: 36px;
  padding: 8px 0;
  line-height: 1.3;
}
.topbar .wrap { flex-wrap: wrap; align-items: center; row-gap: 2px; }
.topbar a:hover { color: var(--color-bauhaus-yellow); }

/* The long-form label is swapped for the short one on phones rather than
   allowed to wrap — two mono lines in a utility bar reads as a mistake. */
.tb-short { display: none; }

/* ── 3. RESPONSIVE PASS ──────────────────────────────────────────────────
   The desktop grid work was already sound (a full-page sweep at 375px
   found zero horizontal overflow). What was missing was a phone tier:
   the layout collapsed to one column but kept its multi-column padding,
   and several mono utility rows had no room to breathe. */

/* Never-deform guard (CLAUDE.md sitewide rule, Roderic 2026-07-05: no image
   may be stretched, squashed, or have its aspect ratio changed — ever).
   `.pitch-frame img` sets width: 100% + height: auto and no object-fit, so
   it inherits the CSS default of `fill`. That does not distort while the
   height stays auto — but this is a shared template now, and the first case
   study that gives the frame a fixed height or aspect-ratio would stretch
   its photo silently. `contain` is a no-op today and a guarantee tomorrow.
   Locked by e2e/case-study-template-regression.spec.js. */
.pitch-frame img { object-fit: contain; }

/* Guard: `.feat-frame` breaks its container with `width: 100vw - 48px`.
   `100vw` counts the classic desktop scrollbar, so it can overhang by a
   few px and summon a horizontal scrollbar. `clip` contains it without
   creating a scroll container (unlike `hidden`, which would break any
   position: sticky descendant). */
html, body { overflow-x: clip; }

@media (max-width: 560px) {
  /* `.mono` sets font-size on `.wrap` itself, so a rule on `.topbar`
     alone loses — match the element that carries the class. At 11px with
     tightened tracking the short label and the link share one line at
     375px, which is the point: a two-line utility bar reads as broken. */
  .topbar .wrap.mono { font-size: 11px; letter-spacing: 0.06em; flex-wrap: nowrap; }
  .topbar .wrap.mono > span { flex: 0 1 auto; min-width: 0; }
  .topbar .wrap.mono a { flex: 0 0 auto; white-space: nowrap; }
  .tb-full { display: none; }
  .tb-short { display: inline; }

  /* Single-column cells inherited the gutter that separated columns. */
  .brief-cell { padding-right: 0; }
  .stat { padding-right: 0; }
  .stat + .stat { padding-left: 0; }

  /* Mono rows with two ends: let them stack instead of colliding. */
  .section-eyebrow { flex-wrap: wrap; row-gap: 4px; margin-bottom: 28px; }
  .feat-frame .cap,
  .pitch-frame .cap,
  .reel-item .cap,
  footer.site .wrap { flex-wrap: wrap; row-gap: 4px; font-size: 12px; }

  /* Full-width CTAs — side-by-side buttons at 375px leave ~150px each,
     which truncates the mono labels. */
  .cta-row { gap: 12px; }
  .cta-row .btn { width: 100%; text-align: center; }
  .final .cta-row .btn { width: 100%; }

  /* Frames sit closer to the edge on phones; 48px of inset on a 375px
     screen spends 13% of the width on margin. */
  .feat-frame { width: calc(100vw - 24px); }

  .modal-panel { padding: 24px 20px; max-height: 94vh; }
}

@media (max-width: 380px) {
  /* Smallest supported tier — the 4-up stat grid is unreadable at 2-up. */
  .stat-grid { grid-template-columns: 1fr; }
  .stat:nth-child(n+2) { border-top: 1px solid rgba(243, 238, 228, 0.25); }
}

/* ── 4. EMBED MODE ───────────────────────────────────────────────────────
   Set by case-study.js when the page is mounted inside a parent surface
   (the planned §-origami case-study flap, which will open a case study
   in-page, scroll it to completion, then advance to the next one). The
   parent owns the chrome, so the page drops its own topbar and footer and
   keeps only the story. Nothing else changes — the page is the same
   document in both mounts, which is the whole point. */
body.is-embedded .topbar,
body.is-embedded footer.site { display: none; }
body.is-embedded .hero { padding-top: clamp(32px, 5vh, 64px); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ── 6. PHONE CAPTURES, SIDE BY SIDE ─────────────────────────────────────
   Roderic, 2026-08-06: "you're blowing up mobile images to desktop aspect
   ratio, and of course they're completely blown out and blurred… put side by
   side like we did for the design system in War Room."

   Phone captures are ~430x845. In the base 16:9 frame, object-fit: cover
   crops them to a horizontal band AND upscales ~3.3x. Paired into a split
   frame each cell is 8:9, so `contain` renders the whole phone at roughly
   native height — a ~1:1 pixel match instead of a 3.3x blow-up. The
   letterbox falls on the frame's own graph-paper ground, which is already
   the house treatment for undersized art. */
.feat-frame--phones { background: var(--color-paper-warm); }
.feat-frame--phones .cell {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  background:
    linear-gradient(var(--color-graph) 1px, transparent 1px) 0 0 / 100% 28px,
    linear-gradient(90deg, var(--color-graph) 1px, transparent 1px) 0 0 / 28px 100%,
    var(--color-paper-warm);
}
/* contain, never cover — a phone screen cropped to a band is unreadable, and
   the sitewide never-deform rule forbids fixing that by stretching. */
.feat-frame--phones img {
  position: static;
  width: auto;
  height: 100%;
  max-width: 100%;
  object-fit: contain;
}
@media (max-width: 560px) {
  /* Two phones side by side at 375px leaves each ~170px — under the
     legibility floor. Stack them and let the frame find its own height. */
  .feat-frame.feat-frame--phones { aspect-ratio: auto; grid-template-columns: 1fr; }
  .feat-frame--phones img { height: auto; width: 100%; }
}
