/* ─────────────────────────────────────────────────────────────────────────
   NOVA SAKI — launch countdown
   Design tokens and layout follow design_handoff_countdown_landing/README.md.
   The planet anchor percentages are measured against the background art;
   if the art is ever re-exported with a different crop, they must be
   re-measured or the clock circles drift off the painted planets.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  --bg:            #070B22;
  --text:          #FFFFFF;
  --text-dim:      #D4DAEE;
  --text-panel:    #DDE2F4;
  --accent:        #A9C4FF;
  --cta-from:      #FFBE8C;
  --cta-to:        #F6A2CB;
  --cta-ink:       #1A1330;

  /* Two serifs doing different jobs: Playfair sets the large titles and panel
     headings, Marcellus is reserved for the wordmark alone. */
  --font-display: 'Playfair Display', Georgia, 'Times New Roman', serif;
  --font-logo:    Marcellus, Georgia, serif;
  --font-ui:      'Instrument Sans', system-ui, -apple-system, sans-serif;

  --glass-bg:
    radial-gradient(60% 48% at 100% 100%, rgba(248,190,215,.36), transparent 70%),
    radial-gradient(51% 42% at 0% 0%,     rgba(140,170,255,.324), transparent 70%),
    linear-gradient(150deg, rgba(28,40,100,.60), rgba(26,30,78,.42));
  --glass-border: rgba(180,200,255,.55) rgba(255,205,215,.44) rgba(255,205,190,.55) rgba(180,200,255,.44);
  --glass-blur:   blur(10px) saturate(1.2);
  --glass-shadow: 0 30px 80px rgba(0,0,10,.15), inset 0 1px 0 rgba(255,255,255,.1);

  --ease: cubic-bezier(.2,.7,.2,1);

  /* How much of the viewport an on-screen keyboard is covering. Set by
     app.js from visualViewport; zero on desktop and whenever it's closed. */
  --kb: 0px;
  --kb-up: 0px;   /* the same distance, negated, for `translate` */
}

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  overflow: hidden;
}

body {
  font-family: var(--font-ui);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ── Scene ──────────────────────────────────────────────────────────────── */

.scene {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: var(--bg);
  container-type: size;
}

/* ── Painted stage ──────────────────────────────────────────────────────── */
/* One element holds the art and every clock, so the circles stay welded to
   the painted planets at any viewport. W never exceeds 166cqw, which keeps
   the planet row (31%→87% of the art) on screen on tall displays. */

.stage {
  --W: min(max(100cqw, 177.73cqh), 166cqw);
  --H: calc(var(--W) * 0.56264);
  position: absolute;
  width: var(--W);
  height: var(--H);
  left: clamp(calc(100cqw - var(--W)), calc(50cqw - var(--W) * 0.59), 0px);
  top:  clamp(calc(100cqh - var(--H)), calc(50cqh - var(--H) * 0.62), 0px);
}

.stage-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  animation: fade 1.6s both;
}

/* Blends the top of the art into the page background. */
.stage-fade {
  position: absolute;
  left: 0; right: 0; top: -2px;
  height: 18%;
  background: linear-gradient(180deg, var(--bg), rgba(7,11,34,0));
  pointer-events: none;
}

/* ── Clock circles ──────────────────────────────────────────────────────── */

.clock {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--d);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3%;
  /* Readability scrim -- the painted planet still shows through. */
  background: radial-gradient(circle, rgba(4,6,20,.5) 0%, rgba(4,6,20,.25) 45%, rgba(4,6,20,0) 70%);
  animation: fade 1.2s var(--in) both;
}

.clock-ring {
  position: absolute;
  inset: -6%;
  border-radius: 50%;
  border: 1px solid var(--ring);
  animation: breathe 4s ease-in-out infinite;
}

.clock-digit {
  font-size: calc(var(--W) * 0.034);
  line-height: 1;
  color: var(--text);
  text-shadow: 0 2px 16px rgba(0,0,0,.85), 0 0 4px rgba(0,0,0,.6);
  font-variant-numeric: tabular-nums;
  display: flex;
}

.clock-unit {
  font-size: max(9px, calc(var(--W) * 0.0068));
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--text);
  text-shadow: 0 1px 8px rgba(0,0,0,.9);
}

.phase {
  position: absolute;
  left: var(--x);
  top: 84.2%;
  transform: translateX(-50%);
  font-size: max(10px, calc(var(--W) * 0.0078));
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--text);
  text-shadow: 0 1px 10px rgba(0,0,0,.9);
  white-space: nowrap;
  animation: fade 1s var(--in) both;
}

/* A digit re-mounts on change; JS re-triggers this by toggling the class. */
.is-ticking { animation: tick .55s var(--ease); }

/* ── Header ─────────────────────────────────────────────────────────────── */

.header {
  position: absolute;
  z-index: 4;
  left: 0; right: 0; top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: clamp(14px, 3cqh, 28px) 5cqw;
  padding-top: max(clamp(14px, 3cqh, 28px), env(safe-area-inset-top));
  animation: fade 1s .1s both;
}

.brand {
  position: relative;
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.1cqw, 18px);
  color: var(--text);
  text-decoration: none;
}

/* The mark sits over the densest part of the starfield, where white-on-stars
   loses its edges. A soft pool of the page background behind it settles the
   sky down without reading as a box -- it has no edge of its own, and the
   art still shows through at the rim. */
.brand::before {
  content: "";
  position: absolute;
  inset: -90% -14% -90% -22%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(ellipse at center,
    rgba(7, 11, 34, .72) 0%,
    rgba(7, 11, 34, .52) 45%,
    rgba(7, 11, 34, 0) 72%);
  pointer-events: none;
}

.brand span {
  font-family: var(--font-logo);
  font-size: clamp(17px, 2.0cqw, 29px);
  letter-spacing: .3em;
  /* Lifts the wordmark off whatever star happens to sit behind a letter. */
  text-shadow: 0 1px 12px rgba(0, 0, 10, .55);
}

.brand img {
  display: block;
  width: clamp(28px, 2.8cqw, 44px);
  height: auto;
  filter: drop-shadow(0 0 10px rgba(180, 205, 255, .45));
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(12px, 2cqw, 26px);
}

.nav-link {
  font: inherit;
  font-size: 15px;
  color: var(--text);
  background: none;
  border: 0;
  border-bottom: 1px solid transparent;
  padding: 6px 0;
  cursor: pointer;
  transition: color .2s, border-color .2s;
}
.nav-link:hover { color: var(--text); }
.nav-link[aria-expanded="true"] {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.nav-divider {
  width: 1px;
  height: 22px;
  background: rgba(255,255,255,.3);
}

/* Wide screens read the labels; the icons only come out on a phone. */
.nav-icon,
.btn-icon { display: none; }

/* ── Buttons ────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 26px;
  border-radius: 999px;
  border: 0;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 500;
  transition: box-shadow .3s, transform .3s, background .3s;
}

.btn--primary {
  color: var(--cta-ink);
  background: linear-gradient(90deg, var(--cta-from), var(--cta-to));
  box-shadow: 0 0 28px rgba(255,200,190,.35);
}
.btn--primary:hover {
  box-shadow: 0 0 40px rgba(255,200,190,.6);
  transform: translateY(-1px);
}

.btn--ghost {
  align-self: flex-start;
  margin-top: 6px;
  color: var(--text);
  border: 1px solid rgba(190,205,255,.55);
  background: rgba(120,150,255,.12);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  animation: rise 1s .8s var(--ease) both;
}
.btn--ghost:hover {
  background: rgba(160,185,255,.3);
  box-shadow: 0 0 30px rgba(150,180,255,.4);
}

.btn--block { width: 100%; height: 48px; padding: 0; }

.btn:focus-visible,
.nav-link:focus-visible,
.brand:focus-visible,
.panel-close:focus-visible,
.field:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.field:focus-within { outline-offset: 1px; }

/* Once the address is in, both CTAs stop asking and start confirming. The
   label is replaced in the DOM rather than toggled, so the animation
   re-runs naturally on mount. */
.btn-swap {
  display: flex;
  align-items: center;
  gap: 8px;
  letter-spacing: .06em;
  text-transform: uppercase;
  font-size: 13.5px;
  font-weight: 600;
  animation: swapIn .6s var(--ease) both;
}
.btn-swap svg { stroke-dasharray: 24; animation: checkDraw .5s .35s ease-out both; }

/* The ring-out belongs to the solid header CTA; the ghost pill just swaps. */
.btn--primary.is-signalled { animation: sigPulse 1.2s .15s ease-out 1; }
.btn--ghost.is-signalled .btn-swap svg { stroke: #FFFFFF; }

.success-check {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: linear-gradient(90deg, var(--cta-from), var(--cta-to));
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.success-check svg { stroke-dasharray: 24; animation: checkDraw .5s .3s ease-out both; }

/* Submit button loading state */
.btn-spinner { display: none; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(26,19,48,.3); border-top-color: var(--cta-ink);
  animation: spin .7s linear infinite; }
.btn.is-loading { pointer-events: none; opacity: .85; }
.btn.is-loading .btn-label { display: none; }
.btn.is-loading .btn-spinner { display: block; }

/* ── Hero ───────────────────────────────────────────────────────────────── */

.hero {
  position: absolute;
  z-index: 1;
  left: 8cqw;
  top: clamp(84px, 14cqh, 140px);
  max-width: min(480px, 86cqw);
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 2.4cqh, 22px);
}

.hero-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(32px, min(4.2cqw, 7cqh), 72px);
  line-height: 1.04;
  letter-spacing: -.01em;
  text-wrap: balance;
  animation: rise 1s .3s var(--ease) both;
}

.hero-lede {
  margin: 0;
  font-size: clamp(15px, 2.2cqh, 18px);
  line-height: 1.55;
  color: var(--text-dim);
  max-width: 34ch;
  text-wrap: pretty;
  animation: rise 1s .5s var(--ease) both;
}

.hero-kicker {
  margin: 0;
  font-size: clamp(17px, 2.5cqh, 21px);
  color: var(--accent);
  animation: rise 1s .65s var(--ease) both;
}


/* ── Role selector ──────────────────────────────────────────────────────── */

.roles { display: flex; flex-direction: column; gap: 8px; }

.roles-label { font-size: 13.5px; color: var(--text-panel); }

.roles-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}

.role {
  height: 62px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 0 4px;
  border: 1px solid transparent;
  border-radius: 12px;
  background: rgba(10, 14, 40, .35);
  color: var(--text-panel);
  font-family: var(--font-ui);
  font-size: 11.5px;
  cursor: pointer;
  /* The handoff asks for a full second, which is what makes the "Other"
     tile's return to quiet read as settling rather than switching off. */
  transition: border-color 1s, box-shadow 1s, background 1s, color 1s;
}
.role:hover { color: var(--text); }

.role[aria-checked="true"] {
  border-color: rgba(255, 205, 165, 1);
  box-shadow: 0 0 18px rgba(255, 190, 140, .35);
  color: var(--text);
}

/* "Other" is selected by default, but shouldn't look like a choice the
   visitor made -- so it sits quiet until tapped, and settles back after. */
.role.is-quiet[aria-checked="true"] {
  border-color: rgba(200, 210, 255, .55);
  box-shadow: none;
  background: rgba(200, 210, 255, .08);
  color: #E6E9F5;
}

.role:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.panel-footnote {
  margin: 2px 0 0;
  font-size: 13px;
  color: #B4BCD8;
  text-align: center;
}

/* ── Footer ─────────────────────────────────────────────────────────────── */
/* Quiet on purpose: a way through for anyone who needs one, without
   competing with the countdown. Arrives last in the entrance sequence. */

.footer {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: clamp(28px, 6cqh, 56px) 8cqw clamp(16px, 3cqh, 30px);
  font-size: 14px;
  color: #B4BCD8;
  text-shadow: 0 1px 10px rgba(0, 0, 10, .8);
  /* Lifts both ends off whatever the art is doing down there. */
  background: linear-gradient(rgba(5, 6, 20, 0), rgba(5, 6, 20, .55) 45%, rgba(5, 6, 20, .85));
  pointer-events: none;
  animation: fade 1s 1.8s both;
}
.footer-left,
.footer-right {
  display: flex;
  align-items: baseline;
  gap: 8px;
  pointer-events: auto;
}
.footer-sep { opacity: .45; }
.footer a:hover { color: #FFD9B8; border-bottom-color: #FFD9B8; }

.footer a {
  color: rgba(221, 226, 244, .9);
  text-decoration: none;
  border-bottom: 1px solid rgba(169, 196, 255, .35);
  padding-bottom: 1px;
  transition: color .2s, border-color .2s;
}

.footer a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ── Glass panels ───────────────────────────────────────────────────────── */

.panel {
  position: absolute;
  z-index: 5;
  right: 5cqw;
  overflow: auto;
  border-radius: 22px;
  border: 1px solid;
  border-color: var(--glass-border);
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-shadow);
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 2.2cqh, 20px);
  animation: rise .6s var(--ease) both;
}
.panel[hidden] { display: none; }

.panel--signal {
  top: clamp(76px, 13cqh, 110px);
  width: min(430px, 90cqw);
  max-height: calc(100cqh - clamp(90px, 15cqh, 130px));
  padding: clamp(20px, 4cqh, 36px) clamp(22px, 3.4cqw, 40px) clamp(18px, 3cqh, 28px);
}

.panel--why {
  top: clamp(76px, 11cqh, 100px);
  width: min(600px, 90cqw);
  max-height: calc(100cqh - clamp(90px, 13cqh, 120px));
  padding: clamp(20px, 4cqh, 36px) clamp(22px, 3.2cqw, 44px) clamp(18px, 3cqh, 28px);
}

.panel-close {
  position: absolute;
  top: 18px; right: 18px;
  width: 36px; height: 36px;
  border: 0; border-radius: 50%;
  background: transparent;
  color: var(--text);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .2s;
}
.panel-close:hover { background: rgba(255,255,255,.12); }

.eyebrow {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .3em;
  text-transform: uppercase;
}
.eyebrow img { display: block; }

.panel-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, min(2.8cqw, 5cqh), 40px);
  line-height: 1.08;
  text-wrap: balance;
}
.panel-title--wide {
  padding-right: 28px;
  font-size: clamp(24px, min(2.5cqw, 4.6cqh), 36px);
  line-height: 1.14;
  text-wrap: pretty;
}

.panel-body {
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--text-panel);
  text-wrap: pretty;
}

/* ── Signup form ────────────────────────────────────────────────────────── */

.signup {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 4px 0 0;
}
.signup[hidden] { display: none; }

.field {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 18px;
  height: 48px;
  border-radius: 999px;
  border: 1px solid rgba(200,210,255,.45);
  background: rgba(10,14,40,.45);
  transition: border-color .2s;
}
.field svg { flex: none; }
.field input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--text);
  font-family: var(--font-ui);
  font-size: 16px; /* 16px stops iOS Safari zooming the viewport on focus */
}
.field input::placeholder { color: rgba(221,226,244,.65); }
.field.is-invalid { border-color: rgba(255,170,170,.85); }

/* Honeypot -- off-screen rather than display:none, which some bots skip. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.field-error {
  margin: 0;
  font-size: 13px;
  color: #FFC2C2;
}
.field-error[hidden] { display: none; }

.success {
  margin: 4px 0 0;
  padding: 16px 20px;
  border-radius: 16px;
  border: 1px solid rgba(255,217,184,.5);
  background: rgba(255,217,184,.1);
  display: flex;
  flex-direction: column;
  gap: 4px;
  animation: rise .5s var(--ease) both;
}
.success[hidden] { display: none; }
.success-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 16px;
  font-weight: 600;
}
/* Lines up with the title text, not the disc. */
.success-body { font-size: 14px; color: var(--text-panel); padding-left: 34px; }
.success-body b { font-weight: 500; color: var(--text); word-break: break-all; }

/* ── Why panel ──────────────────────────────────────────────────────────── */

.why-lines {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 16px;
  line-height: 1.55;
  color: var(--text-panel);
}

.pillars {
  list-style: none;
  margin: 0;
  padding: clamp(12px, 2.4cqh, 20px) 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid rgba(255,255,255,.18);
  border-bottom: 1px solid rgba(255,255,255,.18);
}
.pillars li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
  padding: 0 10px;
  color: var(--tint);
}
.pillars li:nth-child(2) {
  border-left: 1px solid rgba(255,255,255,.18);
  border-right: 1px solid rgba(255,255,255,.18);
}
.pillars span {
  margin-top: 4px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
}

.why-footer {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  text-align: center;
}
.why-footer-title { font-family: var(--font-display); font-size: 19px; }
.why-footer-body  { font-size: 13px; color: var(--text-panel); }

/* ── Launch state (countdown reached zero) ──────────────────────────────── */

.is-launched .hero-kicker { color: var(--cta-from); }
.is-launched .clock-ring  { animation: breathe 1.6s ease-in-out infinite; }

/* ─────────────────────────────────────────────────────────────────────────
   PORTRAIT / SMALL SCREENS
   The handoff proposed rotating the whole viewport 90°. We build a real
   stacked layout instead: the art can't hold its planet alignment in a tall
   crop, so the clocks leave the painting and become their own grid.
   ───────────────────────────────────────────────────────────────────────── */

@media (orientation: portrait) and (max-width: 900px) {

  /* The planets stay welded to the painting here too. The stage is simply
     sized so the painted planet row -- which spans 31.18%..87.19% of the
     art, i.e. 56.01% of W -- fills 96cqw of the viewport:
         W = 96 / 0.5601 = 171.4cqw
     Everything inside is already expressed as a percentage of W, so the
     circles, digits and labels scale down with it and stay in place. At
     390px wide that gives 57-76px circles and ~23px digits. */
  .stage {
    --W: 171.4cqw;
    --H: calc(var(--W) * 0.56264);
    position: fixed;
    width: var(--W);
    height: var(--H);
    /* Centre the row, not the image: its midpoint is 59.18% of W. */
    left: calc(50cqw - var(--W) * 0.5918);
    /* Planet centres sit at ~63% of H; put them 68% down the viewport. */
    top: calc(68cqh - var(--H) * 0.63);
  }

  /* The art no longer runs to the edges, so the fixed top fade would read as
     a band across the middle of the page rather than a blend. Fade the image
     itself at both ends instead -- masking the art and not the stage keeps
     the circles and labels crisp. The bottom fade starts at 86%, below the
     phase labels at 84.2%, so they never wash out. */
  .stage-fade { display: none; }
  .stage-art {
    mask-image: linear-gradient(180deg, transparent 0, #000 16%, #000 86%, transparent 100%);
    -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 16%, #000 86%, transparent 100%);
  }

  /* Phase labels would collide at this width with the landscape tracking. */
  .phase {
    font-size: max(8.5px, calc(var(--W) * 0.0078));
    letter-spacing: .1em;
  }

  .header {
    position: relative;
    padding: max(16px, env(safe-area-inset-top)) 6cqw 0;
    gap: 12px;
  }
  .brand span { font-size: 16px; letter-spacing: .26em; }
  .brand img { width: 26px; }
  .brand::before { inset: -70% -12% -70% -18%; }
  /* The full "Notify me at launch" label ran off the edge of a phone. Both
     nav actions collapse to their icon instead of disappearing -- the label
     lives on in aria-label, so the buttons still announce themselves.
     42px keeps them a comfortable thumb target. */
  .nav { gap: 10px; }
  .nav-label { display: none; }
  .nav-icon,
  .btn-icon { display: block; }

  .nav-link {
    width: 42px;
    height: 42px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(190,205,255,.4);
    border-radius: 50%;
    padding: 0;
    background: rgba(120,150,255,.12);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  .nav-link[aria-expanded="true"] {
    color: var(--cta-ink);
    background: linear-gradient(90deg, var(--cta-from), var(--cta-to));
    border-color: transparent;
  }

  .nav .btn--primary {
    width: 42px;
    height: 42px;
    padding: 0;
    gap: 0;
    flex: none;
  }
  /* The written label and its post-submit swap are both too wide here; the
     icon carries the state instead. */
  .nav .btn--primary .btn-text,
  .nav .btn--primary .btn-swap { display: none; }
  .nav .btn--primary .btn-icon--check { display: none; }
  .nav .btn--primary.is-signalled .btn-icon--bell { display: none; }
  .nav .btn--primary.is-signalled .btn-icon--check {
    display: block;
    animation: swapIn .6s var(--ease) both;
  }

  .nav-divider { display: none; }

  /* Centred under the planets, clear of the home indicator. Stacked, because
     both halves side by side wrap badly at this width. */
  .footer {
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: clamp(24px, 5cqh, 44px) 6cqw max(16px, env(safe-area-inset-bottom));
    font-size: 12.5px;
  }
  .roles-grid { gap: 6px; }
  .role { height: 58px; font-size: 11px; }

  .hero {
    position: relative;
    left: auto; top: auto;
    max-width: none;
    padding: clamp(18px, 4cqh, 36px) 6cqw 0;
    gap: 12px;
  }
  .hero-title  { font-size: clamp(28px, 8.6cqw, 42px); }
  .hero-lede   { font-size: 15px; max-width: 32ch; }
  .hero-kicker { font-size: 17px; }
  /* The ghost pill becomes the primary action on a phone, since the header
     CTA is hidden -- full width so it's an easy thumb target. */
  .btn--ghost {
    align-self: stretch;
    justify-content: center;
    margin-top: 8px;
    height: 50px;
    padding: 0;
  }

  .panel {
    position: fixed;
    right: 0; left: 0;
    bottom: 0;
    top: auto;
    width: auto;
    /* Ride up with the keyboard instead of disappearing behind it.
       `translate` rather than `bottom`: measured in a 390px viewport, this
       element ignores `bottom` (and `inset-block-end`) even at !important
       while accepting `height` from the same rule -- so the inset is pinned
       by something in the fixed/size-container setup. `translate` is also a
       separate property from `transform`, so it does not fight the `rise`
       entry animation the way a transform would. */
    translate: 0 var(--kb-up);
    /* ...and give back the height it took, so the sheet stays scrollable
       rather than running off the top of the screen. */
    max-height: calc(88cqh - var(--kb));
    border-radius: 22px 22px 0 0;
    padding: 28px 6cqw max(24px, env(safe-area-inset-bottom));
    transition: translate .2s ease-out;
  }
  .panel--why { padding-left: 6cqw; padding-right: 6cqw; }
  .panel-title { font-size: 26px; }
  .panel-title--wide { font-size: 23px; padding-right: 24px; }
  .pillars svg { width: 26px; height: 26px; }
}

/* Short landscape phones: shrink the hero so it can't collide with the art. */
@media (orientation: landscape) and (max-height: 460px) {
  .hero { top: clamp(56px, 12cqh, 90px); }
  .hero-lede { display: none; }
  .btn { padding: 11px 20px; font-size: 14px; }
}

/* ── Motion ─────────────────────────────────────────────────────────────── */

@keyframes rise   { from { opacity: 0; transform: translateY(28px); filter: blur(6px); }
                    to   { opacity: 1; transform: none; filter: blur(0); } }
@keyframes fade   { from { opacity: 0; } to { opacity: 1; } }
@keyframes tick   { from { opacity: 0; transform: translateY(.35em) scale(.96); }
                    to   { opacity: 1; transform: none; } }
@keyframes breathe{ 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
@keyframes spin   { to { transform: rotate(360deg); } }

/* Post-submit acknowledgement. */
@keyframes swapIn {
  0%   { opacity: 0; transform: translateY(.7em); filter: blur(4px); }
  100% { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes sigPulse {
  0%   { box-shadow: 0 0 0 0 rgba(255,210,190,.7); }
  60%  { box-shadow: 0 0 0 14px rgba(255,210,190,0), 0 0 40px rgba(255,200,190,.5); }
  100% { box-shadow: 0 0 28px rgba(255,200,190,.35); }
}
@keyframes checkDraw { from { stroke-dashoffset: 24; } to { stroke-dashoffset: 0; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .clock-ring { opacity: .8; }
}

/* ─────────────────────────────────────────────────────────────────────────
   PRIVACY PAGE
   A real page rather than a panel, so the policy has an address that can be
   linked from an email or quoted in a form. Same glass treatment as the
   panels, over the softened cosmos art the handoff supplies.
   ───────────────────────────────────────────────────────────────────────── */

/* The countdown pins html/body to the viewport and hides overflow. This page
   has to undo both on the root as well as the body, or it silently refuses to
   scroll and the policy below the fold is unreachable. */
.privacy-root,
.privacy-root .privacy-body {
  height: auto;
  min-height: 100%;
  overflow: visible;
  background: var(--bg);
}

.privacy {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  container-type: inline-size;
  background:
    linear-gradient(rgba(7, 11, 34, .55), rgba(7, 11, 34, .82)),
    url("/assets/privacy-cosmos-soft.webp") center top / cover no-repeat,
    var(--bg);
}

.privacy-head { padding: clamp(18px, 3cqw, 32px) clamp(20px, 5cqw, 64px) 0; }

.privacy-sheet {
  width: min(1220px, 90cqw);
  margin: clamp(24px, 5cqw, 56px) auto clamp(28px, 5cqw, 48px);
  padding: clamp(26px, 4cqw, 54px) clamp(22px, 4cqw, 56px);
  border-radius: 22px;
  border: 1px solid;
  border-color: var(--glass-border);
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-shadow);
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2.4cqw, 28px);
  animation: rise .6s var(--ease) both;
}

.privacy-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(30px, 4cqw, 52px);
  line-height: 1.08;
  color: var(--text);
  text-wrap: balance;
}

.privacy-intro {
  margin: 0;
  max-width: 62ch;
  font-size: clamp(15px, 1.3cqw, 17px);
  line-height: 1.6;
  color: var(--text-panel);
  text-wrap: pretty;
}

.privacy-tagline {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(18px, 1.7cqw, 24px);
  line-height: 1.35;
  color: var(--accent);
}

.privacy-cols {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(16px, 2cqw, 32px);
  padding: clamp(16px, 2cqw, 26px) 0;
  border-top: 1px solid rgba(255, 255, 255, .18);
  border-bottom: 1px solid rgba(255, 255, 255, .18);
}

.privacy-notes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2cqw, 32px);
}

/* The four columns are the substance of the policy, so their headings are
   picked out in amber. The two notes below are footnotes to it and sit in the
   same colour as the body text -- the contrast is the hierarchy. */
.privacy-cols h2,
.privacy-notes h2 {
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
}

.privacy-cols h2  { color: var(--cta-from); }
.privacy-notes h2 { color: var(--text-panel); }

.privacy-cols p,
.privacy-notes p {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-panel);
  text-wrap: pretty;
}

.privacy-updated { margin: 0; font-size: 13px; color: #B4BCD8; }

/* The supplied icons are lit orbs on transparency -- they carry their own
   glow, so they sit directly on the glass with nothing drawn behind them. */
.privacy-icon {
  display: block;
  width: 56px;
  height: 56px;
  margin: 0 0 10px -6px;   /* the glow reads as padding; pull it back into line */
}

/* Matches the mockup: a peach text link, not a pill. */
.privacy-back {
  align-self: flex-start;
  margin-top: 4px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--cta-from);
  text-decoration: none;
  transition: color .2s, gap .2s;
}
.privacy-back:hover { color: #FFD9B8; gap: 12px; }
.privacy-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 4px; }

/* The sheet's own close, in the same place a panel's would be. */
.privacy-close {
  position: absolute;
  top: 18px;
  right: 18px;
  text-decoration: none;
  font-size: 26px;
}
.privacy-sheet { position: relative; }

/* The countdown's footer is pinned to a fixed viewport; here it just follows
   the content down the page. */
.footer--static {
  position: static;
  margin-top: auto;
  animation: none;
}
.footer-privacy.is-current { color: var(--cta-from); }

@container (max-width: 860px) {
  .privacy-cols  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@container (max-width: 560px) {
  .privacy-cols,
  .privacy-notes { grid-template-columns: 1fr; }
  .privacy-tagline { display: none; }   /* the handoff hides it on phones */
  .privacy-sheet { width: 94cqw; border-radius: 18px; }
}
