/* ============================================================
   pages.css — Page-specific layout
   Components live in components.css; this is layout + scoped style.
   ============================================================ */

/* ----- Sitewide utility: scroll reveal -----
   Add `.reveal-on-scroll` to a section that should fade up when it enters
   viewport. Triggered by assets/js/reveal.js, which adds `.is-visible`.
   Page-specific scoped reveals (.about-spread, .about-tools-blend) live with
   their pages — they use the same `.is-visible` flag added by the same script. */
.reveal-on-scroll {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-reveal) var(--ease-out),
              transform var(--dur-reveal) var(--ease-out);
}
.reveal-on-scroll.is-visible {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .reveal-on-scroll {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ----- HOME ----- */
/* Hero — text-only. Bounded vertical padding (no full-screen min-height), with
   roomy spacing between eyebrow / headline / body and a looser headline line
   height. Display headline breaks into two lines and scales via clamp; body
   stays at 2/3. */
.home-hero {
  padding-top: var(--space-10);
  padding-bottom: 88px;   /* 88 + .home-selected 88 = the old 176 gap, split equally so the hero border sits centered between the two sections */
}
.home-hero-text { max-width: none; }
.home-hero .hero-subline { margin-bottom: var(--space-7); }
.home-hero .hero-headline {
  max-width: none;
  font-size: clamp(38px, 6.5vw, 84px);
  line-height: 1.4;
  margin-bottom: var(--space-8);
}
.home-hero .hero-body { max-width: 66%; }

@media (max-width: 720px) {
  .home-hero .hero-body { max-width: 100%; }
}

.home-selected {
  margin-top: 88px;   /* paired with .home-hero padding-bottom: 88px — centers the divider */
}
.home-selected h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-h2);
  letter-spacing: -0.015em;
  margin-bottom: var(--space-7);
}
.home-selected .lead {
  font-size: var(--fs-body);
  color: var(--text-muted);
  max-width: 56ch;
  margin-bottom: var(--space-7);
  line-height: 1.55;
}
.work-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
}
.selected-cta {
  margin-top: var(--space-7);
  text-align: right;
}
/* Forward link mirroring the case-study back-link (.case-crumb) — arrow slides
   right on hover instead of left. */
.selected-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-base);
  text-decoration: none;
}
.selected-link-arrow {
  display: inline-block;
  width: 16px;
  height: 16px;
  transition: transform var(--dur-fast) var(--ease-out);
}
.selected-link:hover .selected-link-arrow { transform: translateX(3px); }
.selected-link:focus-visible { outline: 2px solid var(--text-base); outline-offset: 4px; }

/* ----- Home · Where I do my best work (asymmetric) ----- */
.home-capabilities {
  margin-top: var(--space-10);
}
.section-eyebrow {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  background: var(--text-base);
  color: var(--accent-lime);
  padding: 7px 14px;
  border-radius: var(--radius-pill);
  margin-bottom: var(--space-5);
  transform: rotate(-1deg);
}
.capabilities-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
  gap: var(--space-9);
  align-items: start;
}
.capabilities-lead h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(40px, 5.6vw, 64px);
  /* line-height >= 1.1 — required for rotated .accent block clearance (see design-system-v1 § Type) */
  line-height: 1.1;
  letter-spacing: var(--tracking-headline);
  max-width: 12ch;
  margin-bottom: var(--space-5);
}
.capabilities-lead h2 .accent {
  display: inline-block;
  background: var(--accent-soft);
  padding: 0 0.18em;
  margin: 0 -0.05em;
  border-radius: 6px;
  transform: rotate(-1deg);
}
.capabilities-lead .lead {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--text-muted);
  max-width: 36ch;
}
.capabilities-list .capability {
  border-top: 2px solid var(--text-base);
  padding: var(--space-6) 0;
}
.capabilities-list .capability:first-child {
  border-top: 0;
  padding-top: 0;
}
.capabilities-list .capability:last-child {
  padding-bottom: 0;
}
.capability-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: var(--lh-snug);
  letter-spacing: -0.01em;
  margin-bottom: var(--space-3);
}
.capability-body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--text-muted);
  max-width: 64ch;
}

@media (max-width: 920px) {
  .capabilities-grid { grid-template-columns: 1fr; gap: var(--space-6); }
}

/* ----- Home · How I work (forest section, lime ink) ----- */
.home-process-wrap {
  margin-top: var(--space-10);
  background: var(--text-base);
  color: var(--accent-lime);
  padding: var(--space-9) 0 var(--space-10);
  /* Bleed edge-to-edge: cancel the shell's auto-centering by pulling out. */
}
.process-head {
  margin-bottom: var(--space-8);
}
.home-process h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(40px, 5.4vw, 64px);
  /* line-height >= 1.1 — required to keep ascenders/descenders from clashing across the explicit line break */
  line-height: 1.1;
  letter-spacing: var(--tracking-headline);
  color: var(--accent-lime);
  margin: 0;
}
.process-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-7);
  list-style: none;
  padding: 0;
}
.step {
  position: relative;
}
/* Numbered stepper (Option A) — lime numeral discs linked by a connector line.
   Reuses the hgo-stepper pattern, recolored for the forest band: lime disc +
   forest numeral, accent-soft connector. */
.step-num {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-pill);
  background: var(--accent-lime);
  color: var(--text-base);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-lg);
  letter-spacing: -0.02em;
  margin-bottom: var(--space-4);
}
/* Connector runs from this disc's centre to the next disc's centre:
   100% = column width, + the grid gap = distance between adjacent centres
   (each disc sits 28px from its column left). */
.process-grid.is-stepper .step::after {
  content: "";
  position: absolute;
  top: 28px;
  left: 28px;
  width: calc(100% + var(--space-7));
  height: 2px;
  background: var(--accent-soft);
  opacity: 0.45;
  z-index: 0;
}
.process-grid.is-stepper .step:last-child::after { display: none; }
.step-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-h4);
  line-height: var(--lh-snug);
  letter-spacing: -0.01em;
  margin-bottom: var(--space-3);
  color: var(--accent-lime);
}
.step-body {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: var(--bg-elevated); /* #FBFCF6 — neutral off-white on forest, full opacity for readability */
  max-width: 32ch;
}

@media (max-width: 920px) {
  .process-grid { grid-template-columns: 1fr; gap: var(--space-6); }
  .process-grid.is-stepper .step::after { display: none; }
}

@media (max-width: 920px) {
  .work-strip { grid-template-columns: 1fr; }
}

/* ----- ABOUT: hero -----
   Numbered editorial spreads (01, 02, 03) follow. Closes on a forest band
   with categorized tool rows (.about-tools-blend). Animations defined below
   the layout block. */
.about-hero {
  padding-top: var(--space-9);
  padding-bottom: var(--space-7);
  border-bottom: 1px solid var(--border-base);
}
.about-hero .eyebrow {
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: 700;
  margin-bottom: var(--space-5);
}
.about-hero h1 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(48px, 7vw, 88px);
  line-height: 1.1; /* required when .accent rotates — design-system rule */
  letter-spacing: var(--tracking-tight);
  max-width: 18ch;
  margin-bottom: var(--space-6);
}
.about-hero h1 .accent {
  display: inline-block;
  background: var(--accent-soft);
  padding: 0 0.18em;
  margin: 0 -0.05em;
  border-radius: 6px;
  transform: rotate(-1deg);
}
.about-hero p {
  font-size: var(--fs-body-lg);
  line-height: 1.55;
  color: var(--text-muted);
  max-width: 56ch;
}

/* ----- ABOUT: numbered editorial spreads -----
   Each spread = giant SVG numeral on one side, body text on the other.
   `.is-flipped` swaps sides; `.is-lime` swaps the outlined numeral for a
   lime-filled one (used on 02 for visual rhythm). */
.about-spreads { margin-top: var(--space-9); }

.about-spread {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: var(--space-7);
  align-items: center;
  margin-bottom: var(--space-10);
}
.about-spread.is-flipped { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
.about-spread.is-flipped .about-numeral     { order: 2; justify-self: end; }
.about-spread.is-flipped .about-spread-text { order: 1; }

/* Numerals: SVG <text> with stroke-linejoin: round.
   Drawing as SVG paths (instead of CSS -webkit-text-stroke) keeps strokes
   crisp at large display sizes — corners rounded by linejoin rather than
   pinched at sharp glyph junctions. Outlined uses stroke; .is-lime fills. */
.about-numeral {
  display: block;
  width: clamp(180px, 22vw, 340px);
  height: auto;
  align-self: center;
  overflow: visible;
}
.about-numeral-text {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 170px;
  letter-spacing: -0.05em;
  fill: none;
  stroke: var(--text-base);
  stroke-width: 4;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.about-spread.is-lime .about-numeral-text {
  fill: var(--accent-lime);
  stroke: none;
}

/* Small-caps eyebrow used inside each spread + at the top of the tools band. */
.block-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-3);
}

.about-spread-text h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(28px, 3.6vw, 40px);
  line-height: var(--lh-snug);
  letter-spacing: -0.01em;
  margin-bottom: var(--space-4);
  max-width: 18ch;
}
.about-spread-text p {
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--text-base);
  max-width: 56ch;
}

@media (max-width: 720px) {
  .about-spread,
  .about-spread.is-flipped { grid-template-columns: 1fr; gap: var(--space-3); }
  .about-spread.is-flipped .about-numeral     { order: 0; justify-self: start; }
  .about-spread.is-flipped .about-spread-text { order: 1; }
  .about-numeral { width: clamp(140px, 28vw, 220px); justify-self: start; }
}

/* ----- ABOUT: closing forest band (tools by category) -----
   Full-bleed dark section. Categorized rows (Design / Research / Code & ship)
   with quiet accent-soft @ 30% dividers. Outlined accent-soft chips ride the
   dark surface. Everything inside is recoloured for the dark mode of the band. */
/* "Why I approach products differently" — a lead line above a 3-card triad */
.about-approach { margin-top: var(--space-9); }
.about-approach-lead {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(22px, 2.6vw, 30px);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--text-base);
  max-width: 30ch;
  margin-top: var(--space-4);
}
.about-approach-grid {
  list-style: none;
  margin-top: var(--space-7);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
}
.about-approach-grid li {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-6);
  background: var(--bg-elevated);
  border: 1px solid var(--border-base);
  border-radius: var(--radius-l);
}
.principle-check {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: var(--accent-soft);
  border-radius: var(--radius-pill);
  color: var(--text-base);
}
.principle-check svg { width: 18px; height: 18px; }
.principle-text {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-body-lg);
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--text-base);
}
@media (max-width: 720px) {
  .about-approach-grid { grid-template-columns: 1fr; }
}

.about-tools-blend {
  margin-top: var(--space-9);
  background: var(--text-base);
  color: var(--accent-lime);
  padding: var(--space-9) 0 var(--space-10);
}
.about-tools-blend .block-num { color: var(--accent-soft); margin-bottom: var(--space-5); }

.about-tools-headline {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(40px, 5.4vw, 64px);
  line-height: 1.1; /* required when .accent rotates */
  letter-spacing: -0.015em;
  color: var(--accent-lime);
  margin: 0 0 var(--space-8);
  max-width: 30ch;
}
.about-tools-headline .accent {
  display: inline-block;
  background: var(--accent-lime);
  color: var(--text-base);
  padding: 0 0.18em;
  margin: 0 -0.05em;
  border-radius: 6px;
  transform: rotate(-1deg);
}

.about-tools-rows {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  max-width: 760px;
}
.about-tools-row {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: var(--space-5);
  align-items: center;
  border-top: 1px solid rgba(212, 245, 197, 0.30); /* accent-soft @ 30% — quiet rule */
  padding: var(--space-5) 0;
}
.about-tools-row:last-child { border-bottom: 1px solid rgba(212, 245, 197, 0.30); }
.about-tools-row-label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-small);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--accent-lime);
}
.about-tools-row-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding: 0;
  list-style: none;
}
.about-tools-row-chips li {
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  background: transparent;
  border: 1px solid var(--accent-soft);
  color: var(--accent-soft);
}

@media (max-width: 720px) {
  .about-tools-row { grid-template-columns: 1fr; gap: var(--space-2); padding: var(--space-4) 0; }
}

/* ----- ABOUT: animations -----
   Restrained set:
     - Hero .accent uses Home's hero-accent-enter keyframe, slowed to 1.2s
     - Each spread body text fades up as one unit (no per-element stagger)
     - Outlined numerals (01, 03) draw along their stroke path (2.2s)
     - Lime numeral (02) gets a soft opacity fade — matches the calmer tempo
     - Tools band fades up as a single block
   Triggered by an IntersectionObserver (inline in about.html). */
.about-hero h1 .accent {
  animation: hero-accent-enter var(--dur-reveal) var(--ease-out) both;
}

.about-spread-text {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--dur-reveal) var(--ease-out) 0.25s,
              transform var(--dur-reveal) var(--ease-out) 0.25s;
}
.about-spread.is-visible .about-spread-text {
  opacity: 1;
  transform: none;
}

.about-spread:not(.is-lime) .about-numeral-text {
  stroke-dasharray: 1800;
  stroke-dashoffset: 1800;
  opacity: 0;
  transition: stroke-dashoffset var(--dur-draw) var(--ease-out),
              opacity var(--dur-reveal) var(--ease-out);
}
.about-spread:not(.is-lime).is-visible .about-numeral-text {
  stroke-dashoffset: 0;
  opacity: 1;
}

.about-spread.is-lime .about-numeral {
  opacity: 0;
  transition: opacity var(--dur-reveal) var(--ease-out);
}
.about-spread.is-lime.is-visible .about-numeral {
  opacity: 1;
}

.about-tools-blend .shell {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-reveal) var(--ease-out),
              transform var(--dur-reveal) var(--ease-out);
}
.about-tools-blend.is-visible .shell {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .about-spread-text,
  .about-spread .about-numeral,
  .about-spread .about-numeral-text,
  .about-tools-blend .shell {
    opacity: 1 !important;
    transform: none !important;
    stroke-dashoffset: 0 !important;
  }
}

/* ----- WORK INDEX (placeholder shell — filled in once content lands) ----- */
.work-index-hero {
  padding-top: var(--space-9);
  padding-bottom: var(--space-7);
}
.work-index-hero .eyebrow {
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: 700;
  margin-bottom: var(--space-5);
}
.work-index-hero h1 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(48px, 7vw, 88px);
  line-height: 1.0;
  letter-spacing: var(--tracking-tight);
  max-width: none;                       /* was 18ch — match the home hero so the work header isn't narrower */
  margin-bottom: var(--space-7);
}
.work-index-hero h1 .accent {
  display: inline-block;
  background: var(--accent-soft);
  padding: 0 0.18em;
  margin: 0 -0.05em;
  border-radius: 6px;
  transform: rotate(-1deg);
  animation: hero-accent-enter var(--dur-reveal) var(--ease-out) both;
}
.work-index-hero p {
  font-size: var(--fs-body-lg);
  line-height: 1.55;
  color: var(--text-muted);
  max-width: 66%;                        /* was 56ch — match the home hero body width */
}
.work-index-note {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: var(--space-4);
  font-size: var(--fs-body-sm);
  font-style: italic;
  color: var(--text-subtle);
}
.work-index-note svg { width: 24px; height: 24px; flex: none; }

.work-grid {
  margin-top: var(--space-5);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-5);
}
@media (max-width: 720px) {
  .work-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   CASE STUDY — Order History
   Components scoped to /work/<case>.html pages.
   Built 2026-05-29. Variety strategy:
   - Alternate surfaces (cream / forest / lime) every 1-2 sections.
   - No two adjacent sections share column count, surface OR anchor type.
   - Rotation as recurring motif (-2°, -1°, +1°, +2°) — not random.
   ============================================================ */

/* ----- Case hero (Variant C) — image-led split + full-bleed stat band
   Picked 2026-05-29 from hero-explorations preview. Replaces the earlier
   case-hero + meta-strip blocks (those were "card pills + 4-col strip" —
   metric chips read as accidental, gaps drifted unevenly).
   Structure:
     .case-hero      → wrapper (cream, equal-stretch grid)
     .case-crumb     → back-arrow link, SVG arrow matches site language
     .case-hero-split → 2-col grid (text + image), align-items: stretch
     .case-tag       → forest pill (eyebrow chip)
     .case-title     → hero H1, ≤14ch
     .case-sub       → lead paragraph
     .case-meta-grid → 2×2 dl of client/year/role/brief, border-top 2px
     .case-hero-image → bordered figure; img is absolute-positioned to
                        crop via object-fit: cover without pushing the
                        grid row taller than the text column
     .case-stats-band → full-bleed forest band (replaces meta-strip)
     .case-stats-grid → 3 equal columns, lime 1px hairlines between
   ----- */
.case-hero {
  padding-top: var(--space-8);
  padding-bottom: var(--space-8);
}
.case-crumb {
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: var(--space-6);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.case-crumb:hover { color: var(--text-base); }
.case-crumb:hover .crumb-arrow { transform: translateX(-3px); }
.case-crumb:focus-visible {
  outline: 2px solid var(--text-base);
  outline-offset: 4px;
  color: var(--text-base);
}
.crumb-arrow {
  display: inline-block;
  width: 16px;
  height: 16px;
  transition: transform var(--dur-fast) var(--ease-out);
}

.case-hero-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: var(--space-8);
  align-items: stretch;
}
.case-tag {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  background: var(--text-base);
  color: var(--accent-lime);
  padding: 7px 14px;
  border-radius: var(--radius-pill);
  margin-bottom: var(--space-5);
}
.case-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(40px, 5.2vw, 64px);
  /* line-height ≥ 1.05 — the rotated .accent block clips at tighter values */
  line-height: 1.05;
  letter-spacing: -0.025em;
  margin-bottom: var(--space-4);
  max-width: 14ch;
}
.case-title .accent {
  display: inline-block;
  background: var(--accent-soft);
  padding: 0 0.12em;
  margin: 0 -0.04em;
  border-radius: 6px;
  transform: rotate(-1deg);
  line-height: 1;
}
.case-sub {
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--text-muted);
  max-width: 42ch;
  margin-bottom: var(--space-6);
}
.case-meta-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4) var(--space-6);
  padding-top: var(--space-5);
  border-top: 2px solid var(--text-base);
  margin: 0;
}
.case-meta-cell { display: flex; flex-direction: column; gap: 4px; }
.case-meta-cell .lbl {
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-subtle);
}
.case-meta-cell .val {
  font-family: var(--font-display);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--text-base);
  line-height: 1.25;
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
}
/* Inline directional arrow inside a meta value — reuses the site's stroke
   language (same path as .closer-arrow / .crumb-arrow). Sized to the cap-
   height of the surrounding text so it reads as a typographic mark. */
.case-meta-cell .val-arrow {
  width: 0.7em;
  height: 0.7em;
  flex-shrink: 0;
  margin-top: -0.04em;
}

.case-hero-image {
  position: relative;
  border: 2px solid var(--text-base);
  border-radius: var(--radius-l);
  overflow: hidden;
  background: var(--bg-elevated);
  box-shadow: 0 4px 16px rgba(8, 52, 0, 0.10), 0 24px 48px rgba(8, 52, 0, 0.12);
  height: 100%;
  margin: 0;
  /* button reset — element is a <button> so we can open the gallery on click.
     Hover is a legitimate affordance now (click → gallery opens at the
     Final design slide). */
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
  display: block;
  width: 100%;
  transition: transform var(--dur-med) var(--ease-out),
              box-shadow var(--dur-med) var(--ease-out);
}
.case-hero-image:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(8, 52, 0, 0.14), 0 32px 60px rgba(8, 52, 0, 0.18);
}
.case-hero-image:focus-visible {
  outline: 2px solid var(--text-base);
  outline-offset: 4px;
}
/* Square hero variant (per-page opt-in via .is-square) — keeps a 1:1 crop
   instead of stretching to the text-column height. Scoped so the landscape
   Order History hero (shared .case-hero-image) is unaffected. */
.case-hero-image.is-square {
  height: auto;
  aspect-ratio: 6 / 5;   /* matches the 720x600 wireframe, so it fills with no empty band */
  align-self: start;
}
.case-hero-image.is-square img { object-position: center; object-fit: cover; }
/* Full natural-aspect hero (OH, CT) — shows the whole screen, no crop, top-aligned
   (same intent as SS's square hero, but each image keeps its own aspect). */
.case-hero-image.is-full { height: auto; align-self: start; }
.case-hero-image.is-full img { position: static; width: 100%; height: auto; object-fit: unset; }
.case-hero-image img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: top;
}

/* Full-bleed stats band (replaces the old meta-strip) */
.case-stats-band {
  background: var(--text-base);
  color: var(--bg-elevated);
  padding: var(--space-8) 0;
}
.case-stats-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Stretch (was center) so numerals share a top edge and the lime dividers
     are equal height regardless of how many lines each label wraps to.
     Promoted from the HGO-only `.hgo-stats` override 2026-06-06 so all three
     case studies match. */
  align-items: stretch;
}
.case-stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: 0 var(--space-6) 0 0;
}
.case-stat + .case-stat {
  border-left: 1px solid var(--accent-lime);
  padding-left: var(--space-6);
}
.case-stat .n {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(56px, 7vw, 88px);
  line-height: 0.85;
  letter-spacing: -0.03em;
  color: var(--accent-lime);
  display: inline-flex;
  align-items: center;
  gap: 0.18em;
}
/* Shared stat symbol/unit treatments — used by every case study's stats band
   so %, ~, the reduced-to arrow, and word-units (min) read identically.
   Numeral stays lime; symbols/units recede to accent-soft and sit smaller.
   Promoted from the HGO-only `.hgo-stat-*` classes 2026-06-06. */
.stat-sym {
  font-size: 0.66em;
  font-weight: 700;
  letter-spacing: 0;
  color: var(--accent-soft);
  align-self: center;
  margin-left: -0.08em;
}
.stat-sym.is-pre { margin-left: 0; margin-right: -0.08em; }
.stat-unit {
  font-size: 0.34em;
  font-weight: 700;
  letter-spacing: 0;
  color: var(--accent-soft);
  align-self: flex-end;
  /* negative left pulls back the .n flex gap (0.18em); colour already
     separates the unit from the numeral, so the gap can be tight. */
  margin: 0 0 0.22em -0.08em;
}
/* The reduced-to arrow (Order History) is a stat symbol too — same accent-soft
   recede, sized to sit with the %/~ symbols rather than with the numeral.
   (Reverses the 2026-06-03 0.72→0.85 bump so it matches the % treatment.) */
.stat-arrow {
  width: 0.66em;
  height: 0.66em;
  color: var(--accent-soft);
  flex-shrink: 0;
  margin-top: -0.02em;
}
.case-stat .l {
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-soft);
  max-width: 24ch;
  line-height: 1.3;
}

@media (max-width: 920px) {
  .case-hero-split { grid-template-columns: 1fr; gap: var(--space-6); }
  .case-title { font-size: clamp(36px, 9vw, 56px); }
  /* mobile: columns stack, so image returns to natural aspect */
  .case-hero-image { height: auto; }
  .case-hero-image img { position: static; height: auto; object-fit: contain; }
  .case-stats-grid { grid-template-columns: 1fr; gap: var(--space-5); }
  .case-stat + .case-stat {
    border-left: 0;
    border-top: 1px solid var(--accent-lime);
    padding-left: 0;
    padding-top: var(--space-4);
  }
}

/* ----- Case section frame (general)
   Used on cream sections so we get consistent vertical rhythm.
   `.is-forest-band` flips bg + ink. `.is-lime-band` does the lime treatment. */
.case-section {
  padding: var(--space-9) 0;
}
.case-section.is-forest-band {
  background: var(--text-base);
  color: var(--bg-elevated);
}
.case-section.is-forest-band .section-head h2,
.case-section.is-forest-band p { color: var(--bg-elevated); }
.case-section.is-forest-band .case-prose,
.case-section.is-forest-band .case-prose p { color: var(--accent-soft); }
.case-section.is-forest-band .case-prose-lead { color: var(--accent-soft); }
.case-section.is-lime-band {
  background: var(--accent-lime);
  color: var(--text-base);
}
.case-section.is-lime-band .section-head h2,
.case-section.is-lime-band .case-prose,
.case-section.is-lime-band .case-prose p,
.case-section.is-lime-band .case-prose-lead { color: var(--text-base); }
.case-section.is-lime-band .section-head .num {
  background: var(--text-base);
  color: var(--accent-lime);
}

.case-prose {
  max-width: 64ch;
  font-size: var(--fs-body-lg);
  /* Lowered 2026-06-03 from 1.65 → 1.55 to match other body text on the page
     (.hero-body, .case-sub, .goal-body, .persona-quote all sit at 1.55–1.6).
     1.65 made section 01's body line spacing visibly looser than every other
     prose block. */
  line-height: 1.55;
  color: var(--text-muted);
}
.case-prose-lead {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(26px, 3vw, 36px);
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--text-base);
  max-width: 22ch;
  margin-bottom: var(--space-5);
}
.case-prose p + p { margin-top: var(--space-4); }

/* ----- Asymmetric 60/40 split — used in Challenge ----- */
.split-60-40 {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 4fr);
  gap: var(--space-8);
  align-items: center;
}
.split-40-60 {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
  gap: var(--space-8);
  align-items: center;
}
.split-50-50 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: center;
}

/* ----- Challenge layout — text + problem ledger (left) beside one dominant
   tilted figure (right). Asymmetric, distinct from the symmetric splits. ----- */
.challenge-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: var(--space-8);
  align-items: start; /* top-align so "The old HGO" pill anchors with the prose, not floating */
}
.challenge-grid .case-lead { margin-bottom: var(--space-4); }
.problem-ledger {
  margin-top: var(--space-6);
  border-top: 2px solid var(--text-base);
}
.problem-ledger .ledger-row {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--border-base);
}
.problem-ledger .ledger-row:last-child { border-bottom: 0; }
.problem-ledger .ledger-num {
  flex: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-sm);
  line-height: 1.5;
  color: var(--text-base);
  background: var(--accent-soft);
  border-radius: var(--radius-s);
  padding: 1px 9px;
}
.problem-ledger .ledger-text {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  color: var(--text-muted);
}

@media (max-width: 920px) {
  .split-60-40, .split-40-60, .split-50-50, .challenge-grid { grid-template-columns: 1fr; gap: var(--space-6); }
}

/* ----- Big outlined section numeral (SVG-like CSS look) — reused on Challenge anchor ----- */
.section-numeral {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(140px, 18vw, 240px);
  line-height: 0.85;
  letter-spacing: -0.04em;
  color: transparent;
  -webkit-text-stroke: 3px var(--text-base);
  display: inline-block;
  margin-bottom: var(--space-5);
}
.is-forest-band .section-numeral {
  -webkit-text-stroke: 3px var(--accent-lime);
}
.is-lime-band .section-numeral {
  -webkit-text-stroke: 3px var(--text-base);
}

/* ============================================================
   CARD SYSTEM — base + meaning modifiers + sub-parts.
   Canonical source: framework/ux-patterns/card-system.md.
   One base per job; differences are named .is-* modifiers,
   never new near-identical classes. Interaction values
   (lift 4px, focus ring) are global, set once here.
   ============================================================ */

/* Base: bordered image card, interactive (gallery / zoom trigger). */
.case-frame {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;                 /* button / anchor reset */
  text-align: left;
  font: inherit;
  color: inherit;
  background: var(--bg-elevated);
  /* Light default frame (was 2px forest) — a strong near-black border read as
     boxy on multi-image sections; 1px subtle + soft shadow lets images breathe.
     Strong emphasis is reserved for .is-answer (lime). 2026-06-06. */
  border: 1px solid var(--border-base);
  border-radius: var(--radius-l);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  transition: translate var(--dur-med) var(--ease-out),
              transform var(--dur-med) var(--ease-out),
              box-shadow var(--dur-med) var(--ease-out);
}
/* Lift uses `translate` (NOT transform) so it composes with a tilt's
   `transform: rotate()` — a tilted figure lifts on hover without straightening. */
.case-frame:hover  { translate: 0 -4px; box-shadow: var(--shadow-lg); }
.case-frame:active { translate: 0 -1px; }
.case-frame:focus-visible { outline: 2px solid var(--text-base); outline-offset: 4px; }
/* A direct child image shows the whole image at natural height (no crop) —
   use this when the frame has no `.case-frame-media` ratio wrapper. */
.case-frame > img { display: block; width: 100%; }

/* Modifier: the answer / shipped design — lime border, no lift (it's a
   showcase, usually with annotation pins, not a trigger). */
.case-frame.is-answer {
  border-color: var(--accent-lime);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.30);
  cursor: default;
}
.case-frame.is-answer:hover { translate: none; box-shadow: 0 16px 48px rgba(0, 0, 0, 0.30); }

/* Modifier: sits on a forest / dark band — a forest border vanishes there,
   so drop it and use a black-alpha shadow that reads on dark. */
.case-frame.is-on-dark { border: 0; box-shadow: none; }
.case-frame.is-on-dark:hover { translate: 0 -4px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.30); }

/* Modifier: the "pinned paper" look — subtle 1px edge + soft paper shadow.
   Still interactive when it's a button/link: it lifts on hover (base `translate`)
   and deepens its shadow; cursor + focus ring come from the base. A truly
   decorative <figure> suppresses the lift so there's no false affordance. */
.case-frame.is-static {
  border: 1px solid var(--border-base);
  box-shadow: 0 1px 3px rgba(8, 52, 0, 0.08);
}
.case-frame.is-static:hover { box-shadow: 0 1px 2px rgba(8, 52, 0, 0.05), 0 8px 24px rgba(8, 52, 0, 0.10); }
figure.case-frame, article.case-frame { cursor: default; }
figure.case-frame:hover { translate: none; box-shadow: 0 1px 3px rgba(8, 52, 0, 0.08); }
/* Decorative static figures (e.g. state tiles) must not hover-lift — overrides
   the .case-frame.is-static:hover shadow so there's no false click affordance. */
figure.case-frame.is-static:hover { box-shadow: 0 1px 3px rgba(8, 52, 0, 0.08); translate: none; }

/* Tilt: there is NO generic tilt utility on .case-frame. Decorative single-figure
   tilt was removed 2026-06-06 (read as a glitch at 1°, and undercut the precision of
   product screenshots). Tilt is allowed ONLY when rotation is structural to a
   composition — e.g. the overlapping `.streamline-pair` (±2°, defined in its own
   block). Never as decoration on a lone figure. See card-system.md § Tilt.
   The frame lift uses `translate` (above) so any composition-level `transform: rotate`
   still composes with the hover lift. */
.case-frame.is-static.tilt-left:hover,   .case-frame.is-static.tilt-left:active   { transform: rotate(-2deg); }
.case-frame.is-static.tilt-right:hover,  .case-frame.is-static.tilt-right:active  { transform: rotate(2deg); }

/* Sub-part: aspect-ratio media holder. Ratio is data — set per use via
   --frame-ratio (default 16:10); crop origin via --frame-pos (default top). */
.case-frame-media {
  display: block;            /* span default is inline — would collapse the ratio box */
  position: relative;
  width: 100%;
  aspect-ratio: var(--frame-ratio, 16 / 10);
  overflow: hidden;
  background: var(--bg-base);
}
.case-frame-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: var(--frame-pos, top);
}
/* Fill variant: media stretches to fill a flex-column card (e.g. the research
   feature tile) instead of holding a fixed ratio. The card must be a flex column. */
.case-frame-media.is-fill { aspect-ratio: auto; flex: 1 1 auto; min-height: 0; }

/* Sub-part: single caption strip (one label). */
.case-frame-cap {
  display: block;
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border-base);
  background: var(--bg-elevated);
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-subtle);
}

/* Sub-part: meta footer (number + note) for indexed grids. */
.case-frame-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid rgba(95, 107, 84, 0.5); /* text-subtle @ 50% */
  background: var(--accent-soft);
}
.case-frame-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h4);
  letter-spacing: -0.01em;
  color: var(--text-base);
}
.case-frame-note {
  font-family: var(--font-body);
  font-size: var(--fs-small);
  color: var(--text-muted);
  text-align: right;
  line-height: 1.4;
  min-height: 2.8em; /* reserve 2 lines so footers match height across a row */
  display: flex;
  flex-direction: column;
  justify-content: center; /* center the (1- or 2-line) text within the reserved height */
}

/* ----- Figure with tilt ----- */
.figure-tilt {
  position: relative;
  background: var(--bg-elevated);
  border: 1px solid var(--border-base);
  border-radius: var(--radius-l);
  overflow: hidden;
  transition: transform var(--dur-med) var(--ease-out), box-shadow var(--dur-med) var(--ease-out);
  /* Tighter shadow 2026-06-03 — was 0 8px 24px (read as "lift / interactive").
     A tight 0 1px 3px gives the figure a paper edge against the page without
     implying it can be clicked. Interactive variants (.streamline-pair,
     .case-hero-image) bring their own lift + heavier shadow on hover. */
  box-shadow: 0 1px 3px rgba(8, 52, 0, 0.08);
}
.figure-tilt img { width: 100%; display: block; }
.figure-tilt .figure-caption {
  display: block; /* required when used as <span> inside a <button> wrapper */
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-subtle);
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border-base);
  background: var(--bg-elevated);
}
/* (Dead tilt utilities + decorative-figure hover/reveal/entrance rules removed
   2026-06-06 when standalone figure-tilt figures migrated to `.case-frame`.
   `.figure-tilt` now serves ONLY the streamline pair; its rotation is set in the
   `.streamline-pair` block. Reduced motion flattens it.) */
@media (prefers-reduced-motion: reduce) {
  .figure-tilt { transform: none; }
}

/* ----- Case head grid — used on the merged challenge section.
   Headline left (wider), tight body right (narrower). Replaces the older
   split-60-40 layout for sections that introduce the comparison below. */
.case-head-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--space-8);
  align-items: end;
  margin-bottom: var(--space-7);
}
.case-lead {
  font-family: var(--font-display);
  font-weight: 500;
  /* Dropped 2026-06-02 — was clamp(36px, 5vw, 60px); competed with hero .case-title.
     One display moment per page: hero (64px). case-lead reads as strong lead, not second hero. */
  font-size: clamp(36px, 4vw, 48px);
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: var(--text-base);
  max-width: 16ch;
  margin: 0;
}
@media (max-width: 920px) {
  .case-head-grid { grid-template-columns: 1fr; gap: var(--space-5); align-items: start; }
}

/* ----- Before/After comparison split
   Picks (v2 from challenge-explorations, 2026-05-29):
   - Card background: accent-soft (#D4F5C5) — pushes the white screenshot
     interiors forward, ties the card into the brand wash family.
   - Divider: text-subtle 1px — visible enough to read on accent-soft
     without the heaviness that 2px border-base would have on cream.
   - Equal-height image frames: 4:3 aspect, object-fit cover, object-position top.
   ----- */
.comparison {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  position: relative;
  border: 1px solid var(--border-base); /* lightened from 2px forest 2026-06-06 */
  border-radius: var(--radius-l);
  overflow: hidden;
  background: var(--accent-soft);
}
.comparison::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  width: 1px;
  background: var(--text-subtle);
  z-index: 2;
  pointer-events: none;
  opacity: 0.5;
}
.comparison-side {
  position: relative;
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.comparison-side + .comparison-side { border-left: 0; }
.comparison-tag {
  display: inline-block;
  background: var(--text-base);
  color: var(--accent-lime);
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  align-self: flex-start;
}
.comparison-side.is-after .comparison-tag {
  background: var(--accent-lime);
  color: var(--text-base);
}

/* Borderless rounded image inside the `.comparison` box — the box is the outer
   frame, so each cell is just a rounded image that lifts on hover (not a
   .case-frame, to avoid a frame-in-frame). The accent-soft box bg gives
   definition; a green-family border would vanish on it anyway. */
.comparison-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-s);
  overflow: hidden;
  background: var(--bg-elevated);
  /* button reset */
  padding: 0;
  border: 0;
  font: inherit;
  color: inherit;
  display: block;
  transition: transform var(--dur-med) var(--ease-out), box-shadow var(--dur-med) var(--ease-out);
}
.comparison-frame:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(8, 52, 0, 0.18); }
.comparison-frame:focus-visible { outline: 2px solid var(--text-base); outline-offset: 4px; }
.comparison-frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: top;
}

.comparison-side .comparison-note {
  font-size: var(--fs-small);
  color: var(--text-muted);
  line-height: 1.5;
}
@media (max-width: 720px) {
  .comparison { grid-template-columns: 1fr; }
  .comparison::before {
    top: 50%; left: 0; right: 0;
    width: auto; height: 1px;
    margin: 0;
  }
}

/* ----- Goals grid (sits inside lime band) ----- */
.goals-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
  align-items: stretch;
}
.goal-card {
  background: var(--text-base);
  color: var(--bg-elevated);
  border-radius: var(--radius-l);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-height: 240px;
  position: relative;
  overflow: hidden;
}
.goal-card .goal-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  color: var(--accent-lime);
  text-transform: uppercase;
}
.goal-card .goal-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-h4);
  line-height: 1.15;
  letter-spacing: -0.01em;
  min-height: 2.3em; /* reserve 2 lines so bodies align when titles differ in length */
}
.goal-card .goal-body {
  font-size: var(--fs-body-sm);
  line-height: 1.55;
  color: var(--accent-soft);
}
@media (max-width: 920px) {
  .goals-grid { grid-template-columns: 1fr; }
}

/* ----- Persona spreads — reuses the about-page numbered-spread pattern
   SVG monograms (not CSS -webkit-text-stroke) for crisp strokes at
   display sizes. Mirrors .about-numeral / .about-numeral-text styling:
   outlined letters use stroke-width 4 with linejoin: round; .is-lime
   variant swaps to a solid lime fill, no stroke, no box.
   Picked 2026-05-29 from personas-explorations variant A. ----- */
.persona-spread {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: var(--space-7);
  align-items: center;
  padding: var(--space-7) 0;
  border-top: 1px solid var(--border-base);
}
.persona-spread:last-of-type { border-bottom: 1px solid var(--border-base); }
.persona-spread.is-flipped { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
.persona-spread.is-flipped > .about-numeral  { order: 2; justify-self: end; }
.persona-spread.is-flipped > .persona-text   { order: 1; }
.persona-spread.is-lime .about-numeral-text  { fill: var(--accent-lime); stroke: none; }

.persona-text {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.persona-role {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-3);
}
.persona-name {
  font-family: var(--font-display);
  font-weight: 600;
  /* Lowered 2026-06-03 from clamp(28px, 3.6vw, 40px) — was outranking the section's
     .case-h2 (36px), breaking hierarchy. Now caps at 30px so the section title leads. */
  font-size: clamp(22px, 2.6vw, 30px);
  line-height: var(--lh-snug);
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-4);
  max-width: 14ch;
}
.persona-quote {
  font-family: var(--font-body);
  font-style: italic;
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--text-base);
  max-width: 48ch;
  margin: 0;
}
.persona-quote::before { content: "\201C"; color: var(--text-base); font-style: normal; font-weight: 600; }
.persona-quote::after  { content: "\201D"; color: var(--text-base); font-style: normal; font-weight: 600; }

@media (max-width: 920px) {
  .persona-spread,
  .persona-spread.is-flipped { grid-template-columns: 1fr; gap: var(--space-4); padding: var(--space-6) 0; }
  .persona-spread.is-flipped > .about-numeral { order: 0; justify-self: start; }
  .persona-spread.is-flipped > .persona-text  { order: 1; }
}

/* ----- Standalone case-section heading (replaces .section-head usage)
   Removes the lime-block num chip per design-update 2026-05-29: section
   number now lives in the eyebrow only (e.g. "02 / Goals"); the headline
   sits underneath at H2 weight. ----- */
.case-h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-h2);
  line-height: var(--lh-snug);
  letter-spacing: -0.015em;
  color: var(--text-base);
  margin: 0 0 var(--space-6);
  max-width: 22ch;
}
.case-section.is-forest-band .case-h2 { color: var(--bg-elevated); }
.case-section.is-lime-band .case-h2 { color: var(--text-base); }

/* ----- Research grid — Section 02 / Research
   60/40 asymmetric grid. Left column = ONE tall feature card (the primary
   research artifact). Right column = 2 smaller cards stacked vertically.
   Combined stacked height matches the feature card. (Reverted 2026-06-03
   from a brief 3-up trial — the editorial asymmetry reads richer.) */
.research-grid {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: var(--space-5);
  align-items: stretch;
}
/* min-height: 600px applies on desktop only. At mobile the grid collapses to
   a single column and the cards self-size — a 600px floor would leave empty
   space below the last card. */
@media (min-width: 921px) {
  .research-grid { min-height: 600px; }
}
.research-feature-col {
  display: flex;
}
.research-feature-col .research-card {
  flex: 1;
  display: flex;
  flex-direction: column;
}
.research-stack {
  display: grid;
  grid-template-rows: repeat(2, 1fr);
  gap: var(--space-5);
}
.research-stack .research-card {
  display: flex;
  flex-direction: column;
}
/* (research cards migrated to `.research-card.case-frame.is-on-dark` +
   `.case-frame-media.is-fill` + `.case-frame-meta` on 2026-06-06. The frame
   look + footer come from the shared base; `.research-card` is kept only as a
   layout/reveal hook — feature-col / stack sizing + scroll stagger key off it.) */
@media (max-width: 920px) {
  .research-grid { grid-template-columns: 1fr; }
  .research-feature-col .case-frame-media { aspect-ratio: 4 / 3; flex: 0 0 auto; }
  .research-stack { grid-template-rows: auto; gap: var(--space-5); }
  .research-stack .case-frame-media { aspect-ratio: 4 / 3; flex: 0 0 auto; }
}

/* ----- Concept grid — Concept direction (section 05).
   Renamed 2026-06-03 (was .scroll-strip — relic of the original horizontal-scroll
   variant that was converted to a static 3-up grid 2026-05-29). Now names match
   the actual layout.
   Image fills the upper portion via a 4:3 aspect-ratio frame with
   object-fit: cover. Meta divider matches section 01 (text-subtle 1px
   at 50% opacity) for a quiet, consistent treatment across the page. */
.concept-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
  padding: 0;
  margin: 0;
  align-items: start;
  --frame-pos: center; /* concept screenshots crop from center, not top */
}
/* (concept cards migrated to `.case-frame` + `.case-frame-media` + `.case-frame-meta`
   on 2026-06-06 — frame look + footer now come from the shared base. See card-system.md.) */
@media (max-width: 920px) {
  .concept-grid { grid-template-columns: 1fr; }
}

/* ----- Testing insights — verdict split (by device) + one evidence figure ----- */
.testing-verdict {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: var(--space-8);
  align-items: start;
}
.verdict-list { list-style: none; margin: 0; padding: 0; border-top: 2px solid var(--text-base); }
.verdict-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--border-base);
}
.verdict-ico {
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: var(--radius-m);
  background: var(--accent-soft);
  color: var(--text-base);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.verdict-ico svg { width: 22px; height: 22px; }
.verdict-text { display: flex; flex-direction: column; gap: 2px; }
.verdict-k {
  font-family: var(--font-body);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-subtle);
}
.verdict-v {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-body);
  color: var(--text-base);
}
.verdict-metric {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-small);
  letter-spacing: 0.02em;
  color: var(--text-muted);
  margin: var(--space-5) 0 0;
}
.verdict-metric b { color: var(--text-base); }
.testing-quote {
  margin: var(--space-7) 0 0;
  border-top: 2px solid var(--text-base);
  padding-top: var(--space-5);
  max-width: 72ch;
}
.testing-quote p {
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: clamp(16px, 1.7vw, 20px);
  line-height: 1.45;
  color: var(--text-base);
  margin: 0 0 var(--space-3);
}
.testing-quote cite {
  font-family: var(--font-body);
  font-style: normal;
  font-size: var(--fs-small);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-subtle);
}
@media (max-width: 920px) {
  .testing-verdict { grid-template-columns: 1fr; gap: var(--space-6); }
}

/* ----- Design-system state strip — every component state as a labelled tile ----- */
.state-strip {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-4);
  margin-top: var(--space-6);
  --frame-ratio: 4 / 3;   /* state thumbnails crop 4:3 */
  --frame-pos: center;
}
/* (state tiles migrated to `.case-frame.is-static` + `.case-frame-media` +
   `.case-frame-cap` 2026-06-06; the DS-showcase labels stay centered.) */
.state-strip .case-frame-cap { text-align: center; }
.spec-sheet-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-6);
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-base);
  background: none;
  border: 0;
  padding: 0;
}
.spec-sheet-link svg { width: 18px; height: 18px; transition: transform var(--dur-fast) var(--ease-out); }
.spec-sheet-link:hover { color: var(--text-muted); }
.spec-sheet-link:hover svg { transform: translateX(3px); }
.spec-sheet-link:focus-visible { outline: 2px solid var(--text-base); outline-offset: 4px; }
@media (max-width: 720px) {
  .state-strip { grid-template-columns: repeat(2, 1fr); }
}

/* ----- Spec callout (CD constraint chip overlay) ----- */
.spec-callout {
  position: relative;
  margin-top: var(--space-7);
  padding: var(--space-7) var(--space-6);
  background: var(--bg-elevated);
  border: 2px solid var(--text-base);
  border-radius: var(--radius-l);
  overflow: hidden;
}
.spec-callout::before {
  content: "";
  position: absolute;
  inset: 0;
  /* Flat accent-soft tint (was a double linear-gradient — violated locked principle 2.2 "no gradients"). */
  background-color: var(--accent-soft);
  opacity: 0.4;
  pointer-events: none;
}
.spec-callout-tag {
  position: relative;
  display: inline-block;
  background: var(--accent-lime);
  color: var(--text-base);
  border: 2px solid var(--text-base);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  padding: 8px 18px;
  border-radius: var(--radius-pill);
  margin-bottom: var(--space-4);
  transform: rotate(-1deg);
  z-index: 1;
}
.spec-callout p {
  position: relative;
  z-index: 1;
  max-width: 56ch;
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--text-muted);
}
.spec-image-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
  margin-top: var(--space-6);
  position: relative;
  z-index: 1; /* sit above the .spec-callout::before accent-soft tint */
}
/* Equal-height image area regardless of source aspect — sources vary from
   1.54 to 1.91. Force 3/2, cover-crop to top. (Spec figures are .case-frame
   buttons now; the crop is applied to the direct img.) */
.spec-image-strip .case-frame img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: top;
  display: block;
}
@media (max-width: 720px) {
  .spec-image-strip { grid-template-columns: 1fr; }
}

/* ----- Voices — Testing insights: three real user quotes in equal columns.
   Picked 2026-05-30 from testing-explorations variant A (post-iteration).
   Replaces the earlier .pull-quote + .testing-thumbs treatment (a single
   designer-summarized quote with three screenshot-of-quotes thumbnails).
   The screenshots were screenshots of text — better rendered as typography.
   - Each voice: bold body quote (centered) + small-caps tester label + role
   - Inline curly quotes via .q span sit in text-subtle (no pill, no rotation)
   - Hairline divider between columns matches section 01 (text-subtle @ 50%)
   ----- */
.voices {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 2px solid var(--text-base);
}
.voice {
  padding: var(--space-7) var(--space-5) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  text-align: center;
  align-items: center;
}
.voice + .voice {
  border-left: 1px solid rgba(95, 107, 84, 0.5);
}
.voice-quote {
  font-family: var(--font-body);
  font-weight: 700;
  font-style: italic;
  font-size: var(--fs-h4);
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--text-base);
  margin: 0;
  max-width: 22ch;
}
.voice-quote .q {
  color: var(--text-subtle);
  font-style: normal;
  font-weight: 400;
}
.voice-attr {
  margin-top: auto;
  padding-top: var(--space-5);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  border-top: 1px solid rgba(95, 107, 84, 0.5);
  width: 100%;
}
.voice-num {
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}
.voice-who {
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: 400;
  color: var(--text-muted);
}
@media (max-width: 920px) {
  .voices { grid-template-columns: 1fr; border-top: 0; }
  .voice { border-top: 1px solid rgba(95, 107, 84, 0.5); }
  .voice + .voice { border-left: 0; }
  .voice:first-child { border-top: 2px solid var(--text-base); }
}

/* Inline emphasis utility — accent-soft underline highlight inside body
   prose. Used to surface the load-bearing phrase in a context paragraph
   (e.g. the testing-insights body line). */
.case-prose .emph {
  /* Flat accent-soft fill (was a linear-gradient highlighter bar — violated locked
     principle 2.2 "no gradients"). box-decoration-break keeps the fill intact across
     line wraps. */
  background: var(--accent-soft);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  color: var(--text-base);
  font-weight: 600;
  padding: 0 0.04em;
}

/* ----- Final outcome — annotated design (replaces .bleed-figure)
   Picked 2026-06-01 from final-explorations Option A (with click-to-reveal
   animation). Forest band stays. Image fills the left/main column. Legend
   on the right has 7 items matching section 09 / Key improvements. Click a
   legend item → its pin animates in on the image at the matching spot;
   previous pin animates out. Only one pin shown at a time. ----- */
.final-outcome {
  background: var(--text-base);
  color: var(--bg-elevated);
  padding: var(--space-9) 0;
}
.final-outcome .case-eyebrow { color: var(--accent-lime); }
.final-outcome .case-h2 { color: var(--bg-elevated); }
.final-outcome .case-prose,
.final-outcome .case-prose p { color: var(--accent-soft); } /* was dark-on-dark; match the forest band */

.final-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--space-7);
  align-items: start;
  margin-top: var(--space-6);
}
/* Frame look (lime border + heavy shadow, no lift) now comes from
   `.case-frame.is-answer`; .final-figure keeps only position (for the pins). */
.final-figure { position: relative; margin: 0; }
.final-figure img { width: 100%; height: auto; display: block; }

/* Annotation pins — hidden by default, scale-in on .is-shown. Only one
   pin is shown at a time (controlled by JS toggling the class). */
.final-pin {
  position: absolute;
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-lime);
  color: var(--text-base);
  border: 2px solid var(--text-base);
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-small);
  letter-spacing: -0.01em;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
  z-index: 2;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0);
  transition: opacity var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out);
  pointer-events: none;
}
.final-pin.is-shown {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
/* Pulse ring on the active pin so the eye lands on it. */
.final-pin::after {
  content: "";
  position: absolute;
  inset: -8px;
  border-radius: var(--radius-pill);
  border: 2px solid var(--accent-lime);
  opacity: 0;
  pointer-events: none;
}
.final-pin.is-shown::after {
  animation: final-pin-pulse 1.8s var(--ease-out) infinite;
}
@keyframes final-pin-pulse {
  0%   { opacity: 0.7; transform: scale(0.9); }
  70%  { opacity: 0;   transform: scale(1.6); }
  100% { opacity: 0;   transform: scale(1.6); }
}
@media (prefers-reduced-motion: reduce) {
  .final-pin.is-shown::after { animation: none; }
  .final-pin { transition: opacity 0.01ms, transform 0.01ms; }
}

/* Legend — 7 numbered items, each a button. Active item gets lime
   bg on the number + brighter text. Hover lightens the text. */
.final-legend {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  list-style: none;
  padding: 0;
  margin: 0;
}
.final-legend-item {
  display: grid;
  grid-template-columns: 36px 1fr;
  gap: var(--space-4);
  align-items: start;
  padding: var(--space-3) var(--space-3) var(--space-3) 0;
  background: transparent;
  border: 0;
  border-radius: var(--radius-s);
  cursor: pointer;
  text-align: left;
  width: 100%;
  font: inherit;
  color: inherit;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.final-legend-item:hover { background: rgba(212, 245, 197, 0.06); }
.final-legend-item:focus-visible {
  outline: 2px solid var(--accent-lime);
  outline-offset: 2px;
}
.final-legend-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  border: 1.5px solid rgba(212, 245, 197, 0.50);
  background: transparent;
  color: var(--accent-soft);
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-small);
  letter-spacing: -0.005em;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.final-legend-item.is-active .final-legend-num {
  background: var(--accent-lime);
  color: var(--text-base);
  border-color: var(--accent-lime);
}
.final-legend-text {
  font-family: var(--font-body);
  font-size: var(--fs-body-sm);
  line-height: 1.5;
  color: var(--accent-soft);
  padding-top: 6px;
  transition: color var(--dur-fast) var(--ease-out);
}
.final-legend-item.is-active .final-legend-text,
.final-legend-item:hover .final-legend-text { color: var(--bg-elevated); }

@media (max-width: 920px) {
  .final-grid { grid-template-columns: 1fr; }
}

/* ----- Numbered manifest (Key improvements)
   Updated 2026-05-30:
   - Dropped hover (these items aren't interactive — hover on non-clickable
     content creates a false affordance).
   - Replaced the false hover with a real entrance animation: lime
     underlines stagger-draw left→right when the section scrolls into view.
   - Numerals filled lime (matches the persona-M precedent for lime fill on
     cream surfaces). Outline removed — webkit-text-stroke pinches at the
     glyph corners at display sizes.
   - Column widths shrink to content + uniform 24px gap so spacing reads
     consistently across all rows.
   ----- */
.manifest {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: repeat(4, auto);
  grid-auto-flow: column;
  gap: var(--space-3) var(--space-7);
  list-style: none;
  padding: 0;
  margin: 0;
}
.manifest-item {
  position: relative;
  display: grid;
  /* Fixed 72px num column so text starts at the same x position across rows.
     Padding-left on the item insets content from the divider's start —
     numbers don't sit flush against the underline's left edge. */
  grid-template-columns: 72px 1fr;
  column-gap: var(--space-7);
  align-items: center;
  padding: var(--space-5) 0;
  border-bottom: 1px solid var(--border-base);
}
/* Only the "01" item gets the right-side padding tweak — the "1" glyph's
   typographic right-edge sits slightly differently than the wider digits,
   so its row needs a small visual nudge to optically line up. */
.manifest-item:nth-child(1) {
  padding-right: var(--space-4);
}
/* Entrance: lime underline draws left→right when the section becomes
   visible. The reveal-on-scroll wrapper on the section toggles .is-visible
   via assets/js/reveal.js — we just hook the draw to that flag. */
.manifest-item::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  background: var(--text-base);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-slow) var(--ease-out);
}
.reveal-on-scroll.is-visible .manifest-item::after {
  transform: scaleX(1);
}
/* Stagger so the seven underlines arrive in sequence rather than all at once.
   Order is the 2-col reading order: left col top-to-bottom, then right. */
.reveal-on-scroll.is-visible .manifest-item:nth-child(1)::after { transition-delay: 0.05s; }
.reveal-on-scroll.is-visible .manifest-item:nth-child(2)::after { transition-delay: 0.15s; }
.reveal-on-scroll.is-visible .manifest-item:nth-child(3)::after { transition-delay: 0.25s; }
.reveal-on-scroll.is-visible .manifest-item:nth-child(4)::after { transition-delay: 0.35s; }
.reveal-on-scroll.is-visible .manifest-item:nth-child(5)::after { transition-delay: 0.45s; }
.reveal-on-scroll.is-visible .manifest-item:nth-child(6)::after { transition-delay: 0.55s; }
.reveal-on-scroll.is-visible .manifest-item:nth-child(7)::after { transition-delay: 0.65s; }

.manifest-item .manifest-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 56px;
  line-height: 0.9;
  letter-spacing: -0.02em;
  color: var(--accent-lime);
}
.manifest-item .manifest-text {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-body-lg);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--text-base);
}
@media (max-width: 920px) {
  .manifest { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  .manifest-item { grid-template-columns: 52px 1fr; }
  .manifest-item .manifest-num { font-size: 40px; }
}

/* ----- Streamlining (50/50 with overlapping images)
   Cards are now <button>s that open a modal with the full-size SVG —
   the hover-straighten is a legitimate affordance (click → modal opens).
   ----- */
.streamline-pair {
  position: relative;
  min-height: 480px;
}
.streamline-pair .figure-tilt {
  position: absolute;
  width: 70%;
  box-shadow: 0 8px 32px rgba(8, 52, 0, 0.25);
  /* button reset so the figure-tilt visual stays intact */
  padding: 0;
  background: var(--bg-elevated);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.streamline-pair .sp-back {
  top: 0;
  right: 0;
  transform: rotate(2deg);
  z-index: 1;
}
.streamline-pair .sp-front {
  bottom: 0;
  left: 0;
  transform: rotate(-2deg);
  z-index: 2;
}
.streamline-pair .figure-tilt:hover,
.streamline-pair .figure-tilt:focus-visible {
  z-index: 3;
  transform: rotate(0deg);
  padding: 0; /* lock in the reset so UA defaults don't reappear on hover */
}
.streamline-pair .figure-tilt:focus-visible {
  outline: 2px solid var(--text-base);
  outline-offset: 4px;
}
@media (max-width: 920px) {
  .streamline-pair { display: flex; flex-direction: column; gap: var(--space-5); min-height: auto; }
  .streamline-pair .figure-tilt { position: static; width: 100%; }
  /* Soft 1° tilt on mobile — keeps the editorial framing instead of collapsing to flat tiles. */
  .streamline-pair .sp-back  { transform: rotate(1deg); }
  .streamline-pair .sp-front { transform: rotate(-1deg); }
  /* Reduced-motion users still get the global figure-tilt override (transform: none). */
}

/* ============================================================
   GALLERY — case-study lightbox-style overlay
   One <dialog id="gallery"> holds the slides for the whole case
   study. Triggers open it at a specific index. Prev/next, thumbnail
   strip, ←/→ keys all navigate. Esc closes (native behaviour).
   Body scroll is locked while open via :has() so the page underneath
   doesn't shift. Image is centered in the stage.
   ============================================================ */

/* Body scroll lock while the gallery is open — keeps the underlying
   page exactly where it was. :has() is supported in current browsers;
   if it isn't, the page is still readable (just may scroll behind). */
html:has(dialog[open]) { overflow: hidden; }

.gallery {
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: var(--radius-l);
  background: var(--bg-elevated);
  color: var(--text-base);
  /* Bumped to near-full-viewport so images fill as much space as possible
     regardless of screen size. The lens (480px) still has breathing room. */
  width: 98vw;
  max-width: 98vw;
  height: 96vh;
  max-height: 96vh;
  overflow: hidden;
}
/* Only apply grid layout when actually open — otherwise the UA's
   `dialog:not([open]) { display: none }` would be overridden and the
   gallery would render inline on the page. Explicit fixed+inset+margin
   centering so the dialog sits at the viewport center on every browser
   regardless of UA defaults. */
.gallery[open] {
  display: grid;
  grid-template-rows: 56px 1fr 116px;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
}
.gallery::backdrop {
  background: rgba(8, 52, 0, 0.82);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

/* Top bar — position counter, caption, close. */
.gallery-bar {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-4);
  padding: 0 var(--space-5);
  background: var(--text-base);
  color: var(--bg-elevated);
  border-bottom: 1px solid rgba(212, 245, 197, 0.18);
}
.gallery-pos {
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--accent-lime);
}
.gallery-cap {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-body-sm);
  letter-spacing: -0.005em;
  color: var(--bg-elevated);
  text-align: center;
}
.gallery-close {
  /* 44x44 hit area (WCAG touch target); SVG icon stays at 16x16 visually. */
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--accent-lime);
  border: 1px solid rgba(212, 245, 197, 0.4);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.gallery-close svg { width: 16px; height: 16px; }
.gallery-close:hover {
  background: var(--accent-lime);
  color: var(--text-base);
  border-color: var(--accent-lime);
}
.gallery-close:focus-visible { outline: 2px solid var(--accent-lime); outline-offset: 4px; }

/* Stage — prev / image / next. Image centered both axes. */
.gallery-stage {
  position: relative;
  display: grid;
  grid-template-columns: 64px 1fr 64px;
  align-items: stretch;
  background: var(--bg-base);
  overflow: hidden;
}
.gallery-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
  padding: var(--space-5);
}
.gallery-img {
  display: block;
  /* Fill the frame and scale up small assets (several research/concept SVGs are
     only ~392px wide and otherwise rendered tiny). object-fit: contain keeps
     aspect + letterboxes; the zoom lens computes the contained box (modal.js). */
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: var(--radius-l);
}
/* Custom cursor on the gallery image while it's a zoomable target.
   Default = magnifier with "+" (zoom-in). After clicking the image
   to activate the lens, the frame gets .is-zooming and the cursor
   flips to magnifier with "-" (zoom-out). Click again to deactivate.
   Skipped on video frames (.is-video). */
.gallery-frame:not(.is-video) .gallery-img { cursor: zoom-in; }
.gallery-frame.is-zooming .gallery-img { cursor: zoom-out; }

/* Zoom lens — a square popover that follows the cursor inside the
   gallery and shows the image magnified at the cursor's position.
   `pointer-events: none` lets the mouse pass through to the image
   beneath so we keep tracking. Hidden by default; shown by JS on
   mousemove inside the image bounds. */
.gallery-lens {
  position: fixed;
  width: 480px;
  height: 480px;
  border-radius: var(--radius-m);
  border: 2px solid var(--text-base);
  box-shadow: 0 12px 32px rgba(8, 52, 0, 0.35);
  pointer-events: none;
  z-index: 200;
  display: none;
  background-repeat: no-repeat;
  background-color: var(--bg-elevated);
  overflow: hidden;
}
.gallery-nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--text-base);
  border: 0;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.gallery-nav svg { width: 24px; height: 24px; }
.gallery-nav:hover { background: var(--accent-soft); }
.gallery-nav:focus-visible {
  outline: 2px solid var(--text-base);
  outline-offset: -4px;
}

/* Thumbnail strip — scrolls horizontally if it overflows. */
.gallery-strip {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--accent-soft);
  border-top: 1px solid rgba(95, 107, 84, 0.5);
  overflow-x: auto;
  align-items: stretch;
  scrollbar-width: thin;                                  /* Firefox */
  scrollbar-color: var(--text-subtle) transparent;
}
/* Custom thumbnail-band scrollbar — design-system colours (forest thumb on the
   accent-soft strip), pill shape, inset so it reads as part of the band. */
.gallery-strip::-webkit-scrollbar { height: 8px; }
.gallery-strip::-webkit-scrollbar-track { background: transparent; }
.gallery-strip::-webkit-scrollbar-thumb {
  background: var(--text-subtle);
  border-radius: var(--radius-pill);
  border: 2px solid var(--accent-soft);
}
.gallery-strip::-webkit-scrollbar-thumb:hover { background: var(--text-base); }
.gallery-thumb {
  position: relative; /* contains the .gallery-thumb-video icon overlay */
  flex: 0 0 auto;
  width: 110px;
  align-self: stretch;
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 4px;
  padding: 4px;
  background: var(--bg-elevated);
  border: 2px solid transparent;
  border-radius: var(--radius-s);
  cursor: pointer;
  overflow: hidden;
  min-height: 0;
  transition: border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.gallery-thumb img {
  width: 100%;
  height: 100%;
  min-height: 0;
  object-fit: cover;
  object-position: top;
  display: block;
  border-radius: 3px;
}
.gallery-thumb-cap {
  font-family: var(--font-body);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-muted);
  line-height: 1.2;
  padding: 2px 4px;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Play-icon overlay marking a video slide. Forest disc + lime triangle —
   uses the same colour and stroke language as the rest of the site's
   icons (close, arrows). Sits centred on the thumbnail. */
.gallery-thumb-video {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 32px; height: 32px;
  z-index: 1;
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(8, 52, 0, 0.35));
}
.gallery-thumb-video circle { fill: var(--text-base); }
.gallery-thumb-video polygon { fill: var(--accent-lime); }
.gallery-thumb:hover { border-color: var(--text-base); }
.gallery-thumb.is-active {
  border-color: var(--text-base);
  background: var(--text-base);
}
.gallery-thumb.is-active .gallery-thumb-cap { color: var(--accent-lime); }
.gallery-thumb:focus-visible {
  outline: 2px solid var(--text-base);
  outline-offset: 2px;
}

@media (max-width: 720px) {
  .gallery { grid-template-rows: 48px 1fr 84px; }
  .gallery-stage { grid-template-columns: 44px 1fr 44px; }
  .gallery-nav svg { width: 18px; height: 18px; }
  .gallery-thumb { width: 100px; }
}

/* ----- Future scaling tiles (outlined "coming next" tiles) ----- */
/* ----- Device showcase — the shipped design across screens (bottom-aligned,
   each image at its native ratio, common height). Clickable to the gallery. ----- */
.device-showcase {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: var(--space-7);
  margin: var(--space-7) 0 var(--space-8);
}
.device-shot {
  display: block;
  padding: 0;
  margin: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: center;
}
/* Frame look now from `.case-frame` (added to .device-frame). Reset width so
   each frame hugs its height-driven image (.case-frame defaults to width:100%);
   hover lift comes from .case-frame:hover. */
.device-shot .device-frame { width: auto; }
.device-shot img {
  display: block;
  height: clamp(200px, 24vw, 300px);   /* all three the same height */
  object-fit: cover;                    /* crop the image to fill the per-device width */
  object-position: top;
}
/* Same height, but width set per device so desktop reads widest → tablet → mobile.
   The image is cropped (object-fit: cover) to fill each box. */
.device-shot:nth-child(1) img { width: clamp(300px, 36vw, 460px); }   /* desktop — widest */
.device-shot:nth-child(2) img { width: clamp(210px, 25vw, 320px); }   /* tablet */
.device-shot:nth-child(3) img { width: clamp(118px, 14vw, 172px); }   /* mobile — narrow phone */
.device-shot:focus-visible { outline: 2px solid var(--text-base); outline-offset: 4px; }
/* (device labels moved inside the frame as `.case-frame-cap` 2026-06-06 — the
   old below-the-frame `.device-cap` was the only caption-outside pattern.) */

.future-tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
  margin-top: var(--space-7);
}
.future-tile {
  border: 2px dashed var(--text-base);
  border-radius: var(--radius-l);
  padding: var(--space-5);
  background: transparent;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.future-tile .ft-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-small);
  letter-spacing: 0.08em;
  color: var(--text-muted);
}
.future-tile .ft-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-body-lg);
  letter-spacing: -0.01em;
  color: var(--text-base);
}
.future-tile .ft-body {
  font-size: var(--fs-small);
  color: var(--text-muted);
  line-height: 1.5;
}
@media (max-width: 720px) {
  .future-tiles { grid-template-columns: 1fr; }
}

/* .impact-band — removed 2026-06-01 with section 12. Without metrics
   the closing section was abstract summary that repeated sections 08+09.
   If a future case study earns a closing impact moment, restore this
   block: forest band + lime-accent headline + two-button action row. */

/* ----- Beyond Order History — merged section (was 10 + 11)
   Picked 2026-06-01 from beyond-explorations Variant C: forest band for
   "Next" — bookends section 08's forest final-outcome moment.
   Two subsections inside one .case-section: "Now" (cream, the pattern
   carried) and "Next" (forest band, room to grow). The subsection head
   is a small chip + small h3 — clearly secondary to the section's main h2,
   no divider underline. ----- */
.beyond-block + .beyond-block { margin-top: var(--space-10); }
/* Subsection head — chip stacks ABOVE the h3 (matches the page's eyebrow-
   above-headline rhythm used in every other section). Was inline baseline-
   aligned, which fought the rest of the page's vocabulary. */
.beyond-block-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.beyond-tag {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  background: var(--text-base);
  color: var(--accent-lime);
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  flex: 0 0 auto;
}
/* Subsection h3 — distinctly smaller than the section h2 (36px) so the
   hierarchy reads: section title → tag + small subsection title → content.
   Was 22-30px (too close to h2 size). Now 19-20px static-ish. */
.beyond-h {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-body-lg);
  line-height: 1.3;
  letter-spacing: -0.005em;
  color: var(--text-base);
  margin: 0;
  max-width: 36ch;
}

/* "Next" subsection on a forest band — bookends section 08. Lives outside
   the section's main .shell so the band can stretch full-bleed. */
.beyond-next-band {
  background: var(--text-base);
  color: var(--bg-elevated);
  padding: var(--space-9) 0;
  margin-top: var(--space-9);
}
.beyond-next-band .beyond-tag {
  background: var(--accent-lime);
  color: var(--text-base);
}
.beyond-next-band .beyond-h { color: var(--bg-elevated); }
.beyond-next-band .case-prose,
.beyond-next-band .case-prose p { color: var(--accent-soft); }
/* Future tiles on forest: outlined accent-soft @ 50% (matches the dashed
   chip vocabulary on the about-tools-blend band). */
.beyond-next-band .future-tile {
  border-color: rgba(212, 245, 197, 0.40);
  background: transparent;
}
.beyond-next-band .future-tile .ft-num { color: var(--accent-lime); }
.beyond-next-band .future-tile .ft-title { color: var(--bg-elevated); }
.beyond-next-band .future-tile .ft-body { color: var(--accent-soft); }

/* ----- Case closer — invitation to keep browsing
   Sits between section 09's forest "Next" band and the site footer.
   Cream surface gives the page a soft landing after the saturated band.
   Centered eyebrow + display headline (with rotated lime-soft accent —
   echoes the hero) + primary button with arrow.
   ----- */
.case-closer {
  background: var(--bg-base);
  /* 88px — slightly tighter than space-9 (96px) so the closer feels like a
     softer landing than a full section. Still on the 4px grid. */
  padding: 88px 0;
  text-align: center;
}
.case-closer .case-closer-eyebrow {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-4);
}
.case-closer-h {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(36px, 5.5vw, 60px);
  line-height: 1.1;
  letter-spacing: var(--tracking-tight);
  color: var(--text-base);
  margin: 0 auto var(--space-7);
  max-width: 18ch;
}
.case-closer-h .accent {
  display: inline-block;
  background: var(--accent-soft);
  color: var(--text-base);
  padding: 0 0.16em;
  margin: 0 -0.05em;
  border-radius: 6px;
  transform: rotate(-1deg);
  line-height: 1;
}
.case-closer .closer-arrow {
  width: 16px;
  height: 16px;
  transition: transform var(--dur-fast) var(--ease-out);
}
.case-closer .btn-primary:hover .closer-arrow {
  transform: translateX(3px);
}

/* ----- Inline section eyebrow (small reusable header for case sections) ----- */
.case-eyebrow {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-3);
}
.case-section.is-forest-band .case-eyebrow { color: var(--accent-lime); }
.case-section.is-lime-band .case-eyebrow { color: var(--text-base); }

/* ============================================================
   ENTRANCE ANIMATIONS (2026-06-01)
   Cards / stats / numerals fade up and stagger when their parent
   .reveal-on-scroll section enters the viewport. Matches the
   existing language (opacity + translateY + ease-out + staggered
   delays — same as .manifest-item underlines).
   base.css already disables transitions under prefers-reduced-motion,
   so these all snap to final state for users who opt out of motion.
   ============================================================ */

/* Durations bumped 2026-06-02 — earlier animations were finishing before
   users had scrolled the elements into view. Longer durations + larger
   staggers keep the motion visible while the user is looking at it. */

/* ----- Hero stats band (section 02) — numerals fade up */
.case-stats-band.reveal-on-scroll .case-stat {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-reveal-lg) var(--ease-out), transform var(--dur-reveal-lg) var(--ease-out);
}
.case-stats-band.reveal-on-scroll.is-visible .case-stat { opacity: 1; transform: none; }
.case-stats-band.reveal-on-scroll.is-visible .case-stat:nth-child(1) { transition-delay: 0.15s; }
.case-stats-band.reveal-on-scroll.is-visible .case-stat:nth-child(2) { transition-delay: 0.45s; }
.case-stats-band.reveal-on-scroll.is-visible .case-stat:nth-child(3) { transition-delay: 0.75s; }

/* ----- Research cards (section 02) — staggered fade up (60/40 grid) */
.reveal-on-scroll .research-card {
  opacity: 0;
  transform: translateY(24px);
  /* entrance (opacity/transform, slow) + hover (translate/box-shadow, med) —
     both must be listed or the .case-frame hover snaps (choppy). */
  transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out),
              translate var(--dur-med) var(--ease-out), box-shadow var(--dur-med) var(--ease-out);
}
.reveal-on-scroll.is-visible .research-card { opacity: 1; transform: none; }
/* Stagger delays apply ONLY to the entrance (opacity, transform) — the 3rd/4th
   values keep hover (translate, box-shadow) at 0s so the lift isn't delayed.
   Order matches the transition-property list above: opacity, transform, translate, box-shadow. */
.reveal-on-scroll.is-visible .research-feature-col .research-card        { transition-delay: 0.15s, 0.15s, 0s, 0s; }
.reveal-on-scroll.is-visible .research-stack .research-card:nth-child(1) { transition-delay: 0.4s, 0.4s, 0s, 0s; }
.reveal-on-scroll.is-visible .research-stack .research-card:nth-child(2) { transition-delay: 0.65s, 0.65s, 0s, 0s; }

/* ----- Voice cards (section 07) — staggered fade up */
.reveal-on-scroll .voice {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out);
}
.reveal-on-scroll.is-visible .voice { opacity: 1; transform: none; }
.reveal-on-scroll.is-visible .voices .voice:nth-child(1) { transition-delay: 0.15s; }
.reveal-on-scroll.is-visible .voices .voice:nth-child(2) { transition-delay: 0.4s; }
.reveal-on-scroll.is-visible .voices .voice:nth-child(3) { transition-delay: 0.65s; }

/* ----- Future tiles (section 09 / Next) — staggered fade up */
.reveal-on-scroll .future-tile {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out);
}
.reveal-on-scroll.is-visible .future-tile { opacity: 1; transform: none; }
.reveal-on-scroll.is-visible .future-tiles .future-tile:nth-child(1) { transition-delay: 0.15s; }
.reveal-on-scroll.is-visible .future-tiles .future-tile:nth-child(2) { transition-delay: 0.4s; }
.reveal-on-scroll.is-visible .future-tiles .future-tile:nth-child(3) { transition-delay: 0.65s; }

/* ----- Persona SVG numerals (section 03) — stroke-dashoffset draw
   Slower stroke draw + bigger stagger so each persona's numeral
   visibly draws in while the user is reading the section. */
.reveal-on-scroll .persona-spread:not(.is-lime) .about-numeral-text {
  stroke-dasharray: 1800;
  stroke-dashoffset: 1800;
  opacity: 0;
  transition: stroke-dashoffset var(--dur-draw) var(--ease-out),
              opacity var(--dur-reveal) var(--ease-out);
}
.reveal-on-scroll.is-visible .persona-spread:not(.is-lime) .about-numeral-text {
  stroke-dashoffset: 0;
  opacity: 1;
}
.reveal-on-scroll .persona-spread.is-lime .about-numeral {
  opacity: 0;
  transition: opacity var(--dur-reveal) var(--ease-out);
}
.reveal-on-scroll.is-visible .persona-spread.is-lime .about-numeral { opacity: 1; }
/* Staggered per persona (S/M/P) — bigger gaps so each draws sequentially */
.reveal-on-scroll.is-visible .persona-spread:nth-of-type(1) .about-numeral-text { transition-delay: 0.3s; }
.reveal-on-scroll.is-visible .persona-spread:nth-of-type(2) .about-numeral      { transition-delay: 1.1s; }
.reveal-on-scroll.is-visible .persona-spread:nth-of-type(3) .about-numeral-text { transition-delay: 1.8s; }

/* ============================================================
   CUSTOM CURSORS (2026-06-01)
   Brand-matched cursors across four states:
   - default: forest arrow with a lime tip accent (hotspot at the tip)
   - pointer: forest pointing-finger hand for clickable items
   - zoom-in: magnifier with lime "+" inside (gallery image)
   - zoom-out: magnifier with lime "−" (gallery image, after activation)
   Inline SVG data URLs — modern browsers support directly. Native
   cursors (default / pointer / zoom-in / zoom-out) are the fallback.
   ============================================================ */

/* Default arrow — cream fill (#E0E5D2) + dark forest outline (#041A00).
   Resized 2026-06-03 from 28×28 to 20×20 so the cursor sits closer to
   native baseline (~16–20px) and doesn't crowd small UI. stroke-width
   reduced to 1.5 to keep the line weight visually consistent at the
   smaller size. Hotspot stays at the arrow tip (1, 1). */
body {
  cursor: url("data:image/svg+xml;utf8,<svg width='20' height='20' viewBox='0 0 28 28' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M26.5131 20.688L16.3568 12.4302L20.4027 8.38427C20.5955 8.19274 20.7348 7.95404 20.8067 7.69195C20.8786 7.42985 20.8806 7.1535 20.8125 6.8904C20.7443 6.62827 20.609 6.38847 20.4197 6.1947C20.2305 6.00093 19.994 5.8599 19.7336 5.78555L2.98454 1.06014C2.7176 0.98369 2.43506 0.980063 2.16624 1.04963C1.89743 1.1192 1.65212 1.25943 1.45578 1.45578C1.25943 1.65212 1.1192 1.89743 1.04963 2.16624C0.980063 2.43506 0.98369 2.7176 1.06014 2.98454L5.78555 19.7336C5.85912 19.995 5.9998 20.2326 6.19362 20.4227C6.38744 20.6129 6.62766 20.7491 6.8904 20.8177C7.02116 20.8499 7.15514 20.8673 7.2898 20.8695C7.70132 20.8664 8.09485 20.7004 8.38427 20.4079L12.4302 16.362L20.7295 26.5442C20.8619 26.6874 21.0223 26.8018 21.2007 26.8803C21.3792 26.9588 21.5719 26.9998 21.7669 27.0007C21.9594 27.0023 22.1503 26.9656 22.3285 26.8925C22.5066 26.8195 22.6684 26.7117 22.8043 26.5753L26.5753 22.8043C26.7147 22.6644 26.8241 22.4975 26.897 22.314C26.97 22.1304 27.0048 21.934 26.9995 21.7365C26.9941 21.5391 26.9487 21.3448 26.866 21.1654C26.7833 20.9861 26.665 20.8254 26.5183 20.6932L26.5131 20.688Z' fill='%23E0E5D2' stroke='%23041A00' stroke-width='1.5'/></svg>") 1 1, default;
}

/* Pointer for anything that's actually clickable */
a,
button,
[role="button"],
[type="button"],
[type="submit"],
summary,
.btn,
.card-block,
.anon-cue-btn,
.gallery-thumb,
.gallery-nav,
.gallery-close,
.case-hero-image,
.case-frame,
.device-shot,
.research-card,
.comparison-frame,
.spec-sheet-link,
.streamline-pair .figure-tilt,
.final-legend-item {
  /* Pointer hand — system-style pointing hand (replaced 2026-06-03 from the
     custom illustrated hand; that read too consumer-app for senior B2B audience).
     Cream fill (#E0E5D2) + dark forest outline (#041A00) match the default arrow's
     colour pair so the cursor system speaks one language. Hotspot at the
     fingertip (8, 2). */
  cursor: url("data:image/svg+xml;utf8,<svg width='22' height='26' viewBox='0 0 24 28' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M9 13V4.5C9 3.67157 9.67157 3 10.5 3C11.3284 3 12 3.67157 12 4.5V12.5M12 12.5V2.5C12 1.67157 12.6716 1 13.5 1C14.3284 1 15 1.67157 15 2.5V12.5M15 12.5V3.5C15 2.67157 15.6716 2 16.5 2C17.3284 2 18 2.67157 18 3.5V14.5M18 13V6.5C18 5.67157 18.6716 5 19.5 5C20.3284 5 21 5.67157 21 6.5V18C21 22.4183 17.4183 26 13 26H11.5C9.50893 26 7.59935 25.2098 6.19209 23.8025L2.46967 20.0801C2.17678 19.7872 2.17678 19.3123 2.46967 19.0194C3.78319 17.7059 5.91293 17.7059 7.22645 19.0194L9 20.793V11C9 10.1716 8.32843 9.5 7.5 9.5C6.67157 9.5 6 10.1716 6 11V15' fill='%23E0E5D2' stroke='%23041A00' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>") 8 2, pointer;
}

/* Children of a clickable card inherit the card's hand — otherwise the headings
   and paragraphs inside the card link pick up the text I-beam from the rule below. */
.card-block * { cursor: inherit; }

/* Text cursor — forest I-beam (matches the arrow's forest stroke language).
   Added 2026-06-03 to restore the "this text is selectable / editable"
   affordance the custom default arrow was hiding. 12×18 displayed size
   (close to native I-beam scale). Stroke-width 1.5 matches the arrow.
   Hotspot at the vertical centre of the beam (6, 9) so caret placement
   tracks naturally when clicking into text. */
p, h1, h2, h3, h4, h5, h6, li, blockquote, dt, dd, figcaption, label, address,
input[type='text'], input[type='email'], input[type='search'],
input[type='url'], input[type='tel'], input[type='number'],
input:not([type]), textarea {
  cursor: url("data:image/svg+xml;utf8,<svg width='12' height='18' viewBox='0 0 12 18' fill='none' xmlns='http://www.w3.org/2000/svg'><line x1='6' y1='2' x2='6' y2='16' stroke='%23083400' stroke-width='1.5' stroke-linecap='round'/><line x1='3' y1='2' x2='9' y2='2' stroke='%23083400' stroke-width='1.5' stroke-linecap='round'/><line x1='3' y1='16' x2='9' y2='16' stroke='%23083400' stroke-width='1.5' stroke-linecap='round'/></svg>") 6 9, text;
}

/* Cream-stroke I-beam — same geometry, cream stroke for forest-band surfaces.
   Forest #083400 stroke is invisible against the forest backdrop, so swap to
   cream #FBFCF6 wherever a forest band wraps the text. */
.case-section.is-forest-band p,
.case-section.is-forest-band h1, .case-section.is-forest-band h2,
.case-section.is-forest-band h3, .case-section.is-forest-band h4,
.case-section.is-forest-band li, .case-section.is-forest-band blockquote,
.case-section.is-forest-band figcaption,
.final-outcome p, .final-outcome h1, .final-outcome h2,
.final-outcome h3, .final-outcome h4, .final-outcome li,
.final-outcome blockquote, .final-outcome figcaption,
.beyond-next-band p, .beyond-next-band h1, .beyond-next-band h2,
.beyond-next-band h3, .beyond-next-band h4, .beyond-next-band li,
.beyond-next-band blockquote, .beyond-next-band figcaption {
  cursor: url("data:image/svg+xml;utf8,<svg width='12' height='18' viewBox='0 0 12 18' fill='none' xmlns='http://www.w3.org/2000/svg'><line x1='6' y1='2' x2='6' y2='16' stroke='%23FBFCF6' stroke-width='1.5' stroke-linecap='round'/><line x1='3' y1='2' x2='9' y2='2' stroke='%23FBFCF6' stroke-width='1.5' stroke-linecap='round'/><line x1='3' y1='16' x2='9' y2='16' stroke='%23FBFCF6' stroke-width='1.5' stroke-linecap='round'/></svg>") 6 9, text;
}

/* Gallery image cursors override the pointer on the image area only */
.gallery-frame:not(.is-video) .gallery-img {
  cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'><circle cx='13' cy='13' r='9' fill='%23FBFCF6' stroke='%23083400' stroke-width='2.5'/><line x1='19.5' y1='19.5' x2='27' y2='27' stroke='%23083400' stroke-width='3' stroke-linecap='round'/><line x1='9' y1='13' x2='17' y2='13' stroke='%2387EA5C' stroke-width='2.5' stroke-linecap='round'/><line x1='13' y1='9' x2='13' y2='17' stroke='%2387EA5C' stroke-width='2.5' stroke-linecap='round'/></svg>") 13 13, zoom-in;
}
.gallery-frame.is-zooming .gallery-img {
  cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'><circle cx='13' cy='13' r='9' fill='%23FBFCF6' stroke='%23083400' stroke-width='2.5'/><line x1='19.5' y1='19.5' x2='27' y2='27' stroke='%23083400' stroke-width='3' stroke-linecap='round'/><line x1='9' y1='13' x2='17' y2='13' stroke='%2387EA5C' stroke-width='2.5' stroke-linecap='round'/></svg>") 13 13, zoom-out;
}

/* Disabled / non-interactive overrides — restore the default arrow */
:disabled,
[aria-disabled="true"] {
  cursor: not-allowed;
}

/* ============================================================
   CASE STUDY — HGO (Handling Guide Online)
   Bespoke modules, additive. Tokens only. Built 2026-06-05.
   Variety strategy (per user): shared chrome + reused modules,
   plus 5 HGO-only modules so the scroll differs from the other
   two case studies. Namespaced `.hgo-*` (mirrors `.about-*`).
   ============================================================ */

/* (Stat units/symbols + the equal-height stat-cell stretch were promoted to
   the shared stats-band rules — see `.case-stats-grid`, `.stat-sym`,
   `.stat-unit`, `.stat-arrow` — on 2026-06-06 so all three case studies match.) */

/* ----- "The old HGO" before-grid (section 01) — 2×2 evidence cluster
   that sits in the right column of .challenge-grid. Makes the density
   problem visible instead of only describing it. ----- */
.hgo-before-label {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--accent-lime);
  background: var(--text-base);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-pill);
  transform: rotate(-1deg);
  margin-bottom: var(--space-7);
}
/* (The 2×2 before-grid was replaced by the overlapping `.streamline-pair`
   (2 screens) on 2026-06-06 — concept B. The pill `.hgo-before-label` sits
   above the pair; the pair reuses the shared streamline CSS.) */
.hgo-before .streamline-pair { min-height: 320px; } /* shorter than OH's 480 — HGO's text column is brief */
.hgo-before .streamline-pair .figure-tilt { width: 62%; } /* smaller screens → shorter pair (OH stays 70%) */

/* ----- Three-step process stepper (section 02) — HGO's signature.
   Connector line between numbered circles; masked by the circles. ----- */
.hgo-stepper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-7);
  margin: 0 0 var(--space-8);
  padding: 0;
  list-style: none;
}
.hgo-step {
  position: relative;
  padding-top: var(--space-7);
}
/* connector from this number's centre to the next number's centre.
   100% = the step's column width; + the grid gap = distance between
   adjacent number centres (both circles sit 28px from their column left). */
.hgo-step::after {
  content: "";
  position: absolute;
  top: calc(var(--space-7) + 28px);
  left: 28px;
  width: calc(100% + var(--space-7));
  height: 2px;
  background: var(--border-base);
  z-index: 0;
}
.hgo-step:last-child::after { display: none; }
.hgo-step-num {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  border: 2px solid var(--text-base);
  color: var(--text-base);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-body-lg);
  letter-spacing: -0.02em;
  margin-bottom: var(--space-4);
}
.hgo-step-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--text-base);
  /* Reserve 2 lines (2 × line-height 1.1) so single-line titles
     ("Configure & order") still push their body to the same baseline as
     the two-line title ("Review system suggestions"). Mirrors the stats-band
     stretch fix. Reset on mobile where the stepper is a full-width stack. */
  min-height: 2.2em;
  margin-bottom: var(--space-3);
}
.hgo-step-body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  color: var(--text-muted);
  max-width: 32ch;
}

/* What-HGO-does figure row: diagram + system-type chips. */
.hgo-what-row {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--space-8);
  align-items: center;
}
/* (the diagram now carries the standard +1° standalone-figure tilt — the old
   rotate(0) override was removed 2026-06-06 for cross-case tilt consistency.) */
.hgo-systypes-label {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-bottom: var(--space-4);
}
.hgo-systypes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  list-style: none;
  padding: 0;
  margin: 0;
}
.hgo-systypes li {
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-base);
  border: 2px solid var(--text-base);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-4);
}

/* ----- Integration module (section 06) — sidebar/standalone story +
   the 5 structural requirements. Most HGO-specific section. ----- */
.hgo-integration {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: var(--space-8);
  align-items: center;
}
/* (integration figure migrated to `.case-frame` + `.case-frame-cap`
   on 2026-06-06 — see card-system.md.) */
.hgo-req-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 2px solid var(--text-base);
}
.hgo-req {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--border-base);
}
.hgo-req-num {
  flex: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--text-base);
  background: var(--accent-soft);
  border-radius: var(--radius-s);
  padding: var(--space-1) var(--space-2);
}
.hgo-req-text {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  color: var(--text-muted);
}
.hgo-req-text b { color: var(--text-base); font-weight: 700; }
.hgo-scope-note {
  margin-top: var(--space-7);
  padding-left: var(--space-5);
  border-left: 3px solid var(--accent-lime);
  font-family: var(--font-body);
  font-style: italic;
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  color: var(--text-muted);
  max-width: 60ch;
}

/* (HGO's manifest section was merged into the annotated "Final design" section
   2026-06-06 — the 8th-item stagger override is no longer needed. The `.manifest`
   component stays available for other case studies.) */

/* ----- Loading sequence (section 08) — cross-fading frames + captions. ----- */
.hgo-loading {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: var(--space-8);
  align-items: center;
}
/* (loading stage migrated to `.case-frame` + `.case-frame-media`
   (--frame-ratio: 1513/680) on 2026-06-06. The cross-fade frames keep
   `.hgo-loading-frame` so the page-local script + reduced-motion path work.) */
.hgo-loading-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}
.hgo-loading-frame.is-active { opacity: 1; }
.hgo-loading-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 2px solid var(--text-base);
}
.hgo-loading-steps li {
  display: flex;
  gap: var(--space-3);
  align-items: baseline;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--border-base);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  color: var(--text-muted);
}
.hgo-loading-num {
  flex: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-small);
  color: var(--text-base);
  background: var(--accent-soft);
  border-radius: var(--radius-s);
  padding: var(--space-1) var(--space-2);
}

/* (Motion-cycle concept §09 rebuilt 2026-06-06 as layout B — a narrati