/* Landing v10 — "Fixed Stage." One background stage (position:fixed, inset:0,
   no vh/svh/lvh sizing anywhere on it), all copy in a normal-flow scroll
   column above it. See docs/v10-fixed-stage-spec.md for the architecture
   rationale — this file replaces landing-v7.css for index.html only;
   subpages never referenced landing-v7.css/js (confirmed: they only load
   src/styles.css + src/main.js), so nothing else changes. */
@import url("https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,300..500&family=Inter:wght@400;500;600&display=swap");

body.v7-page {
  --v7-ink: #0d1421;
  --v7-night: #071020;
  --v7-paper: #f6f3ec;
  --v7-haze: #e9edf2;
  --v7-gold: #c9a257;
  --v7-teal: #7fa8b8;
  --v7-ink-80: rgba(13, 20, 33, 0.8);
  --v7-ink-72: rgba(13, 20, 33, 0.72);
  --v7-ink-62: rgba(13, 20, 33, 0.62);
  --v7-ivory-96: rgba(246, 243, 236, 0.96);
  --v7-ivory-60: rgba(246, 243, 236, 0.6);
  --v7-r-outer: 24px;
  --v7-r-inner: 16px;
  /* v21: floating glass panel radius — one size up from --v7-r-outer,
     concentric with it (32 vs 24/16), per the room-panel spec. */
  --v7-r-panel: 32px;
  --v7-r-panel-mobile: 24px;
  --v7-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --v7-ease-in: cubic-bezier(0.6, 0, 0.84, 0.14);
  background: var(--v7-paper);
}

/* ---------- Nav dark-theme flip (Night + Principles + hero-night-variant) ---------- */
body.v7-page .site-header.is-dark {
  color: var(--v7-ivory-96);
  border-color: rgba(246, 243, 236, 0.16);
  background:
    linear-gradient(135deg, rgba(246, 243, 236, 0.14), rgba(246, 243, 236, 0.03)),
    rgba(7, 16, 32, 0.56);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 -1px 0 rgba(0, 0, 0, 0.3);
}

body.v7-page .site-header.is-dark .brand-mark {
  filter: invert(1);
}

body.v7-page .site-header.is-dark .nav-cta {
  color: var(--v7-ink);
  background:
    radial-gradient(circle at 20% 0, rgba(255, 255, 255, 0.4), transparent 40%),
    var(--v7-gold);
}

body.v7-page .site-header.is-dark .mobile-menu {
  border-color: rgba(246, 243, 236, 0.2);
  background:
    linear-gradient(145deg, rgba(246, 243, 236, 0.16), rgba(246, 243, 236, 0.05)),
    rgba(7, 16, 32, 0.72);
}

body.v7-page .site-header.is-dark .mobile-menu a {
  color: var(--v7-ivory-96);
}

body.v7-page .site-header.is-dark .mobile-menu a:hover,
body.v7-page .site-header.is-dark .mobile-menu a[aria-current="page"] {
  background: rgba(246, 243, 236, 0.12);
}

/* ---------- Base ---------- */
.landing-v7 {
  color: var(--v7-ink);
}

/* v10: the flow column itself must be transparent — every "room" section
   (range/ventures/night/principles) already carries its own opaque
   background; a background here would sit above the stage (main has an
   explicit z-index to stack above it) and paint solid paper over every
   transparent hero/film-chapter section, hiding the stage completely. */
body.v10-page main.landing-v7 {
  background: transparent;
}

.landing-v7 h1,
.landing-v7 h2,
.landing-v7 h3 {
  /* v12: margin-block only (not the shorthand) — the UA default margin on
     headings is vertical anyway, and zeroing all four sides here used to
     silently win a specificity fight against component rules further down
     this file that set `margin: ... auto` to horizontally center a heading
     (e.g. .v7-hero-title, .v7-hero-sub, .v7-hero-signature): a two-part
     selector like ".landing-v7 h1" carries more specificity than a lone
     class like ".v7-hero-sub", so its "margin: 0" was clobbering their
     "auto" inline margins and leaving those boxes flush at the left edge
     instead of centered — the real cause of the v12 hero-alignment bug. */
  margin-block: 0;
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-weight: 400;
  line-height: 0.98;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.landing-v7 p {
  /* v12: see margin-block note above — same clobbering issue applied to
     every centered paragraph (.v7-hero-sub, .v7-hero-signature, etc). */
  margin-block: 0;
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-weight: 400;
}

.landing-v7 .v7-eyebrow,
.landing-v7 .v7-lane-label,
.landing-v7 .v7-venture-name,
.landing-v7 .v7-principle-num {
  font-variant-numeric: tabular-nums;
}

.v7-mask {
  display: block;
  overflow: hidden;
}

.v7-mask-line {
  display: block;
  transform: translateY(0);
}

/* ---------- Global texture (grain) ---------- */
body.v7-page ::selection {
  background: var(--v7-gold);
  color: var(--v7-ink);
}

.v7-grain {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-repeat: repeat;
  background-size: 180px 180px;
  background-position: 0 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch' result='t'/%3E%3CfeColorMatrix in='t' type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: v7-grain-shift 0.9s steps(8) infinite;
}

@keyframes v7-grain-shift {
  0% { background-position: 0 0; }
  12.5% { background-position: -42px 18px; }
  25% { background-position: 28px -32px; }
  37.5% { background-position: -18px 42px; }
  50% { background-position: 46px 8px; }
  62.5% { background-position: -30px -26px; }
  75% { background-position: 22px 36px; }
  87.5% { background-position: -14px -44px; }
  100% { background-position: 0 0; }
}

@media (prefers-reduced-motion: reduce), (prefers-reduced-data: reduce) {
  .v7-grain {
    display: none;
  }
}

/* ============================================================
   v10 STAGE — one fixed background, no vh/svh/lvh sizing at all.
   inset:0 always fills the current visual viewport by construction;
   there is no section-height math to desync against dynamic browser
   chrome, touch timing, or pin math, because nothing here is sized
   to the viewport in the first place.
   ============================================================ */
.v10-stage {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background: var(--v7-ink);
}

/* Every direct child of the stage is an explicitly stacked, explicitly
   positioned full-bleed layer — position + a set z-index integer (not
   "auto") guarantees each one establishes its own stacking context
   regardless of the opacity value the JS conductor happens to be driving
   at any moment, so the legacy negative z-index scheme *inside* e.g. the
   hero layer (media/fog/godray/towers) never leaks into or fights with
   sibling layers (journey video, stills, night ambience) at the stage's
   own top level. */
.v10-stage > .v10-layer {
  position: absolute;
  inset: 0;
}

.v10-hero-layer {
  z-index: 5;
  opacity: 1;
  isolation: isolate;
}

.v10-journey-layer {
  z-index: 4;
  opacity: 0;
  isolation: isolate;
}

.v10-still {
  z-index: 6;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 55%;
  opacity: 0;
}

.v10-night-ambience {
  z-index: 7;
  opacity: 0;
  transition: opacity 0.2s linear;
}

.v10-stage-scrim {
  z-index: 8;
  opacity: 0;
  background: rgba(7, 16, 32, 0.4);
  transition: opacity 0.4s ease-out, filter 0.4s ease-out;
}

.v10-stage.is-dimmed .v10-stage-scrim {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .v10-stage-scrim {
    transition: none;
  }
}

/* ---------- Hero diorama (lives inside .v10-hero-layer on the stage) ---------- */
.v7-hero-media {
  position: absolute;
  inset: 0;
  z-index: -6;
  animation: v7-hero-breathe 36s ease-in-out infinite;
}

@keyframes v7-hero-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.045); }
}

.v7-hero-plate {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 60%;
  transform: scale(1);
  will-change: transform;
}

.v7-hero-fallback {
  display: none;
}

.v7-hero-media.is-static .v7-hero-video {
  display: none;
}

.v7-hero-media.is-static .v7-hero-fallback {
  display: block;
}

.v7-hero-scrim {
  position: absolute;
  inset: 0;
  z-index: -2;
  background:
    linear-gradient(180deg, rgba(13, 20, 33, 0.34) 0%, rgba(13, 20, 33, 0.08) 34%, rgba(13, 20, 33, 0.03) 58%, rgba(13, 20, 33, 0.24) 100%);
}

.v7-hero-fog {
  position: absolute;
  inset: -18% -22%;
  overflow: hidden;
  pointer-events: none;
}

.v7-hero-fog-back {
  z-index: -5;
  animation: v7-fog-sway-back 84s ease-in-out infinite alternate;
}

.v7-hero-fog-front {
  z-index: -4;
  animation: v7-fog-sway-front 63s ease-in-out infinite alternate;
}

.v7-hero-fog-inner {
  position: absolute;
  inset: 0;
  will-change: transform;
}

.v7-hero-fog img {
  width: 130%;
  height: 130%;
  object-fit: cover;
}

.v7-hero-fog-back img {
  opacity: 0.32;
  filter: blur(22px) saturate(0.92);
}

.v7-hero-fog-front img {
  opacity: 0.46;
  filter: blur(10px) saturate(0.96);
}

@keyframes v7-fog-sway-back {
  from { transform: translateX(-3.2%); }
  to { transform: translateX(3.2%); }
}

@keyframes v7-fog-sway-front {
  from { transform: translateX(2.6%); }
  to { transform: translateX(-2.6%); }
}

.v7-hero-godray {
  position: absolute;
  inset: 0;
  z-index: -3;
  pointer-events: none;
  background: radial-gradient(ellipse 68% 58% at 88% 4%, rgba(255, 231, 180, 0.95), transparent 62%);
  mix-blend-mode: soft-light;
  opacity: 0.14;
  animation: v7-godray-breathe 9s ease-in-out infinite;
}

@keyframes v7-godray-breathe {
  0%, 100% { opacity: 0.1; }
  50% { opacity: 0.22; }
}

.v7-hero-godray.v10-handoff-quiet {
  animation: none;
}

/* Tower cutout: depth separation, hidden in static-fallback mode (its own
   photo already has baked-in towers) except dusk/night, whose relit still
   needs the animated cutout to keep the scene reading as alive. */
.v8-towers-wrap {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  will-change: transform;
  animation: v7-hero-breathe 36s ease-in-out infinite;
}

.v8-towers {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform, opacity;
}

.v7-hero-media.is-static ~ .v8-towers-wrap {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .v8-towers-wrap {
    animation: none;
    display: none;
  }
}

.v8-cloudshadow {
  position: absolute;
  inset: -22% -30%;
  z-index: -3;
  pointer-events: none;
  background:
    radial-gradient(38% 30% at 22% 60%, rgba(13, 20, 33, 0.16), transparent 70%),
    radial-gradient(30% 24% at 64% 74%, rgba(13, 20, 33, 0.12), transparent 70%),
    radial-gradient(24% 20% at 86% 52%, rgba(13, 20, 33, 0.1), transparent 70%);
  mix-blend-mode: multiply;
  animation: v8-shadow-drift 84s ease-in-out infinite alternate;
}

@keyframes v8-shadow-drift {
  from { transform: translateX(-4%) translateY(0.5%); }
  to { transform: translateX(5%) translateY(-0.8%); }
}

.v8-birds {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 4;
  pointer-events: none;
}

/* ---------- Journey film (lives inside .v10-journey-layer on the stage) ---------- */
.v10-journey-poster,
.v10-journey-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 55%;
}

.v10-journey-video {
  opacity: 0;
  transition: opacity 0.18s linear;
}

.v10-journey-video.is-ready {
  opacity: 1;
}

/* ---------- Night ambience (aurora + stars) ---------- */
.v7-night-aurora {
  position: absolute;
  left: -20%;
  right: -20%;
  top: 36%;
  height: 16%;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(127, 168, 184, 0.9), rgba(201, 162, 87, 0.55), transparent);
  background-size: 220% 100%;
  filter: blur(24px);
  opacity: 0.1;
  mix-blend-mode: screen;
  animation: v7-aurora-drift 42s linear infinite;
}

@keyframes v7-aurora-drift {
  0% { background-position: 0% 0; }
  100% { background-position: 220% 0; }
}

.v7-night-stars {
  position: absolute;
  inset: 0 0 45% 0;
  pointer-events: none;
}

.v7-star {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: 3px;
  height: 3px;
  border-radius: 999px;
  background: var(--v7-ivory-96);
  box-shadow: 0 0 6px 1px rgba(246, 243, 236, 0.6);
  animation: v7-twinkle var(--d, 5s) ease-in-out infinite;
}

@keyframes v7-twinkle {
  0%, 100% { opacity: 0.25; }
  50% { opacity: 0.9; }
}

/* ============================================================
   FLOW — normal-flow copy column above the stage. Sections are
   transparent where the stage should show through, opaque(-ish)
   where they are "rooms." main/footer get an explicit stacking
   context above the stage (z-index:0 fixed) — a plain in-flow,
   non-positioned element would otherwise paint *behind* a
   positioned z-index:0 sibling per the CSS stacking order, letting
   the fixed stage show through solid content.
   ============================================================ */
body.v10-page main.landing-v7,
body.v10-page .site-footer {
  position: relative;
  z-index: 1;
}

/* ---------- Hero copy (transparent flow section) ---------- */
.v10-hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  isolation: isolate;
}

.v7-hero-copy {
  position: relative;
  z-index: 2;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(16px, 2.4vw, 26px);
  width: min(880px, 92vw);
  margin: 0 auto;
  padding: 0 max(20px, calc((100vw - 1280px) / 2)) clamp(56px, 11vh, 150px);
  text-align: center;
  color: var(--v7-ink);
}

.v7-hero-glow {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: -1;
  width: min(1150px, 155%);
  height: 140%;
  transform: translate(-50%, -50%);
  background: radial-gradient(
    ellipse 55% 42% at 50% 50%,
    rgba(246, 243, 236, 0.9) 0%,
    rgba(246, 243, 236, 0.62) 30%,
    rgba(246, 243, 236, 0.28) 54%,
    rgba(246, 243, 236, 0) 76%
  );
  filter: blur(36px);
  pointer-events: none;
}

.v7-hero-hairline {
  display: block;
  width: 64px;
  height: 1px;
  margin: 0 auto 2px;
  background: linear-gradient(90deg, transparent, var(--v7-gold), transparent);
  opacity: 0.85;
}

.v7-eyebrow {
  justify-self: center;
  margin: 0 auto;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--v7-gold);
}

.v7-hero-title {
  /* v12: text-wrap:balance (from the base h1/h2/h3 rule) can render this
     box narrower than the fully-stretched flex width it gets inside
     .v7-hero-copy; margin-inline:auto re-centers whatever width the
     balance algorithm settles on, matching the eyebrow/sub above and
     below it instead of leaving it flush at the flex-start edge. */
  margin-inline: auto;
  font-size: clamp(4rem, 10.5vw, 10rem);
  line-height: 0.96;
  color: var(--v7-ink);
  text-shadow: 0 2px 30px rgba(246, 243, 236, 0.6);
}

.v7-hero-sub {
  max-width: 46ch;
  margin: 0 auto;
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  line-height: 1.6;
  color: var(--v7-ink);
  text-shadow: 0 2px 22px rgba(246, 243, 236, 0.65);
}

.v7-hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 6px;
}

.v7-hero-signature {
  margin: 10px auto 0;
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums;
  color: var(--v7-ink-62);
  text-shadow: 0 2px 16px rgba(246, 243, 236, 0.6);
}

.v7-btn {
  min-height: 52px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* v19: padding aligned to .sp-btn's 28px (subpages.css) — was 26px here,
     a one-off drift between the two otherwise-identical button primitives.
     28px picked as the canon since it's already used in more places
     (every subpage button). See docs/v19-fit-finish-spec.md. */
  padding: 0 28px;
  border-radius: 999px;
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  border: 1px solid transparent;
  transition:
    transform 220ms var(--v7-ease-out),
    box-shadow 220ms var(--v7-ease-out),
    background-color 220ms var(--v7-ease-out);
}

.v7-btn:hover {
  transform: translateY(-3px);
}

.v7-btn:active {
  transform: scale(0.98);
}

.v7-btn-dark {
  color: var(--v7-paper);
  background:
    radial-gradient(circle at 18% 0%, rgba(255, 255, 255, 0.16), transparent 42%),
    var(--v7-ink);
  box-shadow: 0 16px 34px rgba(13, 20, 33, 0.22);
}

.v7-btn-glass {
  --mx: 50%;
  --my: 50%;
  --v7-glow-a: 0;
  color: var(--v7-ink);
  border-color: rgba(13, 20, 33, 0.12);
  background:
    radial-gradient(circle at var(--mx) var(--my), rgba(255, 255, 255, var(--v7-glow-a)), transparent 40%),
    linear-gradient(145deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.2));
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
}

@media (hover: hover) and (pointer: fine) {
  .v7-btn-glass:hover,
  .v7-btn-glass.is-gliding {
    --v7-glow-a: 0.85;
  }
}

/* ---------- Film chapter cards (transparent flow spacers) ---------- */
.v10-film-chapter {
  position: relative;
  height: 95vh;
  background: transparent;
}

/* Per-chapter heights — tuned so each film second gets roughly 60-90px of
   scroll at a ~900px viewport (desktop acceptance height), per spec. */
.v10-film-chapter[data-film-start="0"] { height: 95vh; }
.v10-film-chapter[data-film-start="10.08"] { height: 48vh; }
.v10-film-chapter[data-film-start="15.1"] { height: 48vh; }
.v10-film-chapter[data-film-start="20.2"] { height: 48vh; }

.v9-drive-card {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 3;
  isolation: isolate;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: max-content;
  max-width: min(90vw, 620px);
  opacity: 0;
  text-align: center;
  pointer-events: none;
}

.v9-drive-card::before {
  content: "";
  position: absolute;
  inset: -34px -70px;
  z-index: -1;
  border-radius: 999px;
  background: radial-gradient(
    ellipse 62% 64% at 50% 50%,
    rgba(246, 243, 236, 0.88) 0%,
    rgba(246, 243, 236, 0.52) 42%,
    rgba(246, 243, 236, 0) 76%
  );
  filter: blur(22px);
  pointer-events: none;
}

.v9-drive-eyebrow {
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--v7-gold);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 3px rgba(13, 20, 33, 0.6), 0 0 10px rgba(13, 20, 33, 0.35);
}

.v9-drive-line {
  margin: 0;
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.6rem, 2.6vw, 2.6rem);
  line-height: 1.3;
  letter-spacing: 0.01em;
  color: rgba(13, 20, 33, 0.7);
  text-wrap: balance;
}

.v9-drive-card--teal-glow::before {
  background: radial-gradient(
    ellipse 62% 64% at 50% 50%,
    rgba(11, 33, 38, 0.72) 0%,
    rgba(15, 45, 50, 0.4) 42%,
    rgba(15, 45, 50, 0) 78%
  );
}

.v9-drive-card--teal-glow .v9-drive-line {
  color: rgba(246, 243, 236, 0.92);
}

.v9-drive-card--dark-glow::before {
  background: radial-gradient(
    ellipse 62% 64% at 50% 50%,
    rgba(7, 16, 32, 0.6) 0%,
    rgba(7, 16, 32, 0.32) 46%,
    rgba(7, 16, 32, 0) 78%
  );
}

.v9-drive-card--dark-glow .v9-drive-line {
  color: rgba(246, 243, 236, 0.94);
}

/* ---------- Frosted-glass rooms (range / ventures / night / principles),
   TRANSLUCENT body over a backdrop blur so the film's light (and its
   frame-to-frame color shift as the stage moves between hills/tunnel/arch/
   home) keeps bleeding through the whole time a room is on screen.
   Opacity per room is the contrast lever: each room's rgba alpha below is
   the value that survived measuring worst-case contrast (body text over the
   brightest film still vs the darkest) at WCAG AA (4.5:1) — see
   docs/v15-frosted-rooms-spec.md and docs/v21-floating-panels-spec.md for
   the measured numbers. Raise a room's alpha (never remove blur) if a
   future asset change regresses contrast.
   v17 governed this as a "frosted wall" pattern: full-bleed bands, feathered
   top mask. v21 (founder direction): the rooms still read as full-width
   solid-feeling fields that hide the journey film at the edges. Retired the
   feathered-top-band entirely and converted every content room into a
   CONTAINED FLOATING GLASS PANEL — centered, rounded, with the moving film
   visible on every side (comfortable side margins, generous vertical gaps
   between consecutive panels) instead of a wall the film disappears behind.
   Night + principles opt back INTO a real glass material here too (their own
   dark/slate variant, set on their own selectors further down this file) —
   see docs/v21-floating-panels-spec.md. Since a panel no longer spans the
   viewport, the old top-feather mask (which existed to blend a full-bleed
   band's leading edge into the stage) has nothing left to do; the reveal is
   now a real entrance transition on the panel itself (rise + fade,
   landing-v10.js), not a mask blend. */
.landing-v7 .v10-room {
  position: relative;
  z-index: 1;
  width: min(1280px, 90vw);
  margin: clamp(56px, 8vw, 112px) auto;
  border-radius: var(--v7-r-panel);
  overflow: hidden;
  border: 1px solid rgba(201, 162, 87, 0.24);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 8px 24px rgba(13, 20, 33, 0.1),
    0 48px 100px rgba(13, 20, 33, 0.26);
}

/* Frosted-glass baseline: blur(26px) + slight saturation lift so the stage's
   color keeps reading through instead of turning to gray mush. Touch
   devices (iPad/phone — see the perf-gate media query further down) get a
   no-blur, higher-opacity fallback instead: continuity still improves
   (the tint bleeds and shifts) but the expensive per-frame blur-over-video
   compositing cost drops to near zero. Night + principles now share this
   same blur baseline (v21) — their own touch fallback is added alongside
   range/ventures' in the perf-gate media query further down. */
.landing-v7 .v10-room {
  backdrop-filter: blur(26px) saturate(1.12);
  -webkit-backdrop-filter: blur(26px) saturate(1.12);
}

/* v21: mobile panels go near-full-width (16px side margins) with a slightly
   tighter radius — the "contained panel" language still holds at phone
   width, just with less side margin than the ≥5vw desktop band affords. */
@media (max-width: 860px) {
  .landing-v7 .v10-room {
    width: calc(100% - 32px);
    margin: 32px auto;
    border-radius: var(--v7-r-panel-mobile);
  }
}

/* ---------- v15: breathing gap — a transparent flow spacer inserted only
   where two rooms would otherwise butt directly against each other with no
   film chapter between them (today: range -> ventures). Lets the journey
   film reassert at full clarity (no blur, no tint) between chapters instead
   of one frosted room handing off straight into the next. ---------- */
.v10-breathing-gap {
  position: relative;
  height: 35vh;
  background: transparent;
}

@media (max-width: 860px) {
  .v10-breathing-gap {
    height: 22vh;
  }
}

/* ---------- Beat 2/3: The range ---------- */
.v7-range {
  /* v21: interior padding is symmetric on all sides now (was vertical-only,
     with horizontal centering delegated to .v7-range-inner's own max-width)
     — the room itself is the panel now, so it owns its own inset on every
     edge. */
  padding: clamp(40px, 6vw, 96px);
  /* v15: frosted paper (was solid var(--v7-paper)), alpha 0.84.
     v20: founder feedback — the range cards read as "flat opaque ivory,"
     not glass, because the ROOM behind them was nearly opaque paper: a
     translucent card over a 0.84-alpha wash still composites to something
     close to solid ivory, so there was nothing moving to frost against.
     Dropped to 0.5 so the journey film's motion/color reads through the
     room itself; the cards below now carry their own full glass recipe
     (translucent + blur24 + saturate1.15) to do the actual "frosting," and
     the section header copy got its own measured-sufficient contrast at
     this alpha (see docs/v20-glass-consistency-spec.md). Ventures is left
     at 0.84 — not in this pass's scope; its stage panel gets the glass
     treatment directly instead (see .v10-stage-panel-part below). */
  background: rgba(246, 243, 236, 0.5);
  scroll-margin-top: 100px;
}

.v7-range-inner {
  position: relative;
  z-index: 1;
  /* v21: was min(1240px, 92vw) — a viewport-relative width made sense when
     the room itself spanned the viewport; now the room is a padded panel
     with its own inset, so the inner wrapper just fills the panel's content
     box (100%), capped so it doesn't sprawl on the largest panel width. */
  width: 100%;
  max-width: 1160px;
  margin: 0 auto;
}

.v7-range-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(20px, 4vw, 48px);
  margin: 0 auto clamp(48px, 6vw, 80px);
}

.landing-v7 .v7-range-meta {
  flex: none;
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--v7-gold);
  padding-bottom: 6px;
}

.landing-v7 .v7-range-intro {
  max-width: 640px;
  margin: 0 0 0 auto;
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-size: clamp(1.4rem, 2.4vw, 2rem);
  font-weight: 350;
  line-height: 1.3;
  text-align: right;
  color: var(--v7-ink);
}

/* ---------- v12: unified card anatomy (Homes / Apps / Systems) — one card
   structure, three data instances. Replaces the old v7-lane system (photo /
   tilted screenshot / dark crop) with a single card + media-field
   treatment so all three read as one family.
   v17: the engraved-bookplate emblems were swapped for glass-render plates
   (glass-homes / glass-apps / glass-night) — see docs/v17-glass-pass-spec.md.
   The renders each carry their own background (ivory / warm gradient /
   slate-to-ivory), so the field goes FULL-BLEED (object-fit: cover, no more
   flat-ivory `background: var(--v7-paper)` field) instead of contain-on-
   ivory — the render's own backdrop IS the field now. Field size, radius,
   and shadow stay identical across all three so they still read as one
   family despite the differing background tones. */
.v7-lane-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  align-items: stretch;
}

/* v20: true glass panels — was a flat, opaque var(--v7-paper) fill (no
   backdrop-filter at all), which read as "flat opaque ivory" against the
   now-lighter room (see .v7-range above). Reused the .sp-card recipe
   (src/subpages.css) verbatim rather than inventing a new one: translucent
   paper + blur24/saturate1.15 (a touch stronger than .sp-card's 20/1.3,
   since this card sits over moving video rather than a static page and
   wants a slightly firmer frost), gold-tinted border, inset top highlight.
   The media field (full-bleed glass renders) is untouched by this — only
   the card's OWN body material changes. */
.v7-lane {
  --mx: 50%;
  --my: 50%;
  --v7-glow-a: 0;
  --v7-border-a: 0.22;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 28px 26px 30px;
  border-radius: var(--v7-r-outer);
  border: 1px solid rgba(201, 162, 87, var(--v7-border-a));
  background:
    radial-gradient(circle at var(--mx) var(--my), rgba(255, 255, 255, var(--v7-glow-a)), transparent 42%),
    rgba(246, 243, 236, 0.68);
  backdrop-filter: blur(24px) saturate(1.15);
  -webkit-backdrop-filter: blur(24px) saturate(1.15);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 26px 54px rgba(13, 20, 33, 0.1);
  transition:
    box-shadow 220ms var(--v7-ease-out),
    border-color 260ms var(--v7-ease-out),
    transform 260ms var(--v7-ease-out);
}

@media (hover: hover) and (pointer: fine) {
  .v7-lane:hover,
  .v7-lane.is-gliding {
    --v7-glow-a: 0.7;
    --v7-border-a: 0.55;
    transform: translateY(-6px);
    /* v20: added a soft gold outer glow (the new third box-shadow layer)
       alongside the existing lift + inset highlight — brief-specified
       "hover: lift + sheen sweep (exists) + border glow." */
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.65),
      0 34px 70px rgba(13, 20, 33, 0.18),
      0 0 0 1px rgba(201, 162, 87, 0.28),
      0 0 36px rgba(201, 162, 87, 0.22);
  }

  .v7-lane:hover .v7-lane-media img,
  .v7-lane.is-gliding .v7-lane-media img {
    transform: scale(1.05);
  }

  .v7-lane:hover .v7-lane-media::after,
  .v7-lane.is-gliding .v7-lane-media::after {
    transform: translateX(55%);
    opacity: 1;
  }

  .v7-lane:hover .v7-lane-arrow,
  .v7-lane.is-gliding .v7-lane-arrow {
    transform: translateX(6px);
  }
}

.v7-lane:active {
  transform: scale(0.98) !important;
}

.v7-lane-index {
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-size: 1.1rem;
  font-weight: 300;
  font-variant-numeric: tabular-nums;
  color: var(--v7-gold);
}

.v7-lane-media {
  position: relative;
  isolation: isolate;
  height: 240px;
  border-radius: var(--v7-r-inner);
  overflow: hidden;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.16),
    inset 0 -46px 70px -34px rgba(13, 20, 33, 0.3);
}

.v7-lane-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms var(--v7-ease-out);
}

/* v17: specular sheen sweep — a soft diagonal highlight that travels across
   the glass render on hover, reading as a reflection catching the light.
   transform/opacity only. Timing matches this element's existing 700ms
   hover-reveal precedent (the image scale above), not the generic 300ms
   micro-motion rule — that rule governs UI chrome, this is a deliberate,
   slower media-hover reveal, the same class of exception the constitution
   already grants scroll-driven scrubs. */
.v7-lane-media::after {
  content: "";
  position: absolute;
  inset: -30% -70%;
  z-index: 1;
  background: linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, 0.55) 50%, transparent 58%);
  transform: translateX(-55%);
  opacity: 0;
  pointer-events: none;
  transition: transform 750ms var(--v7-ease-out), opacity 200ms ease;
}

.v7-lane-copy {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 10px;
}

.v7-lane-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--v7-gold);
}

.v7-lane-title-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.v7-lane-copy h3 {
  font-size: clamp(1.5rem, 2vw, 1.9rem);
}

.v7-lane-arrow {
  font-size: 1.1rem;
  color: var(--v7-gold);
  transition: transform 260ms var(--v7-ease-out);
}

.v7-lane-copy p {
  font-size: 0.98rem;
  line-height: 1.6;
  color: var(--v7-ink-72);
}

/* ---------- Beat 4: Ventures — instrument stage (v17) ----------
   Founder feedback on the v12 hover-thumbnail rack: it read as "lazy" and
   the thumbnail was too small to actually see the product. Replaced with a
   split stage: LEFT is a plain list of the five entries (number / name /
   essence — no chip, no thumb; the chip moved into the stage). RIGHT is
   one persistent glass panel that always shows the ACTIVE app's real
   -altai screen at a size big enough to read, over that app's atmosphere
   wash (the same slate/teal/honey/night/felt identities the old rack
   used), with its chip and a real "Visit page" link.
   DRY trick: each `.v10-stage-item` <article> in index.html holds BOTH its
   row and its panel — the copy is authored once. At >=861px the article is
   unwrapped (`display: contents`, see the media query below) so its two
   children become independent CSS Grid items of `.v10-stage-wrap`: the row
   falls into the left column in its own row, and the panel is explicitly
   placed into the SAME right-column cell as the other four (grid allows
   co-located items; they simply overlap in DOM order) — `data-active`
   drives an opacity crossfade to decide which one is on top. Below 861px
   `.v10-stage-item` is just a normal block, so the same two children stack
   as one full card — the "stacked cards, large screen" mobile spec is a
   direct consequence of the layout switch, not separate markup. */
.v7-ventures {
  position: relative;
  z-index: 1;
  /* v15: frosted paper (was solid var(--v7-paper)) — matches the range
     alpha; both are light "paper" rooms sitting over the same held frame. */
  background: rgba(246, 243, 236, 0.84);
  /* v21: symmetric panel inset, same rationale as .v7-range above. */
  padding: clamp(40px, 6vw, 96px);
}

.v7-ventures-frame {
  /* v21: was min(1320px, calc(100vw - 48px)) — viewport-relative; now fills
     the panel's own content box. */
  width: 100%;
  max-width: 1160px;
  margin: 0 auto;
}

.landing-v7 .v7-ventures-intro {
  max-width: 560px;
  margin: 0 auto clamp(36px, 5vw, 56px);
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-size: clamp(1.4rem, 2.4vw, 2rem);
  font-weight: 350;
  line-height: 1.3;
  text-align: center;
}

.v10-stage-frame {
  position: relative;
  z-index: 1;
  /* v21: was min(1320px, calc(100vw - 48px)); see .v7-ventures-frame above. */
  width: 100%;
  max-width: 1160px;
  margin: 0 auto;
}

.v10-stage-wrap {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Mobile-first base: each item is a self-contained card (row text, then
   its panel) stacked in normal flow — the ">=861px" media query below is
   what turns this into the split desktop stage; nothing here is mobile-
   *specific* styling bolted on afterward. */
.v10-stage-item {
  padding: 22px;
  border-radius: var(--v7-r-outer);
  background: var(--v7-paper);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 20px 40px rgba(13, 20, 33, 0.1);
}

.v10-stage-row-part {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  padding: 0 0 16px;
  border: 0;
  background: none;
  text-align: left;
  color: var(--v7-ink);
  font: inherit;
  cursor: default;
}

.v10-stage-num {
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: var(--v7-gold);
}

.v10-stage-name {
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-weight: 400;
  font-size: clamp(1.3rem, 2vw, 1.7rem);
  letter-spacing: -0.01em;
  transition: opacity 220ms var(--v7-ease-out);
}

.v10-stage-essence {
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: 0.98rem;
  line-height: 1.4;
  color: var(--v7-ink-72);
  transition: opacity 220ms var(--v7-ease-out);
}

/* v20: was a bare border+shadow with no background/backdrop-filter at
   all — the per-app ".v10-stage-wash" gradient (below) was the ONLY
   visible material, and at its old near-opaque alpha (0.88-0.98) it read
   as a flat solid color wash (founder: "boring solid background, missing
   glass"). Added the panel's own translucent glass body + blur (matching
   the app-hero stacking language exactly), and gave every wash the exact
   same lowered alpha values already tuned "by eye against real captures"
   in src/subpages.css's .sp-scene-* (v18 app-hero pass) — reused verbatim
   rather than re-tuning, since these are the identical five app moods. */
.v10-stage-panel-part {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 55vw;
  border-radius: var(--v7-r-inner);
  overflow: hidden;
  background: rgba(246, 243, 236, 0.16);
  backdrop-filter: blur(20px) saturate(1.3);
  -webkit-backdrop-filter: blur(20px) saturate(1.3);
  border: 1px solid rgba(201, 162, 87, 0.3);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.3),
    0 24px 48px rgba(13, 20, 33, 0.18);
}

/* ---------- v20: aurora backdrop — assets/v9/aurora-loop.mp4, tinted per
   app with the SAME filter/opacity values as that app's own detail-page
   hero (src/subpages.css .sp-app-hero-aurora-video--*). Sits behind the
   wash and the device, inside the panel's own rounded clip (overflow:
   hidden above), so it plays as the panel's atmosphere rather than a
   room-wide layer. Resilience (poster fallback / reduced-motion static /
   IO-driven play-pause) is wired in landing-v10.js; only the ACTIVE
   panel's video is ever playing (JS pauses the rest), so switching apps
   never runs more than one video at once regardless of viewport. ---------- */
.v10-stage-aurora {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
}

.v10-stage-aurora-video,
.v10-stage-aurora-fallback {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.4;
}

.v10-stage-aurora-fallback {
  display: none;
}

.v10-stage-aurora.is-static .v10-stage-aurora-video {
  display: none;
}

.v10-stage-aurora.is-static .v10-stage-aurora-fallback {
  display: block;
}

@media (prefers-reduced-motion: reduce), (prefers-reduced-data: reduce) {
  .v10-stage-aurora-video {
    display: none;
  }

  .v10-stage-aurora-fallback {
    display: block;
  }
}

.v10-stage-aurora-video--slate,
.v10-stage-aurora-fallback--slate {
  filter: hue-rotate(200deg);
}

.v10-stage-aurora-video--teal,
.v10-stage-aurora-fallback--teal {
  filter: hue-rotate(140deg);
}

.v10-stage-aurora-video--honey,
.v10-stage-aurora-fallback--honey {
  filter: saturate(1.2);
}

.v10-stage-aurora-video--night,
.v10-stage-aurora-fallback--night {
  filter: hue-rotate(190deg) brightness(0.5);
  opacity: 0.38;
}

.v10-stage-aurora-video--felt,
.v10-stage-aurora-fallback--felt {
  filter: hue-rotate(100deg) brightness(0.45);
}

.v10-stage-wash {
  position: absolute;
  inset: 0;
  z-index: 0;
}

/* v20: alpha values match src/subpages.css .sp-scene-* exactly (same app,
   same mood) — was 0.88-0.98 per stop, opaque enough to hide the aurora
   entirely; now 0.55-0.78, so the moving film carries the atmosphere and
   the wash only tints it. */
.v10-stage-panel-part--slate .v10-stage-wash {
  background: linear-gradient(160deg, rgba(219, 210, 238, 0.55), rgba(242, 238, 249, 0.72));
}

.v10-stage-panel-part--teal .v10-stage-wash {
  background: linear-gradient(150deg, rgba(127, 168, 184, 0.32), rgba(233, 237, 242, 0.62) 55%, rgba(246, 243, 236, 0.78));
}

.v10-stage-panel-part--honey .v10-stage-wash {
  background: linear-gradient(150deg, rgba(214, 168, 74, 0.36), rgba(250, 233, 205, 0.62) 42%, rgba(252, 227, 220, 0.66) 72%, rgba(248, 238, 232, 0.78));
}

.v10-stage-panel-part--night .v10-stage-wash {
  background:
    radial-gradient(ellipse 70% 45% at 18% 82%, rgba(45, 138, 150, 0.22), transparent 60%),
    linear-gradient(180deg, rgba(7, 16, 32, 0.62), rgba(7, 16, 32, 0.78));
}

.v10-stage-panel-part--felt .v10-stage-wash {
  background: radial-gradient(ellipse 80% 70% at 50% 28%, rgba(28, 56, 44, 0.6), rgba(7, 12, 11, 0.75));
}

.v10-stage-device {
  position: relative;
  z-index: 1;
  height: 55vw;
  max-height: 420px;
  aspect-ratio: 704 / 1529;
  border-radius: 26px;
  overflow: hidden;
  border: 3px solid var(--v7-ink);
  box-shadow:
    0 2px 0 rgba(255, 255, 255, 0.5) inset,
    0 30px 60px rgba(13, 20, 33, 0.3);
}

.v10-stage-device img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.v10-stage-footer {
  position: absolute;
  z-index: 2;
  left: 18px;
  right: 18px;
  bottom: 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.v10-stage-chip {
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: 999px;
  color: var(--v7-ink);
  background: rgba(246, 243, 236, 0.88);
  border: 1px solid rgba(13, 20, 33, 0.08);
  white-space: nowrap;
}

.v10-stage-cta {
  min-height: 40px;
  padding: 0 18px;
  font-size: 0.85rem;
}

.v10-stage-cta:focus-visible,
.v10-stage-row-part:focus-visible {
  outline: 2px solid var(--v7-gold);
  outline-offset: 2px;
}

/* ---------- Desktop stage: the split instrument layout ----------
   Turns the mobile-first stacked cards above into a two-column grid: a
   plain list on the left, one shared cell on the right where all five
   panels overlap (opacity-crossfaded by `data-active`). Section height is
   capped at min(52vh, 560px) so it — plus the heading — comfortably stays
   under 100vh on common desktop sizes. */
@media (min-width: 861px) {
  .v10-stage-wrap {
    display: grid;
    grid-template-columns: minmax(280px, 380px) 1fr;
    grid-template-rows: repeat(5, 1fr);
    gap: 0 clamp(24px, 3vw, 48px);
    height: min(52vh, 560px);
    border-top: 1px solid rgba(13, 20, 33, 0.14);
  }

  /* Unwraps the <article> so its two children (row + panel) become
     independent grid items of .v10-stage-wrap instead of one nested box —
     see the file-level comment above for why this keeps the copy DRY. */
  .v10-stage-item {
    display: contents;
  }

  .v10-stage-row-part {
    grid-column: 1;
    justify-content: center;
    height: 100%;
    padding: 0 6px;
    border-bottom: 1px solid rgba(13, 20, 33, 0.14);
    cursor: pointer;
    transition: padding-left 280ms var(--v7-ease-out);
  }

  .v10-stage-row-part:hover,
  .v10-stage-row-part:focus-visible,
  .v10-stage-row-part[aria-selected="true"] {
    padding-left: 20px;
  }

  .v10-stage-row-part:not([aria-selected="true"]) .v10-stage-name,
  .v10-stage-row-part:not([aria-selected="true"]) .v10-stage-essence {
    opacity: 0.6;
  }

  /* Explicit placement (not auto-flow): every panel targets the SAME cell
     (col 2, spanning all 5 rows = the panel's full height), so the five
     overlap instead of stacking — only `data-active` + opacity decide
     which one is visible on top. */
  .v10-stage-panel-part {
    grid-column: 2;
    grid-row: 1 / -1;
    min-height: 0;
    border-radius: var(--v7-r-outer);
    opacity: 0;
    z-index: 1;
    transition: opacity 260ms ease;
    pointer-events: none;
  }

  .v10-stage-panel-part[data-active="true"] {
    opacity: 1;
    z-index: 2;
    pointer-events: auto;
  }

  .v10-stage-device {
    /* v20: was 85% — with the panel now showing a real aurora backdrop
       behind it, 85% left almost no visible margin for that film to read.
       78% sits in the brief's specified ~75-80% band and leaves a clear
       aurora-lit edge around the device on all sides. */
    height: 78%;
    max-height: none;
  }
}

/* ---------- Beat 5: Night passage ----------
   v17: founder call — the tunnel film is already near-black, so the v15
   frosted wash + blur was muddying motion that should read crisp. Removed
   entirely (background now transparent; backdrop-filter cancelled via the
   compound override further down, same cascade-safety pattern v15 used for
   its perf fallback — see docs/v17-glass-pass-spec.md). Contrast now comes
   from ONE local vignette (`::before`) sized to sit behind the text column
   only, not a room-wide wash — the film reads full clarity everywhere else. */
.v7-night {
  scroll-margin-top: 100px;
  /* v21: symmetric panel inset — was clamp(90px,16vw,170px) 24px (vertical-
     heavy, thin horizontal gutter), sized for a full-bleed room. Now a
     contained panel with the same clamp on every edge as the other three
     rooms. */
  padding: clamp(40px, 6vw, 96px);
}

/* v21: retired. This local vignette existed to punch contrast into a
   full-bleed room without darkening the whole viewport (v17 rationale:
   the tunnel footage ran edge-to-edge behind it). Now that .v7-night is a
   contained glass panel (see .v7-night's own dark-glass background further
   down this file), the panel's own tint already covers its whole area
   uniformly — a second, narrower vignette on top of that would just double
   up the darkening unevenly. See docs/v21-floating-panels-spec.md. */
.v7-night::before {
  display: none;
}

.v7-night-copy {
  position: relative;
  z-index: 1;
  min-height: 56vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 20px;
  width: min(760px, 100%);
  margin: 0 auto;
  color: var(--v7-ivory-96);
}

.v7-night-copy h2 {
  font-size: clamp(2.2rem, 4.5vw, 4rem);
  color: var(--v7-ivory-96);
}

.v7-night-body {
  max-width: 46ch;
  font-size: clamp(1rem, 1.4vw, 1.15rem);
  line-height: 1.65;
  color: var(--v7-ivory-60);
}

.v7-capabilities {
  display: grid;
  gap: 12px;
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}

.v7-capability {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 0.98rem;
  font-weight: 500;
  color: var(--v7-ivory-96);
}

.v7-hairline {
  flex: none;
  width: 24px;
  height: 1px;
  background: linear-gradient(90deg, var(--v7-gold), var(--v7-teal));
  transform: scaleX(0);
  transform-origin: left center;
}

.v7-dot {
  width: 6px;
  height: 6px;
  flex: none;
  border-radius: 999px;
  background: var(--v7-teal);
  box-shadow: 0 0 8px 1px rgba(127, 168, 184, 0.5);
}

.v7-capability:nth-child(2) .v7-dot {
  background: var(--v7-gold);
  box-shadow: 0 0 8px 1px rgba(201, 162, 87, 0.5);
}

/* ---------- Beat 6: Principles ----------
   v21: this room is a contained floating glass panel now (dark/slate
   variant, set on .v7-principles further down this file), not a full-bleed
   band — see docs/v21-floating-panels-spec.md. The v17 local vignette
   (.v9-principles-scrim) that used to carry contrast on its own is retired
   in favor of the panel's own uniform tint (same call as .v7-night above). */
.v7-principles {
  overflow: hidden;
  /* v21: symmetric panel inset, same rationale as the other three rooms. */
  padding: clamp(40px, 6vw, 96px);
  color: var(--v7-ivory-96);
  scroll-margin-top: 100px;
}

/* v21: retired — see the file-level comment on .v7-principles above. */
.v9-principles-scrim {
  display: none;
}

.landing-v7 .v7-principles-title {
  position: relative;
  z-index: 2;
  width: min(900px, 100%);
  margin: 0 auto clamp(50px, 7vw, 90px);
  font-size: clamp(2.2rem, 4.5vw, 4rem);
  color: var(--v7-ivory-96);
  text-align: center;
}

.v7-principle-row {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 90px minmax(0, 0.7fr) minmax(0, 1fr);
  align-items: baseline;
  gap: clamp(16px, 3vw, 40px);
  width: min(1080px, 100%);
  margin: 0 auto;
  padding: clamp(28px, 4vw, 42px) 0;
  overflow: clip;
}

.v7-principle-row:last-child {
  border-bottom: 1px solid rgba(246, 243, 236, 0.16);
}

.v7-principle-rule {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: rgba(246, 243, 236, 0.16);
  transform: scaleX(0);
  transform-origin: left center;
}

.v7-principle-ghost {
  position: absolute;
  top: 50%;
  right: 0;
  z-index: 0;
  transform: translateY(-42%);
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-size: 18vw;
  font-weight: 300;
  line-height: 1;
  color: var(--v7-ivory-96);
  opacity: 0.04;
  pointer-events: none;
  white-space: nowrap;
}

.v7-principle-num,
.v7-principle-row h3,
.v7-principle-row p {
  position: relative;
  z-index: 1;
}

.v7-principle-num {
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--v7-gold);
}

.v7-principle-row h3 {
  font-size: clamp(1.4rem, 2.2vw, 1.9rem);
  color: var(--v7-ivory-96);
}

.v7-principle-row p {
  max-width: 46ch;
  font-size: 1rem;
  line-height: 1.65;
  color: var(--v7-ivory-60);
}

/* ---------- Beat 7: Closing (transparent overlay over the held final frame) ---------- */
.v7-closing {
  position: relative;
  min-height: 100svh;
  overflow: hidden;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(80px, 14vh, 140px) 24px clamp(50px, 8vh, 80px);
  gap: clamp(48px, 8vh, 90px);
}

.v7-closing-scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(ellipse at 50% 30%, rgba(7, 16, 32, 0.22), transparent 55%),
    linear-gradient(180deg, rgba(7, 16, 32, 0.5) 0%, rgba(7, 16, 32, 0.3) 30%, rgba(7, 16, 32, 0.62) 100%);
}

.v7-closing-copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 34px;
  text-align: center;
}

.v7-closing-copy h2 {
  font-size: clamp(2.6rem, 6vw, 5rem);
  color: var(--v7-ivory-96);
}

.v7-closing-words {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  row-gap: 0.05em;
  column-gap: 0.28em;
}

.v7-cta-pill {
  --mx: 50%;
  --my: 50%;
  --v7-glow-a: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  padding: 0 32px;
  border-radius: 999px;
  border: 1px solid rgba(201, 162, 87, 0.4);
  color: var(--v7-ink);
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 1rem;
  font-weight: 600;
  background:
    radial-gradient(circle at var(--mx) var(--my), rgba(255, 255, 255, var(--v7-glow-a)), transparent 45%),
    var(--v7-gold);
  box-shadow: 0 20px 46px rgba(7, 16, 32, 0.32);
  transition: box-shadow 220ms var(--v7-ease-out);
  will-change: transform;
}

@media (hover: hover) and (pointer: fine) {
  .v7-cta-pill:hover,
  .v7-cta-pill.is-gliding {
    --v7-glow-a: 0.5;
  }
}

.v7-cta-pill:active {
  transform: scale(0.98);
}

.v7-closing-wordmark {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: clamp(10px, 2vw, 22px);
  opacity: 0.9;
  color: var(--v7-ivory-96);
}

.v7-closing-wordmark img {
  height: clamp(28px, 5vw, 56px);
  width: auto;
}

.v7-closing-wordmark span {
  font-family: "Fraunces", ui-serif, Georgia, serif;
  font-size: clamp(2.2rem, 13.5vw, 14vw);
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1;
  white-space: nowrap;
}

/* ---------- Reduced motion safety ---------- */
@media (prefers-reduced-motion: reduce) {
  .v7-star {
    animation: none;
    opacity: 0.55;
  }

  .v7-grain,
  .v7-hero-fog-back,
  .v7-hero-fog-front,
  .v7-hero-godray,
  .v7-hero-media,
  .v7-night-aurora,
  .v8-cloudshadow {
    animation: none !important;
  }

  .v7-hero-godray {
    opacity: 0.14;
  }

  .v8-birds {
    display: none;
  }
}

/* ---------- Responsive ---------- */
@media (max-width: 1080px) {
  .v7-range-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .landing-v7 .v7-range-intro {
    text-align: left;
    margin: 0;
  }

  .v7-lane-grid {
    grid-template-columns: 1fr;
  }

  .v7-lane-media {
    height: 220px;
  }
}

@media (max-width: 860px) {
  /* Film chapters simplify on mobile: shorter, no curtain concept needed
     since sections were never overlapped in the first place. */
  .v10-film-chapter[data-film-start="0"] { height: 70vh; }
  .v10-film-chapter[data-film-start="10.08"],
  .v10-film-chapter[data-film-start="15.1"],
  .v10-film-chapter[data-film-start="20.2"] { height: 40vh; }
}

@media (max-width: 720px) {
  .v7-hero-copy {
    width: 100%;
    padding: 0 22px clamp(36px, 9vh, 100px);
  }

  .v9-drive-card {
    display: none;
  }

  .v7-hero-actions {
    width: 100%;
    max-width: 340px;
    margin: 6px auto 0;
  }

  .v7-btn {
    width: 100%;
  }

  .v7-principle-row {
    grid-template-columns: 48px 1fr;
  }

  .v7-principle-row p {
    grid-column: 2 / 3;
  }

  .v7-closing-wordmark {
    flex-direction: column;
    gap: 10px;
  }
}

/* ================= Route thread — fixed connective spine ================= */
.v9-route {
  position: fixed;
  top: 0;
  right: 24px;
  bottom: 0;
  width: 2px;
  z-index: 90;
  pointer-events: none;
}

.v9-route-track,
.v9-route-fill {
  position: absolute;
  inset: 0;
  background: var(--v7-gold);
}

.v9-route-track {
  opacity: 0.12;
}

.v9-route-fill {
  opacity: 0.85;
  transform: scaleY(0);
  transform-origin: top center;
}

.v9-route-marker {
  position: absolute;
  left: 50%;
  top: 0;
  width: 8px;
  height: 8px;
  transform: translate(-50%, -50%) rotate(45deg);
  background: var(--v7-gold);
  box-shadow: 0 0 10px 2px rgba(201, 162, 87, 0.5);
}

.v9-route-tick {
  position: absolute;
  left: 50%;
  top: 0;
  width: 6px;
  height: 6px;
  border-radius: 1px;
  transform: translate(-50%, -50%);
  background: var(--v7-gold);
  opacity: 0.65;
}

@media (max-width: 860px) {
  .v9-route {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce), (prefers-reduced-data: reduce) {
  .v9-route {
    display: none;
  }
}

/* ================= v9.5 — Entry gate (preloader) ================= */
.v95-gate {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--v7-paper, #f6f3ec);
  transform: translateY(0);
  filter: blur(0);
  transition:
    transform 600ms cubic-bezier(0.65, 0, 0.35, 1),
    filter 600ms cubic-bezier(0.65, 0, 0.35, 1);
}

.v95-gate[hidden] {
  display: none;
}

.v95-gate.is-leaving {
  transform: translateY(-100%);
  filter: blur(14px);
  mask-image: linear-gradient(to bottom, black 0%, black 78%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, black 0%, black 78%, transparent 100%);
}

.v95-gate-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.v95-gate-mark {
  width: 64px;
  height: auto;
  opacity: 0.9;
}

.v95-gate-coords {
  margin: 0;
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.14em;
  font-variant-numeric: tabular-nums;
  color: var(--v7-ink-62, rgba(13, 20, 33, 0.62));
}

/* ================= v9.5 — Time-of-day hero ================= */
body.v95-hour-dusk .v7-hero-title,
body.v95-hour-dusk .v7-hero-sub,
body.v95-hour-dusk .v7-hero-signature,
body.v95-hour-night .v7-hero-title,
body.v95-hour-night .v7-hero-sub,
body.v95-hour-night .v7-hero-signature {
  color: var(--v7-ivory-96);
  text-shadow: 0 1px 3px rgba(7, 16, 32, 0.85), 0 2px 30px rgba(7, 16, 32, 0.55);
}

body.v95-hour-dusk .v7-hero-signature,
body.v95-hour-night .v7-hero-signature {
  width: max-content;
  max-width: calc(100% - 32px);
  padding: 5px 16px;
  border-radius: 999px;
  background: rgba(7, 16, 32, 0.72);
}

body.v95-hour-dusk .v7-hero-glow,
body.v95-hour-night .v7-hero-glow {
  background:
    radial-gradient(
      ellipse 58% 46% at 50% 42%,
      rgba(13, 20, 33, 0.5) 0%,
      rgba(13, 20, 33, 0.36) 32%,
      rgba(13, 20, 33, 0.16) 58%,
      rgba(13, 20, 33, 0) 78%
    ),
    linear-gradient(
      to bottom,
      rgba(13, 20, 33, 0) 55%,
      rgba(13, 20, 33, 0.3) 78%,
      rgba(13, 20, 33, 0.52) 100%
    );
}

body.v95-hour-night .v7-hero-godray {
  filter: brightness(0.35);
}

body.v95-hour-night .v8-cloudshadow {
  display: none;
}

@media (prefers-reduced-motion: no-preference) {
  body.v95-hour-dusk .v7-hero-media.is-static ~ .v8-towers-wrap,
  body.v95-hour-night .v7-hero-media.is-static ~ .v8-towers-wrap {
    display: block;
  }
}

body.v95-hour-dusk .v8-towers-wrap,
body.v95-hour-night .v8-towers-wrap {
  mask-image: linear-gradient(to bottom, black 0%, black 68%, transparent 80%);
  -webkit-mask-image: linear-gradient(to bottom, black 0%, black 68%, transparent 80%);
}

/* ================= v21: night + principles — dark glass panel =================
   v17 removed background from these two rooms entirely (full-bleed room,
   local vignette only, see the old .v7-night::before / .v9-principles-scrim
   rules above, now retired) because a room-wide wash muddied the near-black
   tunnel/night footage running edge-to-edge behind it. v21 changes what a
   "room" IS: no longer a full-bleed band, but a CONTAINED floating panel
   with film visible on every side — so the concern that drove the v17
   removal (hiding motion across the whole viewport) no longer applies; only
   the panel's own contained area needs the tint, and the film outside it
   stays full clarity regardless of pointer type. Opted back into a real
   glass material — same family as .sp-theme-dark .sp-card
   (src/subpages.css), a slate-tinted translucent surface — using single-
   class selectors (not the .v10-room.v7-night compound the v17 rule used)
   so the touch-device flat-alpha fallback in the perf-fallback tier right
   below this naturally wins on specificity alone, same as range/ventures
   already do — no source-order gymnastics needed. Blur AND the gold-tinted
   border both come for free from the shared .landing-v7 .v10-room rule
   above (that rule's border color already suits a dark panel just as well
   as a light one, so it's left alone rather than duplicated at a
   specificity that couldn't win against it anyway). See
   docs/v21-floating-panels-spec.md for the measured contrast numbers. */
.v7-night,
.v7-principles {
  /* v21: alpha measured against this panel's own worst-case frame — the
     principles panel scrolling over the golden-burst stretch of the film
     left its lowest-contrast body copy (ivory-60 on this tint) at 4.38:1,
     just under the 4.5:1 floor. Raised from 0.66 to 0.74 (see
     docs/v21-floating-panels-spec.md for the measured numbers); night's own
     worst case only improves from an already-passing 5.13:1. */
  background:
    linear-gradient(160deg, rgba(246, 243, 236, 0.1), rgba(246, 243, 236, 0.03)),
    rgba(7, 16, 32, 0.74);
}

/* ================= v15: performance fallback tier =================
   backdrop-filter compositing a blur over a *playing video* stage is
   measurably expensive on touch/mobile GPUs. Gated on `pointer: coarse`
   (touch hardware) rather than `@supports`, because every shipping engine
   here supports backdrop-filter — the problem is cost, not capability.
   Frame-time measurement (rAF sampling across a scripted full-page scroll,
   iPad emulation 1366x1024/isMobile/hasTouch/dsf2) decided this tier ships;
   see docs/v15-frosted-rooms-spec.md for the numbers. Swapping to a flat
   higher-opacity paper (no blur) keeps the continuity win — the stage's
   tint still bleeds through and still shifts room to room — while dropping
   the per-frame blur/compositing cost.
   Deliberately placed last in the cascade AND written with the two-class
   compound selectors below (.v10-room.v7-range, not just .v7-range) so this
   override wins on specificity too, not just source order — a rule this
   important shouldn't depend on staying at the bottom of the file forever. */
@media (pointer: coarse) {
  .landing-v7 .v10-room {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .v10-room.v7-range,
  .v10-room.v7-ventures {
    background: rgba(246, 243, 236, 0.93);
  }

  /* v21: night + principles carry a real blur now too (see the unconditional
     dark-glass rule further down this file) — same "blur over playing
     video" touch cost, same fallback shape: drop the blur (already handled
     by the unqualified .v10-room rule above), raise the flat alpha. This
     compound selector has the same specificity as that unconditional rule,
     so it only wins here because it's physically LATER in the file — the
     unconditional rule is placed before this media block specifically so
     this override, not that one, has the last word for touch devices. */
  .v10-room.v7-night,
  .v10-room.v7-principles {
    background: rgba(7, 16, 32, 0.94);
  }

  /* v20: the range cards and the ventures stage panel are new backdrop-
     filter consumers this pass — same "blur over playing video" cost the
     tier above exists to avoid, just moved one layer down (card/panel
     instead of room). Same fallback shape: drop the blur, raise the flat
     alpha so the card/panel still reads as one solid, legible surface. */
  .v7-lane {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background:
      radial-gradient(circle at var(--mx) var(--my), rgba(255, 255, 255, var(--v7-glow-a)), transparent 42%),
      rgba(246, 243, 236, 0.94);
  }

  .v10-stage-panel-part {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: rgba(246, 243, 236, 0.06);
  }
}

/* ================= v19: universal focus-visible (a11y) =================
   Before this pass, only .v10-stage-cta / .v10-stage-row-part (above) had
   an explicit gold ring — every other interactive element (buttons, links,
   any future role="button"/tabindex custom control) fell back to the
   browser default outline. This rule is deliberately unqualified (no
   class/id prefix) so its specificity stays LOWER than the bespoke rule
   above; where the two overlap the bespoke rule still wins (same visual
   result either way, since both use var(--v7-gold)). Covers everything
   else in one shot. See docs/v19-fit-finish-spec.md. */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--v7-gold);
  outline-offset: 2px;
}
