/* Theme A — Light through glass: beat compositions */

/* Hero — the name lays centred over the glass, dead-centre of the screen */
.hero-lockup {
  position: sticky;
  top: 0;
  height: 100vh;
  /* small viewport height on phones: 100vh is the address-bar-hidden height, so
     with the bar showing the lockup overhangs and shifts as it collapses */
  height: 100svh;
  display: flex;
  flex-direction: column;     /* the name, then the one line under it */
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 var(--gutter);
  will-change: opacity;
}
.hero-lockup .eyebrow { display: block; margin-bottom: 1.8em; }
.hero-lockup .hero-name { white-space: nowrap; font-size: clamp(2.6rem, 8vw, 7rem); }
.hero-lockup .sub { margin: 2em auto 0; color: var(--greige-text); }
@media (max-width: 700px) {
  /* small screens: the name stays ONE line and is sized against the viewport
     HEIGHT (the prism's on-screen size follows vh, not vw) so it always reads
     wider than the stone — extending past it on both sides — while the vw cap
     keeps it inside the narrowest screens */
  .hero-lockup .hero-name {
    white-space: nowrap;
    font-size: min(7.5vh, 15vw);
  }
}

/* The name used to paint at FULL opacity the moment the HTML arrived, and only
   then did theme.js run and hide it for the gentle assemble: measured at
   opacity 1 at 78ms, 0 at 309ms, fading back from 1.2s. That is the flash.
   Hiding it in CSS instead means it is never drawn before the module decides.
   Scoped to html.js, which an inline script in the head sets, so a visitor with
   no JavaScript still reads the name; and theme.js is not the only thing that
   can add a-ready — the inline script arms a timer as a backstop, so a module
   that fails to load cannot leave the hero permanently blank. */
html.js:not(.a-ready) .hero-lockup .eyebrow,
html.js:not(.a-ready) .hero-lockup .hero-name,
html.js:not(.a-ready) .hero-lockup .sub { opacity: 0; }

html.a-ready .hero-lockup .eyebrow,
html.a-ready .hero-lockup .hero-name,
html.a-ready .hero-lockup .sub {
  animation: a-rise 3.6s ease both;   /* a slow, pure FADE, starting sooner and reaching full later */
}
html.a-ready .hero-lockup .sub { animation-delay: 0.25s; }

@keyframes a-rise {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Beats — label left (sticky, from base.css), photo right */
#veloro { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--gutter); }
#veloro .beat-photo {
  position: sticky;
  top: 22vh;
  align-self: start;
  width: min(34vw, 480px);
  aspect-ratio: 4 / 5;
  justify-self: end;
  margin-top: 30vh;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.2s cubic-bezier(0.16, 1, 0.3, 1);
}
#veloro.in .beat-photo { clip-path: inset(0 0 0% 0); }

.beat-label .eyebrow,
.beat-label .section-title,
.beat-label .sub {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.9s ease, transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
.beat-label.in .eyebrow,
.beat-label.in .section-title,
.beat-label.in .sub { opacity: 1; transform: none; }
.beat-label.in .section-title { transition-delay: 0.08s; }
.beat-label.in .sub { transition-delay: 0.18s; }

/* Markers stay quiet; a slow fade is enough */
.marker, .colophon { opacity: 0; transition: opacity 1.1s ease; }
.marker.in, .colophon.in { opacity: 1; }

@media (max-width: 700px) {
  #veloro { grid-template-columns: 1fr; }
  #veloro .beat-photo {
    position: relative;
    top: auto;
    width: 100%;
    margin-top: 8vh;
    justify-self: stretch;
  }
  /* mobile: hero centred, name over the glass — dead-centre like desktop */
  .hero-lockup {
    top: 0;
    left: 0; right: 0;
    margin: 0 auto;
    max-width: none;
    padding: 0 24px;
    text-align: center;
  }
  .hero-lockup .sub { margin-left: auto; margin-right: auto; }
  /* The nav used to be centred here for a site-mark that no longer exists,
     which left the toggle absolutely positioned against a zero-height bar and
     out of line with the Index masthead. It now uses the shared nav rules at
     every width, so name and toggle sit on the same line. */
}

@media (prefers-reduced-motion: reduce) {
  html.a-ready .hero-lockup .eyebrow,
  html.a-ready .hero-lockup .hero-name,
  html.a-ready .hero-lockup .sub { animation: none; }
  .beat-label .eyebrow, .beat-label .section-title, .beat-label .sub,
  #veloro .beat-photo, .marker, .colophon {
    opacity: 1; transform: none; clip-path: none; transition: none;
  }
}

/* two pills per stop: the site's own page first, the venture's site second */
/* font-size 11px so the em margins below resolve exactly as .beat-cta's own
   used to; the reset is (0,3,0) so it beats the (0,2,0) .v-label rules that
   follow, in both the landscape and the portrait block */
.beat-ctas { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 2.4em; font-size: 11px; }
.v-label .beat-ctas .beat-cta, .beat-ctas .beat-cta { margin-top: 0; }
@media (max-width: 360px) { .beat-ctas { gap: 6px; } .beat-ctas .beat-cta { padding: 0.9em 1.15em; letter-spacing: 0.16em; } }
.beat-cta-out { color: var(--greige-text); border-color: rgba(20, 22, 27, 0.18); }
.beat-cta-out:hover { background: none; color: var(--ink); border-color: rgba(20, 22, 27, 0.45); }
/* the finale's quiet row of links: the only static site map on the tour */
.finale-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.4em 1.4em; margin-top: 2.6em; }
.finale-links a { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--greige-text); text-decoration: none; transition: color 0.25s ease; }
.finale-links a:hover { color: var(--ink); }
@media (max-width: 700px) { .finale-links { gap: 0.4em 1.1em; margin-top: 2.2em; } }

/* venture stop CTA */
.beat-cta {
  display: inline-block;
  margin-top: 2.4em;
  padding: 0.95em 1.7em;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  border: 1px solid rgba(20, 22, 27, 0.35);
  border-radius: 999px;
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}
.beat-cta:hover {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
/* a pill with nowhere to go yet — quiet, no hover invite */
.beat-cta-soon { color: var(--greige-text); border-color: rgba(20, 22, 27, 0.18); cursor: default; }
.beat-cta-soon:hover { background: none; color: var(--greige-text); border-color: rgba(20, 22, 27, 0.18); }

/* each stop takes its time */
.theme-a section.beat { min-height: 210vh; }
/* the venture stops hold a little longer — more scroll to pass each one, so the
   text + shard dwell longer (hero keeps its own shorter pacing). Of this, the
   fly-in is ~38% and the rest is a near-flat "sit" where nothing moves. */
.theme-a #veloro, .theme-a #brsts, .theme-a #cbx, .theme-a #apps { min-height: 265vh; }

/* Future — email signup */
.future-sub {
  margin-top: 1.6em;
  max-width: 30em;
  color: var(--greige-text);
}
.signup {
  margin-top: 2.6em;
  max-width: 30em;
  width: 100%;
}
.signup-field {
  display: flex;
  align-items: center;
  gap: 14px;
  border-bottom: 1px solid rgba(20, 22, 27, 0.35);
  padding-bottom: 10px;
  transition: border-color 0.3s ease;
}
.signup-field:focus-within { border-color: var(--ink); }
.signup-input {
  flex: 1;
  border: 0;
  background: transparent;
  font-family: var(--font-display);
  font-weight: 340;
  font-size: clamp(1.2rem, 2vw, 1.6rem);
  color: var(--ink);
  letter-spacing: -0.01em;
}
.signup-input::placeholder { color: var(--greige-text); opacity: 1; }   /* #6E6D66: 4.6:1 on paper; the old 28% ink was ~2:1 */
/* A visible focus indicator, not none. The ring was removed for the look of the
   glass capsule, which left keyboard users with no way to see where they were.
   An inset ink ring reads on the glass without the outline clipping outside it. */
.signup-input:focus { outline: none; }
/* No focus ring on the capsule — Charlie's call, made twice. The field is the
   only interactive element in its section and the caret marks it, so the cost
   is smaller here than it would be in a form of several inputs. */
.signup-btn {
  flex: none;
  padding: 0.85em 1.6em;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  background: transparent;
  border: 1px solid rgba(20, 22, 27, 0.35);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}
.signup-btn:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.signup-note {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--greige-text);
  min-height: 1.4em;
  margin-top: 1.2em;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.signup-note.show { opacity: 1; transform: none; }
.signup.done .signup-field { opacity: 0.4; pointer-events: none; }
/* honeypot: kept in the DOM for bots, removed from view + a11y tree */
.signup-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Future — centered, larger signup that emerges from the shards */
#future {
  align-items: center;
  text-align: center;
}
#future .eyebrow { display: block; }
#future .section-title { margin-top: 0.35em; }
#future .future-sub {
  margin-left: auto;
  margin-right: auto;
  max-width: 34em;
}
#future .signup {
  margin-left: auto;
  margin-right: auto;
  max-width: 40em;
  width: 100%;
  opacity: 0;
  transform: translateY(18px) scale(0.94);
  transition: opacity 1s ease 0.15s, transform 1.2s cubic-bezier(0.16, 1, 0.3, 1) 0.15s;
}
#future.in .signup { opacity: 1; transform: none; }
#future .signup-field {
  gap: 18px;
  padding-bottom: 14px;
  border-bottom-width: 1px;
}
#future .signup-input {
  font-size: clamp(1.5rem, 3vw, 2.4rem);
  text-align: left;
}
#future .signup-btn {
  padding: 1em 2em;
  font-size: 12px;
}
#future .signup-note { text-align: left; }

/* site nav + Index menu now live in /shared/index-menu.css (shared across pages) */

/* ---- Future: the signup lives IN the 3D space, revealed by the zoom-out ---- */
.future-zone {
  position: relative;
  min-height: 200vh;      /* scroll length for the reveal; content is pinned */
  border-top: 0;
}
.future-stage {
  position: fixed;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 var(--gutter);
  opacity: 0;                 /* driven by scroll in theme.js */
  pointer-events: none;
  will-change: opacity;
}
.future-stage .eyebrow { display: block; }
.future-stage .section-title { margin-top: 0.35em; }
.future-sub {
  margin: 1.5em auto 0;
  max-width: 34em;
  color: var(--greige-text);
}
.future-colophon {
  margin-top: 3.4em;
  color: var(--greige-text);
}

/* the form is always visible within the (pinned) stage; the stage fades as a whole */
.future-stage .signup {
  opacity: 1;
  transform: none;
  max-width: 40em;
  margin: 2.6em auto 0;
}

/* ensure the signup shows inside the pinned stage (beats the earlier #future rule) */
#future-stage .signup {
  opacity: 1;
  transform: none;
  transition: none;
  max-width: 40em;
  margin: 2.6em auto 0.5em;
}
#future-stage .signup-field { opacity: 1; pointer-events: auto; }
/* Fallback for browsers without `inert` (see theme.js). The rule above is what
   let an invisible input take clicks over the hero; this withdraws it until the
   finale is actually on screen. */
#future-stage:not(.in-view) .signup-field,
#future-stage:not(.in-view) .signup-input,
#future-stage:not(.in-view) .signup-btn { pointer-events: none; }

/* =========================================================
   Future — the signup emerges from the centre of the shards
   ========================================================= */
.future-stage { perspective: 1200px; }

/* the content group comes FORWARD (scales up from centre) as you scroll in */
.future-core {
  position: relative;
  z-index: 3;                     /* between back shards (1) and front shards (5) */
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  transform: scale(0.42);         /* JS drives this toward 1 */
  transform-origin: center center;
  will-change: transform;
}

/* the form itself, in the SAME glass language as the shards */
#future-stage .signup.glasscard {
  position: relative;
  max-width: 34em;
  width: 100%;
  margin: 2.4em auto 0;
  padding: 1.5em 1.6em;
  border-radius: 22px;
  background:
    /* MOLTEN texture: the same swimming flow-lines the shards carry, as a faint
       diagonal ripple in the glass */
    repeating-linear-gradient(115deg,
      rgba(255,255,255,0) 0px, rgba(255,255,255,0.06) 7px,
      rgba(198,238,228,0.055) 13px, rgba(255,255,255,0) 22px),
    /* body leans very slightly cool-green, matching Molten's transmission tint */
    linear-gradient(135deg, rgba(255,255,255,0.58), rgba(244,250,249,0.4) 55%, rgba(253,255,254,0.52));
  -webkit-backdrop-filter: blur(14px) saturate(1.12);
  backdrop-filter: blur(14px) saturate(1.12);
  border: 1px solid rgba(255,255,255,0.72);
  box-shadow:
    0 22px 54px -26px rgba(60,72,120,0.3),
    inset 0 1px 0 rgba(255,255,255,0.88);
  opacity: 1;
  transform: none;
  transition: none;
}
/* a faint prismatic rim, like a shard edge catching light */
#future-stage .signup.glasscard::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: 22px;
  padding: 1px;
  /* Molten's dispersion palette — cyan → violet → soft green, the hues its
     wider spread throws at the shard edges */
  background: linear-gradient(120deg, rgba(120,215,220,0.7), rgba(175,170,240,0.45), rgba(190,240,215,0.6));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  pointer-events: none;
  opacity: 0.7;
}
#future-stage .signup.glasscard .signup-field {
  border-bottom: 1px solid rgba(20,22,27,0.25);
}
#future-stage .signup.glasscard .signup-input { color: var(--ink); }
/* Selected text in the capsule stayed ink-on-ink and unreadable. The generic
   `input::selection` in base.css was losing twice over: this rule's selector is
   far more specific, and the autofill rule's -webkit-text-fill-color overrides
   ::selection's `color` outright in WebKit. Both have to be answered at this
   specificity, and the autofill state needs its own entry — once Safari marks a
   field autofilled it keeps applying that fill colour. */
#future-stage .signup.glasscard .signup-input::selection,
#future-stage .signup.glasscard .signup-input:-webkit-autofill::selection {
  background: var(--ink) !important;
  color: var(--paper) !important;
  -webkit-text-fill-color: var(--paper) !important;
}
#future-stage .signup.glasscard .signup-input::-moz-selection {
  background: var(--ink); color: var(--paper);
}
#future-stage .signup.glasscard .signup-input::placeholder { color: var(--greige-text); opacity: 1; }
/* glass button — same material */
#future-stage .signup.glasscard .signup-btn {
  color: var(--ink);
  background: linear-gradient(135deg, rgba(255,255,255,0.55), rgba(232,246,242,0.32));
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255,255,255,0.7);
  box-shadow: 0 6px 20px -8px rgba(90,110,180,0.4), inset 0 1px 0 rgba(255,255,255,0.8);
}
#future-stage .signup.glasscard .signup-btn:hover {
  background: var(--ink); color: var(--paper); border-color: var(--ink);
  box-shadow: 0 6px 20px -8px rgba(20,22,30,0.45), 0 0 0 3px rgba(140,220,220,0.22);
}

/* (no screen-fixed decorations here: everything visible at the Future stop is
   either the real WebGL field or world-pinned to it, so all apparent motion
   belongs to the camera) */

/* ---- venture stop labels: placement tracks the shard (framed by ASPECT in
   theme.js) so the two occupy DISJOINT zones — no overlap, no scrim ----
   wide screens (aspect ≥ 1.1): shard is held on the RIGHT, text on the LEFT */
.v-label {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  left: clamp(24px, 5vw, 88px);
  max-width: min(520px, 36vw);   /* right edge stays well left of the shard */
  z-index: 5;
}
/* The headline is sized to its COLUMN, not to the viewport. The generic
   .section-title (6vw) was wider than the 36vw column at every landscape size,
   so "fits<br>like a suit." broke a second time into "fits / like a suit." —
   an orphan on every stop. The vh term keeps the whole label (title, line,
   pill) inside a short window, where it used to run off the bottom. */
.v-label .section-title { font-size: clamp(1.9rem, min(4.6vw, 8.5vh), 4.2rem); }
.v-label .sub { font-size: clamp(0.9rem, min(1.1vw, 2.4vh), 1.05rem); margin-top: 1.3em; }
.v-label .beat-cta { margin-top: 1.9em; }
.v-label .beat-ctas { margin-top: 1.9em; }
/* tall / portrait screens (aspect < 1.125): shard fills the TOP, text sits in a
   clean bottom band — no gradient scrim (the shard never reaches it) */
@media (max-aspect-ratio: 9/8) {
  .v-label {
    top: auto;
    transform: none;
    bottom: 0;
    left: 0;
    right: 0;
    max-width: none;
    padding: 0 clamp(22px, 6vw, 48px) calc(5vh + env(safe-area-inset-bottom));
  }
  /* a compact bottom band — sized against viewport HEIGHT so it doesn't balloon
     on wide-but-short (near-square) screens, and tightened so the shard above
     keeps its clearance */
  .v-label .eyebrow { margin-bottom: 0.9em; }
  .v-label .section-title { font-size: clamp(1.85rem, 5vh, 2.7rem); }
  .v-label .sub { font-size: clamp(0.9rem, 1.9vh, 1rem); max-width: 26em; margin-top: 1em; }
  /* same specificity as the landscape rule above, or that one wins here */
  .v-label .beat-cta { margin-top: 1.15em; }
  .v-label .beat-ctas { margin-top: 1.15em; }
}

/* ---- mobile: future signup fits and stacks ---- */
@media (max-width: 700px) {
  .future-stage { padding: 0 20px; }
  .future-core { width: 100%; max-width: 100%; }
  .future-core .section-title { font-size: clamp(2.4rem, 13vw, 3.6rem); }
  .future-sub { font-size: 0.95rem; max-width: 24em; }
  .future-colophon { font-size: 10px; }
}

/* =========================================================
   Future v2 — content pinned in world space (JS positions it);
   the signup is a compact glass pill, not a big panel
   ========================================================= */
.future-stage { display: block; }         /* the core is absolutely positioned now */
.future-core {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  transform-origin: center center;
  width: min(90vw, 30em);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  will-change: transform, left, top;
}
.future-core .section-title { font-size: clamp(2.2rem, 5.5vw, 3.8rem); }
.future-core .future-sub { font-size: 0.92rem; max-width: 22em; margin-top: 1.2em; }
.future-core .future-colophon { font-size: 9.5px; margin-top: 2.4em; }

/* compact glass pill — the input fills the capsule, the button is a solid cap
   of the SAME height snugged into the right, so the two read as one object */
#future-stage .signup.glasscard {
  display: block;
  max-width: 19em;
  width: 100%;
  margin: 1.6em auto 0;
  padding: 4px;
  border-radius: 999px;
}
#future-stage .signup.glasscard::before { border-radius: 999px; }
#future-stage .signup.glasscard .signup-field {
  flex-direction: row;
  align-items: center;
  gap: 4px;
  height: 42px;
  border-bottom: 0;
  padding-bottom: 0;
}
#future-stage .signup.glasscard .signup-input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0 0.3em 0 1.1em;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.92rem;
  letter-spacing: 0;
  line-height: 1;
  text-align: left;
}
#future-stage .signup.glasscard .signup-btn {
  flex: none;
  height: 100%;
  padding: 0 1.4em;
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  /* a second pane of glass LAID ON the pill: its own frost over the pill's,
     a raised highlight, and a shard-edge glint around its rim */
  position: relative;
  background:
    /* the SAME Molten flow-lines as the capsule, finer so the cap reads denser */
    repeating-linear-gradient(115deg,
      rgba(255,255,255,0) 0px, rgba(255,255,255,0.07) 5px,
      rgba(200,240,232,0.06) 10px, rgba(255,255,255,0) 17px),
    linear-gradient(160deg, rgba(255,255,255,0.86), rgba(246,253,251,0.46) 55%, rgba(255,255,255,0.7));
  -webkit-backdrop-filter: blur(8px) saturate(1.18);
  backdrop-filter: blur(8px) saturate(1.18);
  border: 1px solid rgba(255,255,255,0.9);
  border-radius: 999px;
  box-shadow:
    0 5px 16px -7px rgba(60,70,110,0.45),
    inset 0 1px 0 rgba(255,255,255,0.95),
    inset 0 -6px 12px -8px rgba(120,130,170,0.35);
  transition: background 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}
#future-stage .signup.glasscard .signup-btn::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 999px;
  padding: 1px;
  /* Molten dispersion rim, matching the capsule */
  background: linear-gradient(120deg, rgba(120,215,220,0.6), rgba(175,170,240,0.35), rgba(190,240,215,0.5));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  pointer-events: none;
  opacity: 0.55;
  transition: opacity 0.25s ease;
}
/* hover: fills with ink (the site's button language) so it clearly reads as
   interactive — and the prismatic rim FLARES with a soft cyan halo. It does NOT
   move: the highlight alone carries the state, so nothing shifts under the
   cursor and it can't nudge the pinned capsule. */
#future-stage .signup.glasscard .signup-btn:hover {
  background:
    repeating-linear-gradient(115deg,
      rgba(255,255,255,0) 0px, rgba(255,255,255,0.05) 5px,
      rgba(150,235,225,0.055) 10px, rgba(255,255,255,0) 17px),
    linear-gradient(160deg, rgba(20,22,27,0.96), rgba(30,36,44,0.92));
  box-shadow:
    0 6px 20px -8px rgba(20,22,30,0.45),
    inset 0 1px 0 rgba(255,255,255,0.2),
    0 0 0 3px rgba(140,220,220,0.22);      /* prismatic halo instead of a lift */
  color: var(--paper);
  border-color: rgba(20,22,27,0.55);
}
#future-stage .signup.glasscard .signup-btn:hover::after { opacity: 0.95; }   /* rim flares */
/* the status note sits BELOW the capsule, not inside it — so the pill hugs the
   field instead of ballooning to reserve empty space under the button */
#future-stage .signup-note {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: 0.9em;
  text-align: center;
}

@media (max-width: 700px) {
  #future-stage .signup.glasscard { max-width: 18em; padding: 4px; }
  #future-stage .signup.glasscard .signup-field { flex-direction: row; height: 40px; gap: 4px; }
  #future-stage .signup.glasscard .signup-input { font-size: 0.88rem; padding-left: 0.95em; }
  #future-stage .signup.glasscard .signup-btn { padding: 0 1.15em; }
  .future-core .section-title { font-size: clamp(2rem, 12vw, 3rem); }
}

/* ---- static tour: no JavaScript, or theme.js / WebGL failed ----
   html:not(.js) is a browser with scripts off (the inline script never ran);
   html.tour-static is set by that script when theme.js never reported live.
   Either way there is no camera, so the stops become a plain stack: text
   visible, sections their natural height, no canvas. The signup posts through
   theme.js, so without it the form is hidden rather than left to fail. */
html:not(.js) .stage, html.tour-static .stage { display: none; }
html:not(.js) .theme-a section.beat, html.tour-static .theme-a section.beat,
html:not(.js) .future-zone, html.tour-static .future-zone { min-height: 0 !important; }
html:not(.js) .theme-a section.beat:not(.hero), html.tour-static .theme-a section.beat:not(.hero) {
  padding: 16vh var(--gutter); max-width: 1080px; margin: 0 auto;
}
html:not(.js) .beat-label .eyebrow, html.tour-static .beat-label .eyebrow,
html:not(.js) .beat-label .section-title, html.tour-static .beat-label .section-title,
html:not(.js) .beat-label .sub, html.tour-static .beat-label .sub { opacity: 1; transform: none; }
html:not(.js) .future-stage, html.tour-static .future-stage {
  position: static; opacity: 1; pointer-events: auto; padding: 16vh var(--gutter);
}
/* the id matches the (1,2,0) #future-stage .signup.glasscard rule that sets display */
html:not(.js) #future-stage .signup.glasscard, html.tour-static #future-stage .signup.glasscard { display: none; }
