/* =========================================================================
   APPROACH B — paper-2 card surfaces on a page-bg reading surface.

   Architecture:
     • Page bg = var(--ground) (the reading surface — body content sits
       directly on it)
     • Chrome surfaces = var(--paper-2) (the hero card + TOC card)
     • Same surface vocabulary as the homepage manifesto, applied at
       component scale: paper-2 = "stuff that frames or navigates,"
       ground = "stuff that's read."

   Layout:
     • Single-column page container, 60px horizontal padding matching
       homepage --pad-x token
     • Hero CARD spans the full content width, paper-2 + rounded corners
     • Below: 2-column layout — TOC card on left (paper-2, sticky),
       body content on right (page bg, 820px max-width)

   Cohesion-level changes (fonts, callouts, eyebrows, pills) live in
   styles-v2-test.css and propagate from there.
========================================================================= */

/* -------------------------------------------------------------------------
   Nav.top — REMOVED on Approach B. Page-level back link in hero card
   + sticky TOC card cover all navigation needs.
------------------------------------------------------------------------- */
body:has(.v2-layout-b) nav.top{
  display: none !important;
}

/* -------------------------------------------------------------------------
   Page container — single column, page padding via --pad-x to match
   the homepage's responsive padding behavior. Forced to full viewport
   width to override base .v2-main's max-width:1280px + margin auto.
------------------------------------------------------------------------- */
.v2-main.v2-layout-b{
  /* Reset base .v2-main constraints. */
  max-width: none;
  width: 100%;
  margin: 0;
  padding: 32px var(--pad-x, 60px) 96px;
  box-sizing: border-box;
  /* Stack hero + body layout vertically. */
  display: flex;
  flex-direction: column;
  gap: 96px;
  /* Override the homepage main's rounded bottom + shadow. The case
     study's bottom edge sits flat against the footer (which keeps its
     rounded top + shadow) so the footer reads as "rising up" out from
     a clean horizontal joint. */
  border-radius: 0;
  box-shadow: none;
}

/* -------------------------------------------------------------------------
   HERO — no card chrome (no fill, no border, no radius). The hero sits
   directly on the page bg, so its content aligns with the body content
   horizontally (24px inset matches the body-layout's padding). Typography
   and whitespace carry the editorial weight; the card surface is gone.
------------------------------------------------------------------------- */
.v2-layout-b .v2-hero.v2-hero-card{
  background: transparent;
  border-radius: 0;
  padding: 0 24px;
  margin: 0;
  border: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Reset child margins so explicit margins drive vertical rhythm. */
.v2-layout-b .v2-hero-card > *{
  margin: 0;
}

/* Back link — editorial chrome at PAGE level, above the hero card.
   Horizontally inset 24px to align with the body content (same inset).
   No margin-bottom — vertical spacing comes from v2-main's gap (56px)
   so the back→hero gap matches the hero→body gap. */
.v2-layout-b > .v2-back-row{
  margin: 0;
  padding: 0 24px;
}
.v2-layout-b .v2-back-link{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0;
  color: var(--mid);
  text-decoration: none;
  transition: color .25s var(--ease);
}
.v2-layout-b .v2-back-link:hover{
  color: var(--ink);
}

/* Title — large Antonio, dominant. Spans full hero width (above the
   2-col grid). Generous bottom margin gives the title its own moment
   before the grid begins. */
.v2-layout-b .v2-hero-card .v2-hero-label{
  font-size: clamp(48px, 5.6vw, 84px);
  line-height: 0.96;
  letter-spacing: -0.014em;
  margin: 0 0 56px 0;
  max-width: 18ch;
  text-wrap: balance;
}

/* -------------------------------------------------------------------------
   Hero grid — 2-column layout below the title. LEFT (1fr): description
   statement + problem statement paragraph. RIGHT (260px): metadata
   column with Role / Tools / Timeline / Disciplines. align-items:start
   so the description top aligns with the first meta item's label.
------------------------------------------------------------------------- */
.v2-layout-b .v2-hero-grid{
  display: grid;
  /* 3fr / 2fr ratio — description column gets ~58% of available width,
     meta column ~38% (after the 96px gap). Echoes the inspo's
     proportions and gives meta room to breathe (multi-line values like
     "Design Systems, Platform Modernization, Cross-Functional Design"
     don't wrap as tightly). No max-width cap — the grid spans the
     full hero width. */
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: 96px;
  align-items: start;
}
.v2-layout-b .v2-hero-main{
  display: flex;
  flex-direction: column;
  gap: 40px;
  min-width: 0;
}

/* Description — Antonio LOWERCASE statement, weight 600 (more bold
   than body/meta but less bold than the uppercase title which is 700).
   No max-width — fills the left column. text-wrap: balance distributes
   the lines evenly across however many lines the column needs. */
.v2-layout-b .v2-hero-card .v2-hero-desc{
  font-family: 'Antonio', sans-serif;
  font-weight: 600;
  font-size: clamp(24px, 2.4vw, 36px);
  line-height: 1.15;
  letter-spacing: -0.005em;
  text-transform: none;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}

/* Overview / problem statement — body type, sized to MATCH the case
   study body paragraphs exactly (15px / 1.72 in .v2-section-body p)
   so the hero reads as the same voice as the body, just positioned
   at the top. Multiple paragraphs supported (JS maps arrays to
   sibling <p> tags). */
.v2-layout-b .v2-hero-overview{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 400;
  font-size: 15px;
  line-height: 1.72;
  letter-spacing: -0.002em;
  color: var(--ink);
  max-width: 60ch;
}
.v2-layout-b .v2-hero-overview p{
  margin: 0 0 16px 0;
}
.v2-layout-b .v2-hero-overview p:last-child{
  margin-bottom: 0;
}

/* -------------------------------------------------------------------------
   Hero meta column — vertical stack (Role / Tools / Timeline /
   Disciplines), aligned to the right of the 2-col grid. Replaces the
   previous horizontal 3-col bottom row. Each item is label + value
   stacked, with generous spacing between items.
------------------------------------------------------------------------- */
.v2-layout-b .v2-hero-card .v2-hero-meta{
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 0;
  margin: 0;
  border: 0;
}
.v2-layout-b .v2-hero-card .v2-hero-meta-item{
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.v2-layout-b .v2-hero-card .v2-hero-meta-label{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 600;
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  /* Demoted from --accent (pink) to --mid (quiet gray). Lets the
     title and values carry the visible weight; labels recede into
     their proper "structural marker" role. Scoped to layout-b only —
     A keeps the original pink-eyebrow treatment. */
  color: var(--mid);
}
.v2-layout-b .v2-hero-card .v2-hero-meta-value{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 500;
  font-size: 14px;
  line-height: 1.45;
  letter-spacing: -0.002em;
  color: var(--ink);
  text-wrap: balance;
}

/* -------------------------------------------------------------------------
   Pills row — KICKER above the title (Nightingale pattern). Sits as
   "this is what kind of project" context before the title moment. No
   hairline; the spacing carries the separation. Plain text matching
   homepage row-pills (PJS 600, 11px tracked uppercase, --ink).
------------------------------------------------------------------------- */
.v2-layout-b .v2-hero-pills-wrap{
  margin: 0 0 24px 0;
}
.v2-layout-b .v2-hero-card .v2-hero-pills{
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
  margin: 0;
  align-items: center;
}

/* -------------------------------------------------------------------------
   BODY LAYOUT — 2-column grid below the hero card.
     Left: sticky TOC (uncontained)
     Right: body content (page bg, max-width 820px)

   Horizontal padding matches the hero card's internal padding (48px) so
   the body content shares the SAME horizontal axis as the hero's title /
   description — TOC eyebrow lines up with hero title vertically.
------------------------------------------------------------------------- */
.v2-layout-b .v2-body-layout{
  display: grid;
  /* Rail at 340px — the minimum width that fits horizontal Previous/Next
     at full type size while avoiding excess whitespace inside the rail.
     Content stays flexible at 1fr (capped by v2-content's max-width). */
  grid-template-columns: 340px minmax(0, 1fr);
  gap: 80px;
  align-items: start;
  padding: 0 24px;
}

/* -------------------------------------------------------------------------
   TOC RAIL — uncontained. Typography sits directly on the page bg,
   no card surface (the hero card is the only paper-2 element). Still
   sticky-pinned to the viewport top so it follows the reader.
   Original card styling (for revert):
     background: var(--paper-2); border-radius: 16px; padding: 32px;
------------------------------------------------------------------------- */
.v2-layout-b .v2-rail-card{
  background: transparent;
  border-radius: 0;
  position: sticky;
  top: 0;
  /* Full viewport height — rail extends from very top to very bottom
     of viewport (no 32px buffer above/below). Creates a true "front
     of stage" full-screen sidebar. Internal padding on rail-card-inner
     gives the content breathing room from these new edges. */
  height: 100vh;
  max-height: 100vh;
  /* Subtle right-edge shadow gives the rail a depth cue without using
     a fill or a divider. Now runs the full viewport height since the
     rail extends top-to-bottom. */
  box-shadow: 12px 0 32px -16px rgba(0, 0, 0, 0.06);
}
:root[data-theme="dark"] .v2-layout-b .v2-rail-card{
  box-shadow: 12px 0 32px -16px rgba(255, 255, 255, 0.04);
}
.v2-layout-b .v2-rail-card-inner{
  display: flex;
  flex-direction: column;
  /* No flex gap — children control their own margin-bottom. */
  /* Symmetric 48px top + bottom padding. 32px right padding gives
     the prev/next buttons (now with border + bg fill) a more
     comfortable breathing margin from the rail's right edge / shadow.
     No left padding — content stays left-aligned to share the
     horizontal axis with the body content. */
  padding: 48px 32px 48px 0;
  height: 100%;
  box-sizing: border-box;
}
.v2-layout-b .v2-rail-section-label{
  display: block;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 600;
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: color-mix(in oklab, var(--mid) 65%, transparent);
  margin-bottom: 14px;
}

/* -------------------------------------------------------------------------
   Rail summary block — appears when the hero card scrolls out of view.
   Provides persistent case identity (title) + meta (Role/Tools/Timeline)
   while the reader is in the body. Toggled via .is-revealed (added by
   the IntersectionObserver in case-test-b.html).

   Animation technique: grid-template-rows: 0fr → 1fr on the outer
   wrapper + overflow:hidden on the inner. Animates to the EXACT
   content height (not a guessed max-height target), so the timing of
   the height change matches the opacity reveal exactly — smoother than
   the previous max-height:500px approach which overshot the actual
   content size and made the curve feel off-tempo with the extra meta.
------------------------------------------------------------------------- */
.v2-layout-b .v2-rail-summary{
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transform: translateY(-6px);
  margin-bottom: 0;
  transition: grid-template-rows .5s var(--ease),
              opacity .5s var(--ease),
              transform .5s var(--ease),
              margin-bottom .5s var(--ease);
  pointer-events: none;
}
.v2-layout-b .v2-rail-summary-inner{
  overflow: hidden;
  min-height: 0;
}
.v2-layout-b .v2-rail-summary.is-revealed{
  grid-template-rows: 1fr;
  opacity: 1;
  transform: translateY(0);
  margin-bottom: 32px;
  pointer-events: auto;
}

/* Title — Antonio uppercase, larger than the previous 16px so it
   carries weight in the rail. Echoes the hero title's family at a
   compressed scale: reads as "same title, smaller." text-wrap: balance
   distributes wrapping evenly across lines for multi-word titles
   (e.g. "M365 TEST HUB" wraps cleanly instead of orphaning a word). */
.v2-layout-b .v2-rail-title{
  display: block;
  font-family: 'Antonio', sans-serif;
  font-weight: 700;
  font-size: 20px;
  line-height: 1.15;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 16px 0;
  text-wrap: balance;
}

/* Rail description — compressed echo of the hero description.
   Antonio lowercase (matching hero), weight 500 (lighter than the
   hero's 600 since this is the smaller-scale echo). Tells the reader
   "what case is this?" while the case body is being read. */
.v2-layout-b .v2-rail-desc{
  font-family: 'Antonio', sans-serif;
  font-weight: 500;
  font-size: 17px;
  line-height: 1.25;
  letter-spacing: -0.003em;
  text-transform: none;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}

/* TOC base styling lives in styles-v2-test.css (the cohesion layer).
   B overrides the active indicator to use a single SLIDING element
   instead of per-link ::before pseudos, so the bar transitions smoothly
   between sections instead of jumping. The cohesion layer's per-link
   pseudo is hidden in B; A still uses it. */

/* Hide the cohesion layer's per-link pseudo indicator in B. */
.v2-layout-b .v2-toc-link.is-current::before,
.v2-layout-b .v2-toc-link[aria-current="true"]::before{
  display: none;
}

/* Sliding indicator — single element overlaid ON the TOC track
   (scrollbar-thumb pattern). Track sits at left:0 with width:4px;
   indicator sits at the same position so the pink "thumb" overlays
   the gray track at the current section. JS updates transform:
   translateY and (for first/last sections) height so the indicator
   touches the track's top/bottom edges respectively. CSS transition
   handles the smooth slide AND height-grow/shrink between states. */
.v2-layout-b .v2-toc-indicator{
  position: absolute;
  left: 0;
  top: 0;
  width: 4px;
  height: 18px;
  background: var(--accent);
  border-radius: 999px;
  opacity: 0;
  transform: translateY(0);
  transition: transform .35s var(--ease),
              opacity .25s var(--ease),
              height .35s var(--ease);
  pointer-events: none;
  will-change: transform, height;
  z-index: 1;
}

/* -------------------------------------------------------------------------
   Rail nav — Previous + Next case at the bottom of the rail. Pushed to
   the bottom by margin-top:auto (rail-card-inner is flex column). Each
   link shows a small accent eyebrow (← Previous / Next →) above the
   actual case title — so the reader knows what they're navigating to,
   not just that there's a button.
------------------------------------------------------------------------- */
.v2-layout-b .v2-rail-nav{
  margin-top: auto;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: stretch;
  gap: 12px;
}
/* Both nav links styled as REAL buttons now — defined boundary
   (rounded border), internal padding, defined hover state. Each link
   takes flex:1 so they share the available rail width equally and
   sit side-by-side as a paired set. */
.v2-layout-b .v2-rail-nav-link{
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid color-mix(in oklab, var(--mid) 30%, transparent);
  border-radius: 10px;
  background: transparent;
  text-decoration: none;
  color: var(--ink);
  text-align: left;
  align-items: flex-start;
  transition: border-color .2s var(--ease),
              background-color .2s var(--ease),
              transform .2s var(--ease);
}
.v2-layout-b .v2-rail-nav-link:hover{
  border-color: var(--ink);
  background: color-mix(in oklab, var(--ground) 92%, var(--ink) 8%);
}
.v2-layout-b .v2-rail-nav-prev:hover{
  transform: translateX(-2px);
}
.v2-layout-b .v2-rail-nav-next:hover{
  transform: translateX(2px);
}
.v2-layout-b .v2-rail-nav-eyebrow{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 600;
  font-size: 9px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent);
}
.v2-layout-b .v2-rail-nav-title{
  font-family: 'Antonio', sans-serif;
  font-weight: 700;
  font-size: 15px;
  line-height: 1.15;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--ink);
  text-wrap: balance;
}

/* -------------------------------------------------------------------------
   Body content column — text/sections on page bg. Constrained to 820px
   max-width for comfortable reading. min-width:0 prevents grid blowout.
------------------------------------------------------------------------- */
.v2-layout-b .v2-content-col{
  /* padding-top matches .v2-rail-card-inner's padding-top (48px) so:
     1) the first section's eyebrow vertically aligns with the rail's
        project title on initial load (both are 48px below v2-body-layout
        top), AND
     2) clicking the first TOC item (with scroll-margin-top: 48px on
        sections) puts v2-body-layout's top exactly at viewport top —
        which allows the rail's sticky to engage and fill the viewport. */
  padding: 48px 0 0 0;
  min-width: 0;
  max-width: 820px;
}
.v2-layout-b .v2-content-col > section,
.v2-layout-b .v2-content-col > article{
  margin-left: 0;
  margin-right: 0;
}

/* -------------------------------------------------------------------------
   Section scroll snap — section eyebrow lands HORIZONTALLY ALIGNED
   with the rail's project title. The rail-card-inner has padding-top:
   48px (so the title sits at y=48 from viewport top). Matching
   scroll-margin-top: 48px on sections means the eyebrow snaps to the
   same y position when a TOC link is clicked.

   v2-body-layout's top sits 48px above viewport top after the snap →
   rail sticky-engages, fills viewport, no hero peek above.
------------------------------------------------------------------------- */
.v2-layout-b .v2-section{
  scroll-margin-top: 48px;
}

/* -------------------------------------------------------------------------
   Gallery containerization (replaced breakout) — images now cut off at
   the container's edges instead of the rail / viewport edge. The
   track-wrap stretches edge-to-edge of the container via negative
   margins, while everything else (counter, caption, arrows) respects
   the container's 32px padding.

   Behavior:
   - Counter, caption, arrows inset 32px from container edges
   - Track stretches to container edges (negative -32px margins)
   - Track has internal padding-left so first slide aligns with the
     same 32px inset as the rest of the gallery content
   - padding-right: 50vw allows the LAST slide to snap to the focal
     position (otherwise it'd clamp at scroll-end with no snap point)
------------------------------------------------------------------------- */
/* Container-extension overrides removed — they were designed for the
   old "intrinsic-width slides on a horizontal strip" pattern, which
   needed negative margins to let wide images bleed past container
   padding and 50vw of trailing padding to give the last slide enough
   room to snap. With slides now at flex-basis 100% (one visible at a
   time, image inside fits via object-fit:contain), the track's
   natural content width = container's inner width, and there's no
   need to extend past it or pad the scroll-end. */

/* -------------------------------------------------------------------------
   Mobile fallback — collapse to single column at narrow viewports.
   TOC card moves above body content as a static (non-sticky) card.
------------------------------------------------------------------------- */
/* Phone-specific tightening (<=720px). The 900px block below covers
   tablet portrait + phone with intermediate values; this overrides
   the most padding-heavy rules for phone specifically — the TOC area
   was leaving too much vertical space between the rail and the
   first section on phones. */
@media (max-width: 720px){
  .v2-main.v2-layout-b{
    padding: 16px var(--pad-x, 20px) 48px;
    gap: 20px;
  }
  .v2-layout-b .v2-hero.v2-hero-card{
    padding: 24px 18px;
  }
  .v2-layout-b .v2-rail-card-inner{
    padding: 18px;
  }
  /* Smaller default gap between TOC and the first case-study section. */
  .v2-layout-b .v2-content-col{
    margin-top: 0;
  }
}

@media (max-width: 900px){
  .v2-main.v2-layout-b{
    padding: 24px var(--pad-x, 32px) 64px;
    gap: 32px;
  }
  .v2-layout-b .v2-hero.v2-hero-card{
    padding: 32px 24px;
    border-radius: 12px;
  }
  .v2-layout-b .v2-hero-card .v2-hero-meta{
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }
  .v2-layout-b .v2-body-layout{
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .v2-layout-b .v2-rail-card{
    position: relative;
    top: auto;
    max-height: none;
  }
  .v2-layout-b .v2-rail-card-inner{
    padding: 24px;
    min-height: 0;
  }
  .v2-layout-b .v2-content-col{
    max-width: none;
  }
}

/* =========================================================================
   Footer surface override (case study pages only).
   Homepage has the manifesto-back-layer scroll reveal providing
   contrast between page bg and the footer; case-study pages don't —
   the body content ends and the footer begins on the same --ground
   surface, so the footer disappears into the page.
   Routing the footer through --asset-bg makes the footer feel like
   a distinct surface in light mode (#EBEAE5 vs --ground #FBFAF6, ~16
   luminance delta) and reuses the system token already establishing
   the "framed content" vocabulary in case-study assets (galleries,
   figures, BAs). Dark mode resolves --asset-bg to the same value as
   --paper-2 (#322F2E), which is fine — dark mode doesn't have the
   "footer dissolves into page" problem in the first place.
   case-style.css only loads on case.html, so this scope is implicit
   — no need for body classes or sibling selectors.
========================================================================= */
footer{
  background:var(--asset-bg);
}

/* Footer top-edge shadow — kill in light mode (case study only).
   The homepage footer uses a top-edge shadow to give the footer
   "lift" out of the page. On case-study pages we now have a real
   surface change (--asset-bg fill above) doing that work; the
   shadow becomes redundant AND reads as a fuzzy halo above the
   rounded corners in light mode (dark-shadow-on-cream creates
   visible smudge). Dark mode shadow stays intact — warm-dark on
   warm-dark blends cleanly there. The fill + rounded corners alone
   carry the transition in light mode, producing a crisp seam. */
:root[data-theme="light"] footer{
  box-shadow: none;
}

/* =========================================================================
   Password gate (case studies only).
   The early script in case.html <head> adds .case-gated to <html> when
   no valid access token is in localStorage. In that state, the case
   study chrome is hidden and only the gate overlay shows. Once the
   visitor enters the correct password, the gate JS stores a 24-hour
   token and reloads — the case study renders normally afterward.
   This is intentionally light-touch security: it stops accidental
   discovery, casual sharing, and search-engine indexing. A determined
   viewer with DevTools can bypass it. That's the correct trade-off for
   a static portfolio gating client work behind a soft NDA.
========================================================================= */
/* Gated state — hide the case-study chrome but KEEP the cursor and
   theme toggle visible. The cursor is core to the site's personality
   and should always follow the visitor; the theme toggle lets them
   view the gate in their preferred mode. */
html.case-gated body > nav.top,
html.case-gated body > main,
html.case-gated body > footer{
  display: none !important;
}
/* Raise the cursor AND theme toggle above the gate (gate is z-index
   9999). Both render in fixed-corner positions and are core to the
   site's personality (cursor) and accessibility (theme switch);
   without this z-index bump they'd render behind the gate's opaque
   --ground background and disappear. Cursor is bumped HIGHER than
   the toggle (10001 vs 10000) so it draws on top when hovering the
   toggle — without the extra bump, DOM-order ties go to the later
   element (the toggle), and the cursor disappears behind it. */
html.case-gated body > .theme-toggle{
  z-index: 10000;
}
html.case-gated body > .peer{
  z-index: 10001;
}

/* The gate overlay. Hidden by default; flex when .case-gated is set. */
.case-gate{
  display: none;
}
html.case-gated .case-gate{
  display: flex;
}

.case-gate{
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--ground);
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 48px var(--pad-x, 60px);
  box-sizing: border-box;
}

/* Back link — top-left. Styled and behaves identically to the
   case-study back link (.v2-layout-b .v2-back-link): same font,
   weight, size, color tokens, color-only transition, and the
   arrow-slide on hover (gap 8→12). Only the text differs ("Back
   to portfolio" vs "Back to work"). Position is absolute so it
   floats in the page corner while the gate card sits centered. */
.case-gate-back{
  position: absolute;
  top: 32px;
  left: 32px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0;
  color: var(--mid);
  text-decoration: none;
  transition: color .25s var(--ease);
}
.case-gate-back:hover{
  color: var(--ink);
  gap: 12px;
}

/* Card containing the gate content. Uses --asset-bg (not --paper-2)
   so the card has the same "defined framing" treatment as gallery
   containers / BAs / figures elsewhere in the case study, rather
   than the quieter --paper-2 chrome that's tuned for transient
   surfaces (row hover). Higher delta against --ground means the
   card reads as a discrete object in both modes — light-mode
   especially, where --paper-2 was nearly invisible against --ground.
   min-height + justify-content: center give the content room to
   breathe AND vertically center it within the card (rather than
   stacking from the top), which makes the card feel composed
   instead of "starts at the top, ends when content runs out." */
.case-gate-content{
  max-width: 560px;
  width: 100%;
  min-height: 480px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 20px;
  text-align: center;
  background: var(--asset-bg);
  border-radius: 16px;
  padding: 48px;
  box-sizing: border-box;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .18);
}
/* Light-mode shadow — softened further. Earlier values (.06, larger
   blur) read as a fuzzy halo around the card edges. Tight blur + low
   alpha lands as quiet lift instead of a smudge. */
:root[data-theme="light"] .case-gate-content{
  box-shadow: 0 6px 20px rgba(0, 0, 0, .04);
}

/* Lock icon above the title. Outline style (not filled), thin stroke,
   --mid color so it supports rather than competes with the title
   typography. Reads as a visual anchor/punctuation mark — instantly
   signals "auth" without needing the title text to do all the work. */
.case-gate-lock{
  display: block;
  margin: 0 auto;
  color: var(--mid);
  width: 22px;
  height: 22px;
}

/* Title — smaller clamp than before. At 56px max, "Password required."
   dominated the card and made the layout feel top-heavy. 40px max
   gives the title its presence while leaving room for the body, form,
   and breathing space to coexist in better vertical proportion. */
.case-gate-title{
  font-family: 'Antonio', sans-serif;
  font-weight: 700;
  font-size: clamp(28px, 3.5vw, 40px);
  line-height: 1.05;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0;
}

.case-gate-body{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 400;
  font-size: 15px;
  line-height: 1.6;
  color: var(--mid);
  margin: 0;
  max-width: 38ch;
  margin-left: auto;
  margin-right: auto;
}

/* Form — tight gap pairs the input + button as a single unit; the
   error message sits AFTER the button (reordered in markup) so it
   doesn't push them apart when shown. Margin-top creates a deliberate
   gap between the title/body group and the form group — they read
   as two distinct beats rather than one continuous stack. */
.case-gate-form{
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 24px;
}

/* Input — uses --ground (the page bg color) so it lifts off the
   --asset-bg card in light mode (cream input on tan card) and reads
   as a distinct surface in dark mode (warm-dark input set into
   warm-darker card). Matches the reference's "input is its own
   discrete object on the card" pattern without needing a hardcoded
   color that would break theming. */
.case-gate-input{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 16px;
  padding: 14px 18px;
  background: var(--ground);
  border: 1.5px solid var(--rule-strong);
  border-radius: 10px;
  color: var(--ink);
  outline: none;
  text-align: center;
  letter-spacing: 0.05em;
  transition: border-color .2s ease;
  width: 100%;
  box-sizing: border-box;
}
/* Focus state — system text color (--ink) rather than pink. The
   editorial vocabulary uses --ink for primary text; using it here
   makes the field's active state feel like "this is now the focal
   text input" rather than "warning, error-adjacent color." Error
   state still uses pink (see below) so the two states are
   distinguishable. */
.case-gate-input:focus{
  border-color: var(--ink);
}

/* Helper text — always present by default, occupies the slot below
   the button so the form layout is rock-solid (no jump when error
   toggles in/out). Also does real work: visitors without a password
   know what to do. The mailto link is subtle (--mid color, no
   underline unless hovered) so it doesn't compete with the primary
   Enter CTA. */
.case-gate-helper{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 13px;
  color: var(--mid);
  margin: 6px 0 0;
  text-align: center;
}
.case-gate-helper a{
  color: var(--mid);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--mid) 30%, transparent);
  text-underline-offset: 3px;
  transition: color .2s ease, text-decoration-color .2s ease;
}
.case-gate-helper a:hover{
  color: var(--ink);
  text-decoration-color: var(--ink);
}

/* Error — sits in the same slot as the helper. By default the error
   is display:none and the helper is visible; on .is-error, they
   swap. Same font-size, same margin, same single-line height — so
   the swap is invisible to the layout. */
.case-gate-error{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-size: 13px;
  color: var(--accent-strong);
  margin: 6px 0 0;
  text-align: center;
  display: none;
}
.case-gate.is-error .case-gate-input{
  border-color: var(--accent-strong);
}
.case-gate.is-error .case-gate-helper{
  display: none;
}
.case-gate.is-error .case-gate-error{
  display: block;
}

/* Submit button — accent (pink) signals interactivity. Font-size,
   padding, and border-radius MATCH the input above so the two read
   as a single, equally-weighted pair rather than a "field above, CTA
   below" hierarchy. White text against pink is fixed (not a token) so
   it reads in both light and dark mode without needing a per-mode
   override — the pink fill itself shifts via the token.
   No hover state by design — the static fill carries the affordance,
   and the cursor pointer is the only feedback needed. */
.case-gate-submit{
  font-family: 'Plus Jakarta Sans', sans-serif;
  font-weight: 600;
  font-size: 16px;
  padding: 14px 18px;
  background: var(--accent-strong);
  color: #FFFFFF;
  border: 0;
  border-radius: 10px;
  cursor: pointer;
}
