/* =====================================================================
   project.css — project-detail page template
   A static port of the joinery-app project page design system.
   Landing page keeps its own style.css (dark reveal theme); this sheet
   owns the light "paper" project pages.
   ===================================================================== */

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

/* ── Cross-document view transition (row → hero morph) ────────────
   Opt into cross-document View Transitions so arriving from the index
   morphs the clicked row's image + title into this page's hero. Keep the
   timing block identical to style.css. */
@view-transition { navigation: auto; }

::view-transition-group(project-hero-media),
::view-transition-group(project-hero-title) {
  animation-duration: 420ms;
  animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1); /* snappy ease-out */
}
::view-transition-group(root) { animation-duration: 220ms; }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*) { animation: none; }
}

/* Fallback (browsers without cross-document VT): the arriving page hides its
   hero pre-paint and fades it in — see the paired head script in each page. */
.vt-fallback-in #hero { opacity: 0; }

/* ── Fonts ────────────────────────────────────────────────────── */
/* Body/UI face — Geist (same cuts the landing page bundles). */
@font-face {
  font-family: 'Geist';
  src: url('fonts/Geist-Regular.ttf') format('truetype');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Geist';
  src: url('fonts/Geist-Italic.ttf') format('truetype');
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Geist';
  src: url('fonts/Geist-Medium.ttf') format('truetype');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Geist';
  src: url('fonts/Geist-SemiBold.ttf') format('truetype');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Geist';
  src: url('fonts/Geist-Bold.ttf') format('truetype');
  font-weight: 700; font-style: normal; font-display: swap;
}

/* Cover/hero title face — PP Migra Italic (replaces joinery's Cochin). */
@font-face {
  font-family: 'PPMigra';
  src: url('fonts/PPMigra-Italic.woff2') format('woff2'),
       url('fonts/PPMigra-Italic.woff') format('woff'),
       url('fonts/PPMigra-Italic.ttf') format('truetype');
  font-weight: 400; font-style: italic; font-display: swap;
}

/* ── Design tokens (ported verbatim from joinery styles/tokens.css) ── */
:root {
  --ink: #0A0A0A;
  --paper: #FFFFFF;
  --paper-off: #FBFBF9;
  --dark: #0d0e43;               /* navy — matches the landing reveal layer (style.css --bg-clipped) */
  --muted-1: #4d5566;            /* cool blue-grays, anchored to style.css --text-muted #6D7C9C */
  --muted-2: #7e8598;
  --muted-3: #9ca3b2;
  --muted-dark-label: #a6adbf;   /* labels on the dark hero/lede */
  --light-on-dark: #f7f5f1;      /* values/body on the dark hero/lede (matches style.css --text-warm) */
  --hairline-1: #e3e5ea;
  --hairline-2: #eef0f4;
  --accent: #0d0e43;             /* clipped navy from style.css, replacing the old orange */
  --accent-live: #7C8DBF;        /* lightened navy for the LIVE dot on the dark band */

  --font-display: 'Geist', sans-serif;
  --font-serif: 'PPMigra', 'Cochin', Georgia, 'Times New Roman', serif;

  /* Grid: 1176px content frame, 3 columns, 24px gutters */
  --max-content: 1176px;
  --gutter: 24px;
  --grid-gap: 24px;

  --rhythm-section: clamp(56px, 7vw, 100px);
  --rhythm-update: clamp(28px, 3.5vw, 50px);
}

/* ── Base ─────────────────────────────────────────────────────── */
/* scrollbar-gutter must match index.html so the cross-document view
   transition's snapshot containing block is the same size on both pages
   (a size mismatch aborts the transition → instant navigation). */
html { scroll-behavior: smooth; scrollbar-gutter: stable; }
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-display);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }

/* ── Type scale (joinery lib/type.ts — the ten roles) ─────────── */
/* heroTitle: serif cover title (PP Migra italic here). Color set in context. */
.t-hero-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-style: italic;
  font-size: clamp(48px, 7.2vw, 104px);
  letter-spacing: -0.045em;
  line-height: 0.92;
}
/* sectionHeading: log titles, pull quotes, section headers. */
.t-section-heading {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(22px, 2.1vw, 30px);
  letter-spacing: -0.025em;
  line-height: 1.4;
  color: var(--ink);
}
/* heroDescription: the large intro blurb under the hero. Color set in context. */
.t-hero-description {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(20px, 2.1vw, 30px);
  letter-spacing: -0.018em;
  line-height: 1.36;
}
/* body / bodyBold: 18px reading text. */
.t-body      { font-family: var(--font-display); font-weight: 400; font-size: 18px; line-height: 1.66; color: var(--ink); }
.t-body-bold { font-family: var(--font-display); font-weight: 700; font-size: 18px; line-height: 1.66; color: var(--ink); }
/* body2 / body2Bold: 16px reading + UI text. */
.t-body2      { font-family: var(--font-display); font-weight: 400; font-size: 16px; line-height: 1.6; color: var(--ink); }
.t-body2-bold { font-family: var(--font-display); font-weight: 700; font-size: 16px; line-height: 1.6; color: var(--ink); }
/* dateStamp: uppercase log date. */
.t-date-stamp {
  font-family: var(--font-display);
  font-weight: 600; font-size: 13px;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--ink);
}
/* body3 / body3Bold: 11px labels, meta, captions, eyebrows. */
.t-body3      { font-family: var(--font-display); font-weight: 400; font-size: 11px; color: var(--muted-3); }
.t-body3-bold { font-family: var(--font-display); font-weight: 700; font-size: 11px; color: var(--muted-3); }

/* ── Grid helpers (joinery lib/grid.ts) ───────────────────────── */
.frame { max-width: var(--max-content); margin: 0 auto; padding: 0 var(--gutter); }
.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--grid-gap); }
.col1  { grid-column: 1 / 2; }   /* rail */
.cols23 { grid-column: 2 / 4; }  /* right two-thirds */
.cols12 { grid-column: 1 / 3; }  /* left two-thirds */
.col3  { grid-column: 3 / 4; }   /* right rail */

/* ── Hero (dark cover block; sits at very top of the page) ────── */
.hero {
  position: relative;
  width: 100%;
  min-height: min(663px, 74vh);
  overflow: hidden;
  background: #0D0B29;
  display: flex;
}
/* Cover image occupies the right ~54%. */
.hero__cover {
  position: absolute;
  top: 0; bottom: 0; left: 37%; right: 0;
}
/* Stack the poster image and the video so both fill the cover box; the video
   (later in the DOM) paints over the poster once it starts. */
.hero__cover img,
.hero__cover video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* The morph target is always the decoded poster image (one per page), never
   the heavy autoplaying video — that removes the video-decode readiness race. */
.hero__cover .vt-media { view-transition-name: project-hero-media; }
.hero__cover::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(13,14,67,0) 60%, rgba(13,14,67,0.6) 100%);
}
.hero__top {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; align-items: center; justify-content: space-between;
  max-width: var(--max-content); margin: 0 auto; padding: 30px var(--gutter);
}
/* .frame already centers; the top/bottom rows are absolutely placed but need the frame width */
.hero__top, .hero__bottom { left: 50%; transform: translateX(-50%); width: 100%; }
.hero__bottom {
  position: absolute; bottom: 0;
  max-width: var(--max-content); margin: 0 auto; padding: 0 var(--gutter) 46px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 21px;
}
.hero__kicker { letter-spacing: 0.16em; color: rgba(255,255,255,0.92); text-transform: uppercase; }
.hero__credit { letter-spacing: 0.1em;  color: rgba(255,255,255,0.6);  text-transform: uppercase; }
.status-pill {
  display: inline-flex; align-items: center; gap: 7px;
  letter-spacing: 0.04em; color: rgba(255,255,255,0.92);
  border: 1px solid rgba(255,255,255,0.4); border-radius: 999px;
  padding: 6px 13px 6px 11px;
}
.status-pill__dot { width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,0.5); display: inline-block; }
.status-pill__dot--live { background: var(--accent-live); }
.hero__title { margin: 0; color: #fff; max-width: 14ch; view-transition-name: project-hero-title; }
.hero__maker { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding-top: 5px; }
.hero__maker-id { display: flex; align-items: center; gap: 10px; }
.avatar {
  width: 38px; height: 38px; border-radius: 50%;
  background: #fff; color: var(--ink);
  display: flex; align-items: center; justify-content: center;
}
.hero__maker-name { color: #fff; font-weight: 500; font-size: 16px; }
.hero__sep { width: 1px; height: 22px; background: rgba(255,255,255,0.3); }
.hero__meta { color: rgba(255,255,255,0.78); letter-spacing: 0.02em; }

/* ── Lede (dark intro band, shares the hero's dark surface) ───── */
.lede { background: #0D0B29; }
.lede__inner { max-width: var(--max-content); margin: 0 auto; padding: 50px var(--gutter); }
.lede__meta { display: flex; flex-direction: column; gap: 20px; }
.lede__meta-item { display: flex; flex-direction: column; gap: 4px; }
.lede__meta-k { letter-spacing: 0.14em; color: var(--muted-dark-label); text-transform: uppercase; margin: 0; }
.lede__meta-v { color: var(--light-on-dark); font-weight: 500; margin: 0; }
.lede__main { display: flex; flex-direction: column; gap: 34px; }
.lede__blurb { color: var(--light-on-dark); margin: 0; }
.lede__actions { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.lede__collab { display: flex; align-items: center; gap: 12px; }
.collab-stack { display: flex; }
.collab-chip {
  width: 34px; height: 34px; border-radius: 50%;
  border: 2px solid #1e1c1c; display: flex; align-items: center; justify-content: center;
  background: #ECEBE6; color: var(--muted-1);
}
.collab-chip:first-child { background: var(--ink); color: var(--light-on-dark); }
.collab-chip + .collab-chip { margin-left: -8px; }

/* ── Buttons / pills ──────────────────────────────────────────── */
.pill {
  font-family: var(--font-display); font-weight: 700; font-size: 16px;
  border-radius: 999px; cursor: pointer; padding: 11px 22px;
  border: 1px solid var(--hairline-1); background: transparent; color: var(--ink);
}
.pill--ghost-light { font-weight: 500; border: 1px solid #D9D7D0; background: #fff; color: var(--ink); padding: 12px 21px; }
.pill--dark { border: none; background: var(--ink); color: #fff; }
.pill--primary { border: none; background: var(--accent); color: #fff; }
.pill--block { width: 100%; padding: 11px 18px; }

/* ── Nav header (the restyled JumpBar — main header of the page) ──
   Sits in normal flow below the hero+lede, then pins to the top. */
.nav {
  position: sticky; top: 0; z-index: 45;
  background: var(--paper-off);
  border-top: 1px solid var(--hairline-2);
  border-bottom: 1px solid var(--hairline-2);
}
/* Nav shares the page's 3-col grid so tabs line up with the content column. */
.nav__inner {
  max-width: var(--max-content); margin: 0 auto; padding: 0 var(--gutter);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--grid-gap);
  align-items: stretch;
}
/* Left rail (col 1): the name wordmark — aligns with the date/meta rail. */
.nav__rail {
  grid-column: 1 / 2;
  display: flex; align-items: center;
  border-right: 1px solid var(--hairline-1);
}
.nav__name { font-weight: 700; font-size: 16px; letter-spacing: -0.04em; color: var(--ink); white-space: nowrap; }
/* Tab row (cols 2–3): starts at the content column, one tab per project. */
.nav__tabs { grid-column: 2 / 4; min-width: 0; display: flex; overflow-x: auto; }
.nav__tab {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 12px 22px 14px; white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: border-color 240ms ease, color 240ms ease;
}
/* First tab sits flush with the content column edge (matches the headings). */
.nav__tab:first-child { padding-left: 0; }
.nav__tab-num   { letter-spacing: 0.04em; color: var(--muted-3); }
.nav__tab-title { color: var(--muted-1); }
.nav__tab:hover .nav__tab-title { color: var(--ink); }
.nav__tab--active { border-bottom-color: var(--accent); }
.nav__tab--active .nav__tab-num   { color: var(--accent); }
.nav__tab--active .nav__tab-title { color: var(--ink); }

/* ── Log feed & block rhythm (joinery ModuleRenderer.sectionGap) ── */
.feed { padding: var(--rhythm-section) 0; }
.log  { margin-top: var(--rhythm-section); }
.log:first-child { margin-top: 0; }
.block { margin-top: var(--rhythm-section); }
.block:first-child { margin-top: 0; }
/* An update header, and the block immediately after it, use the tighter rhythm. */
.block--tight { margin-top: 16px; }
.block--update { margin-top: var(--rhythm-update); }
.block--update + .block { margin-top: var(--rhythm-update); }

/* ── Module: Update (log header) ──────────────────────────────── */
.m-update__meta { }
.m-update__date { margin: 6px 0 4px; }
.m-update__label { letter-spacing: 0.14em; text-transform: uppercase; margin: 0; }
.m-update__body h3 { margin: 0 0 20px; }
.m-update__body h3:only-child { margin-bottom: 0; }
.m-update__body p { margin: 0; }
.m-update--divider { border-top: 1px solid var(--ink); padding-top: 50px; }

/* ── Module: Figure (one image + caption rail) ────────────────── */
.m-figure__rail { display: flex; flex-direction: column; gap: 10px; padding-top: 4px; }
.m-figure__rail p { margin: 0; }
.m-figure__media { position: relative; }
.m-figure__media img {
  max-width: 100%; max-height: 920px; width: auto; height: auto; background: var(--dark);
}

/* ── Module: Bleed (full-bleed image + caption row) ───────────── */
.m-bleed { width: 100%; }
.m-bleed__media { position: relative; width: 100%; background: var(--dark); }
.m-bleed__media img { width: 100%; height: auto; }
.m-bleed__cap { position: relative; padding-top: 14px; min-height: 16px; }
.m-bleed__cap .caption { text-align: center; letter-spacing: 0.02em; margin: 0; padding: 0 60px; }
.m-bleed__cap .n { position: absolute; right: var(--gutter); top: 14px; letter-spacing: 0.1em; }

/* ── Module: Trio (three images) ──────────────────────────────── */
.m-trio__media { aspect-ratio: 4/5; background: var(--dark); overflow: hidden; }
.m-trio__media img { width: 100%; height: 100%; object-fit: cover; }
.m-trio figcaption { letter-spacing: 0.02em; margin: 10px 0 0; line-height: 1.5; }

/* ── Module: Callout (text-only statement) ────────────────────── */
.m-callout--featured .m-callout__tick { width: 26px; height: 3px; background: var(--accent); margin-bottom: 24px; }
.m-callout--featured blockquote { margin: 0 0 22px; }
.m-callout--featured .attribution { letter-spacing: 0.04em; margin: 0; }
.m-callout__plain p { margin: 0; }

/* ── Module: Problems (numbered problem ledger) ───────────────── */
.m-problems { list-style: none; margin: 0; padding: 0; }
.m-problem {
  display: grid;
  grid-template-columns: 3.5rem 1fr;
  column-gap: 24px;
  align-items: baseline;
  padding: 16px 0;
}
.m-problem__num { color: var(--muted-3); font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.m-problem__body { display: flex; flex-direction: column; gap: 8px; }
.m-problem__label { letter-spacing: 0.14em; text-transform: uppercase; margin: 0; color: var(--muted-1); }
.m-problem__text { margin: 0; max-width: 60ch; }

/* ── Module: Notice (seeking-collaborators / info card) ───────── */
.m-notice {
  border: 1px solid var(--hairline-1); border-radius: 4px; background: var(--paper-off);
  padding: clamp(32px, 5vw, 64px) clamp(28px, 6vw, 100px);
}
.m-notice--help { border-color: rgba(13,14,67,0.19); background: rgba(13,14,67,0.03); }
.m-notice .grid3 { align-items: start; }
.m-notice__body { max-width: 574px; }
.m-notice__kicker { letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted-3); margin: 0 0 16px; }
.m-notice--help .m-notice__kicker { color: var(--accent); }
.m-notice__body h3 { margin: 0 0 12px; }
.m-notice__body > p { margin: 0; }
.m-notice__loc { letter-spacing: 0.02em; margin: 14px 0 0; }
.m-notice__tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.m-notice__tags span { color: var(--muted-1); border: 1px solid var(--hairline-1); border-radius: 999px; padding: 4px 10px; }
.m-notice__actions { display: flex; flex-direction: column; gap: 12px; }
.m-notice__posted { letter-spacing: 0.08em; text-transform: uppercase; margin: 0; }

/* ── Module: Up next (navigates to the next project) ──────────── */
.m-upnext {
  display: block;
  border: 1px solid var(--hairline-1); border-radius: 4px; background: var(--paper-off);
  padding: clamp(32px, 5vw, 64px) clamp(28px, 6vw, 100px);
  transition: background 240ms ease, border-color 240ms ease;
}
.m-upnext:hover { background: #fff; border-color: #D9D7D0; }
.m-upnext .grid3 { align-items: center; }
.m-upnext__meta { display: flex; align-items: baseline; gap: 12px; }
.m-upnext__kicker { letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted-3); margin: 0; }
.m-upnext__num { letter-spacing: 0.04em; color: var(--muted-3); }
.m-upnext__body { display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.m-upnext__title { margin: 0; transition: color 240ms ease; }
.m-upnext__arrow {
  flex-shrink: 0; width: 26px; height: 26px; position: relative;
  transition: transform 240ms ease;
}
.m-upnext__arrow::before,
.m-upnext__arrow::after { content: ""; position: absolute; }
.m-upnext__arrow::before { top: 50%; left: 0; width: 100%; height: 2px; background: var(--ink); transform: translateY(-50%); }
.m-upnext__arrow::after {
  top: 50%; right: 0; width: 11px; height: 11px;
  border-top: 2px solid var(--ink); border-right: 2px solid var(--ink);
  transform: translateY(-50%) rotate(45deg); transform-origin: right center;
}
.m-upnext:hover .m-upnext__title { color: var(--accent); }
.m-upnext:hover .m-upnext__arrow { transform: translateX(6px); }
.m-upnext:hover .m-upnext__arrow::before { background: var(--accent); }
.m-upnext:hover .m-upnext__arrow::after { border-color: var(--accent); }

/* ── Password gate (protected case study) ─────────────────────── */
.gate { display: flex; flex-direction: column; gap: 14px; max-width: 46ch; }
.gate__kicker { letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent); margin: 0; }
.gate__label { margin: 0; color: var(--muted-1); }
.gate__row { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 4px; }
.gate__input {
  flex: 1 1 220px; min-width: 0;
  font-family: var(--font-display); font-size: 16px; color: var(--ink);
  padding: 11px 16px; background: #fff;
  border: 1px solid var(--hairline-1); border-radius: 999px;
  transition: border-color 200ms ease;
}
.gate__input::placeholder { color: var(--muted-3); }
.gate__input:focus { outline: none; border-color: var(--accent); }
.gate__input[aria-invalid="true"] { border-color: #b3261e; }
.gate__btn { flex: 0 0 auto; cursor: pointer; }
.gate__error { color: #b3261e; margin: 0; }

/* ── Video play-button overlay (Figure / Bleed) ───────────────── */
.play-btn {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);
  width: 56px; height: 56px; border-radius: 50%;
  background: rgba(10,10,10,0.45); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,0.45);
}
.play-btn::before {
  content: ""; width: 0; height: 0; margin-left: 4px;
  border-left: 14px solid #fff; border-top: 9px solid transparent; border-bottom: 9px solid transparent;
}
.m-bleed .play-btn { width: 84px; height: 84px; }
.m-bleed .play-btn::before { margin-left: 6px; border-left: 22px solid #fff; border-top: 13px solid transparent; border-bottom: 13px solid transparent; }

/* ── Device: iPhone frame wrapping an autoplay clip ─────────────
   The frame PNG (images/iphone-frame.png) has a fully transparent
   screen; the clip sits behind it, the frame overlays on top.
   Screen inset measured from the asset: top 7.16%, sides ~4%,
   bottom 1.66%. Video plays via IntersectionObserver (see page JS). */
.device {
  position: relative;
  width: 100%;
  max-width: 320px;
  margin: 0 auto;
  aspect-ratio: 1310 / 2710;
  /* shadow follows the phone silhouette, not a box */
  filter: drop-shadow(0 22px 44px rgba(10, 10, 10, 0.20));
}
.device__screen {
  position: absolute;
  /* screen glass reaches the very top — the dynamic island (part of the
     frame PNG) floats over it, so content runs edge-to-edge like a real phone */
  top: 1.66%; left: 3.97%; right: 4.05%; bottom: 1.70%;
  overflow: hidden;
  border-radius: 12% / 5.5%;
  background: #000 center / cover no-repeat;   /* poster still is set here via JS */
  z-index: 1;
}
.device__screen video,
.device__screen img {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
}
/* Once JS is present the clip stays hidden over its poster until it is truly
   playing — so a clip can never flash a black first frame. Without JS the
   video shows its own poster attribute normally (opacity stays 1). */
.has-js-video .device__screen video { opacity: 0; transition: opacity 450ms ease; }
.has-js-video .device.is-playing .device__screen video { opacity: 1; }
/* Grey stand-in while a clip is pending. */
.device__placeholder {
  width: 100%; height: 100%;
  background: #d6d7da;
}
.device__frame {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 2;
}
/* Play affordance — only visible while the clip is paused
   (initial state, off-screen, or when reduced motion is on). */
.device__play {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(0.9);
  z-index: 3;
  width: 54px; height: 54px; border-radius: 50%;
  background: rgba(10, 10, 10, 0.42); backdrop-filter: blur(3px);
  border: 1px solid rgba(255, 255, 255, 0.5);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; pointer-events: none;
  transition: opacity 200ms ease, transform 200ms ease;
}
.device__play::before {
  content: ""; width: 0; height: 0; margin-left: 4px;
  border-left: 15px solid #fff; border-top: 9px solid transparent; border-bottom: 9px solid transparent;
}
.device.is-paused .device__play { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* Flagship phone: centered in cols 2–3. Deliberately NOT .m-figure__media —
   that module's `img { background: var(--dark) }` rule would tint the frame
   PNG, and its transparent screen would show that dark over the clip. This is
   a plain centering wrapper, so the frame behaves like the gallery phones. */
.m-figure__phone { display: flex; justify-content: center; padding: 8px 0; }
.m-figure__phone .device { max-width: 340px; }

/* Duo figure — caption rail (col1) + two phones side by side (cols23), no
   per-phone captions. Keeps the two clips visually paired under one caption. */
.m-figure--duo.grid3 { align-items: start; }
.m-figure__phones {
  display: flex; justify-content: center; align-items: flex-start;
  gap: clamp(8px, 1.4vw, 16px); padding: 8px 0;
}
.m-figure__phones .device { flex: 1 1 0; max-width: 300px; }

/* Bare clip — reuses the .device autoplay wiring (JS + opacity fade), but
   drops the iPhone frame, the forced 1310/2710 aspect ratio and the cover
   crop, so the video shows at its own natural aspect ratio. */
.device--bare { aspect-ratio: auto; width: 100%; max-width: 390px; filter: none; }
.device--bare .device__screen {
  position: static; inset: auto; overflow: visible;
  border-radius: 0; background: none;
}
.device--bare .device__screen video,
.device--bare .device__screen img { height: auto; object-fit: contain; }

/* Device row — a gallery of phones with captions (loops / explorations). */
.m-devices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: clamp(26px, 3vw, 44px);
  align-items: start;
}
.m-device { display: flex; flex-direction: column; }
.m-device .device { max-width: 260px; }
.m-device__cap { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; }
.m-device__cap .media-label { letter-spacing: 0.02em; }
.m-device__cap p { margin: 0; }

/* ── Module: Table (data / roadmap tables) ────────────────────── */
.m-table__wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.m-table {
  width: 100%; border-collapse: collapse;
  font-family: var(--font-display); font-size: 16px; line-height: 1.5;
  font-variant-numeric: tabular-nums;
}
.m-table caption {
  text-align: left; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted-3); font-weight: 700; font-size: 11px;
  padding-bottom: 14px;
}
.m-table th, .m-table td {
  text-align: left; padding: 13px 20px 13px 0; vertical-align: top;
  border-bottom: 1px solid var(--hairline-1);
}
.m-table thead th {
  color: var(--muted-1); font-weight: 700; font-size: 13px;
  letter-spacing: 0.02em; border-bottom-color: var(--ink);
  white-space: nowrap;
}
.m-table tbody th { color: var(--ink); font-weight: 500; }
.m-table td { color: var(--muted-1); }
.m-table td:first-child, .m-table th:first-child { padding-left: 0; }
.m-table td:last-child, .m-table th:last-child { padding-right: 0; }
.m-table tbody tr:last-child th,
.m-table tbody tr:last-child td { border-bottom: none; }
.m-table__num { color: var(--ink); font-weight: 500; }

/* ── Module: Stats (big-number readout) ───────────────────────── */
.m-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(16px, 2vw, 26px);
}
.m-stat {
  padding: 0;
  display: flex; flex-direction: column; gap: 8px;
}
.m-stat__num {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(34px, 4vw, 46px); letter-spacing: -0.03em;
  line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums;
}
.m-stat__num .m-stat__x { color: var(--accent); font-size: 0.62em; letter-spacing: -0.01em; }
.m-stat__label { letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted-1); margin: 0; }
.m-stat__note { color: var(--muted-2); margin: 2px 0 0; }

/* ── Responsive ───────────────────────────────────────────────── */
@media (max-width: 991px) {
  .hero { min-height: min(560px, 70vh); }
  .hero__cover { left: 30%; }
  .lede__inner { padding: 40px var(--gutter); }
}

@media (max-width: 767px) {
  /* Collapse the 3-col grid to a single column across all modules. */
  .grid3 { grid-template-columns: 1fr; gap: 20px; }
  .col1, .cols23, .cols12, .col3 { grid-column: 1 / -1; }

  /* Hero: let the cover recede behind a darker scrim, text stacks over it. */
  .hero { min-height: auto; }
  .hero__cover { left: 0; opacity: 0.5; }
  .hero__cover::after { background: linear-gradient(180deg, rgba(13,14,67,0.35) 0%, rgba(13,14,67,0.85) 100%); }
  .hero__top { position: static; transform: none; }
  .hero__bottom { position: static; transform: none; margin-top: 220px; padding-top: 24px; }
  .hero { display: block; }

  /* Nav: drop the name rail, let tabs use the full width. */
  .nav__inner { grid-template-columns: 1fr; }
  .nav__rail { display: none; }
  .nav__tabs { grid-column: 1 / -1; }

  /* Stats: four-up is too tight on phones — two per row. */
  .m-stats { grid-template-columns: repeat(2, 1fr); }

  /* Figure: caption rail sits above the image. */
  .m-figure__media img { max-height: none; width: 100%; }
  .m-bleed__cap .caption { padding: 0 var(--gutter); text-align: left; }
  .m-bleed__cap .n { position: static; display: block; margin-top: 6px; }
}

@media (max-width: 479px) {
  .lede__actions { flex-direction: column; align-items: flex-start; }
  .m-notice { padding: 28px 22px; }
}
