/* ==========================================================================
   ECLIPSE — teaser
   Palette + sizing live in :root. The reveal geometry is derived from the
   corona artwork: the dark moon in corona.jpg is 61.33% of the image width,
   so  corona size = moon size / 0.6133  keeps the ring hugging the disc.
   ========================================================================== */

:root {
  --void:  #050505;
  --ink:   #020202;
  --text:  #ece6da;
  --dim:   #8d8578;
  --faint: #57514a;
  --gold:  #c9a063;
  --ember: #f0a343;
  --flare: #ffd9a0;

  /* size of the wheel (and the stage it sits on) */
  /* Trimmed ~8% to fund the gap below the eclipse. The corona is drawn at
     1.702x this, so shrinking it pulls the glow up and away from the whisper
     line as well as freeing layout height. The eclipse still dominates. */
  --scene: min(48vmin, 37svh, 440px);
  /* moon slightly larger than the wheel so it fully hides it at the start */
  --moon:   calc(var(--scene) * 1.06);
  --corona: calc(var(--scene) * 1.702);   /* 1.06 / 0.6230 (moon dia ÷ corona.png size) */
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { color-scheme: dark; }

body {
  background: var(--void);
  color: var(--text);
  font-family: 'Saira', 'Segoe UI', sans-serif;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

/* fine film grain over everything — kills the "flat black" look */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: 9;
  pointer-events: none;
  opacity: .05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

::selection { background: var(--gold); color: var(--ink); }

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

/* ---------- backdrop ---------- */

#stars {
  position: fixed; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  opacity: 0;
  animation: stars-in 3s ease 0.4s forwards;
}
@keyframes stars-in { to { opacity: 1; } }

/* ---------- page frame ---------- */

.hero {
  position: relative; z-index: 1;
  min-height: 100svh;
  display: flex; flex-direction: column; align-items: center;
  padding: max(4.5svh, env(safe-area-inset-top))
           max(24px, env(safe-area-inset-right))
           max(3svh, env(safe-area-inset-bottom))
           max(24px, env(safe-area-inset-left));
  overflow: hidden;
}

/* ---------- wordmark ---------- */

.mark {
  text-align: center; position: relative; z-index: 4;
  /* Reserve headroom so the eclipse sits clear of the wordmark. The corona
     is 1.7x the scene box and overflows it, so the gap has to be measured
     against the glow, not the box: the scene-relative part keeps clear of the
     corona at any size, the svh part adds real breathing room on tall
     screens and shrinks itself on short ones. */
  padding-bottom: calc(var(--scene) * 0.10 + 2.5svh);
}
.mark h1 {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  font-weight: 200; font-size: clamp(16px, 2.1vw, 20px);
  letter-spacing: .58em; text-indent: .58em; /* balance the tracking */
  color: var(--text);
}
.mark-ring { width: 21px; height: 21px; flex: none; }
.mark-sub {
  margin-top: 7px;
  font-weight: 300; font-size: 8.5px; letter-spacing: .92em; text-indent: .92em;
  color: #746c5f;
}

/* ---------- the eclipse scene ---------- */

.scene {
  position: relative;
  width: var(--scene); height: var(--scene);
  margin: auto;              /* centres it in the leftover space */
  flex: none;
  cursor: none;
  touch-action: pan-y;       /* vertical scroll still works; drags become the torch */
  /* Nudge down, away from the wordmark. Kept small: this shifts the render
     without moving the layout box, so every extra unit here is taken straight
     out of the visual gap below the eclipse. */
  translate: 0 1svh;
}

.scene > * { position: absolute; }

/* -- wheel -- */

.wheel-slide {
  inset: 0; z-index: 1;
  transform: translate(24%, 3%);                     /* final resting place */
  animation: wheel-out 3.8s cubic-bezier(.16,.6,.18,1) 1.7s both;
}
@keyframes wheel-out { from { transform: translate(0, 0) scale(.97); } }

.wheel-box { position: absolute; inset: 0; }

.wheel-rot { position: absolute; inset: 0; animation: slow-spin 150s linear infinite; }
@keyframes slow-spin { to { transform: rotate(360deg); } }

.wheel-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border-radius: 50%;
  user-select: none; -webkit-user-drag: none;
  -webkit-touch-callout: none;
}

.wheel-base { filter: brightness(.72) contrast(1.08) sepia(.18) saturate(1.15) hue-rotate(-8deg); }

/* the torch-lit copy, clipped to a circle that follows the pointer */
.lit-clip {
  position: absolute; inset: 0;
  -webkit-mask-image: radial-gradient(circle 165px at var(--mx, -500px) var(--my, -500px), #000 30%, transparent 72%);
          mask-image: radial-gradient(circle 165px at var(--mx, -500px) var(--my, -500px), #000 30%, transparent 72%);
}
.wheel-lit { filter: sepia(.25) saturate(1.5) hue-rotate(-10deg) brightness(1.12) contrast(1.04); }

/* corona light kissing the rim on the moon side */
.rimlight {
  position: absolute; inset: 0; border-radius: 50%;
  background:
    radial-gradient(circle at 9% 42%,  rgba(255, 213, 150, .30), transparent 32%),
    radial-gradient(circle at 24% 30%, rgba(240, 163, 67, .10),  transparent 58%);
  mix-blend-mode: screen;
  pointer-events: none;
}

/* -- moon + corona -- */

.moon-slide {
  inset: 0; z-index: 2;
  transform: translate(-20%, -3%);                   /* final resting place */
  animation: moon-out 3.8s cubic-bezier(.16,.6,.18,1) 1.7s both;
  pointer-events: none;
}
@keyframes moon-out { from { transform: translate(0, 0); } }

.moon-idle {
  position: absolute; inset: 0;
  animation: drift 13s ease-in-out infinite alternate;
}
@keyframes drift { to { transform: translate(.7%, -.5%); } }

.corona-wrap {
  position: absolute;
  width: var(--corona); height: var(--corona);
  left: 50%; top: 50%; translate: -50% -50%;
  animation:
    breathe 7s ease-in-out infinite alternate,
    appear 2s ease .15s both;
}
@keyframes breathe { to { transform: scale(1.02); } }
@keyframes appear { from { opacity: 0; } }

.corona {
  position: absolute; inset: 0; width: 100%; height: 100%;
  user-select: none; -webkit-user-drag: none;
}

/* rotating copies carry only the outer clouds (masked past the ring),
   so the baked-in flare/ring never orbits — the atmosphere just churns */
.corona-b, .corona-c {
  -webkit-mask-image: radial-gradient(circle, transparent 40%, #000 47%);
          mask-image: radial-gradient(circle, transparent 40%, #000 47%);
}
.corona-b { opacity: .5;  animation: churn-cw 240s linear infinite; }
.corona-c { opacity: .36; animation: churn-ccw 170s linear infinite; filter: hue-rotate(7deg) brightness(1.06); }
@keyframes churn-cw  { from { transform: scale(1.05) rotate(0deg); }   to { transform: scale(1.05) rotate(360deg); } }
@keyframes churn-ccw { from { transform: scale(.97) rotate(360deg); }  to { transform: scale(.97) rotate(0deg); } }

/* solar-wind particles streaming off the ring (drawn by app.js) */
.corona-fx {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none;
}

/* Baily's bead — an occasional glint travelling the eclipse edge (app.js places it) */
.bead {
  position: absolute;
  width: 3.5%; height: 3.5%;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 240, 214, .95), rgba(242, 163, 67, .4) 45%, transparent 70%);
  filter: blur(1px);
  opacity: 0;
  pointer-events: none;
}
.bead.glint { animation: bead-glint 2.4s cubic-bezier(.3,.6,.4,1); }
@keyframes bead-glint {
  14% { opacity: .95; }
  32% { opacity: .4; }
  48% { opacity: .8; }
  100% { opacity: 0; }
}

/* breathing bloom over the baked-in diamond-ring flare */
.flare-dot {
  position: absolute;
  left: 30.3%; top: 26.6%;
  width: 7%; height: 7%;
  translate: -50% -50%;
  background: radial-gradient(circle, rgba(255, 226, 178, .9), rgba(240, 163, 67, .35) 45%, transparent 70%);
  filter: blur(4px);
  mix-blend-mode: screen;
  animation: flicker 11s ease-in-out infinite;
}
/* irregular, candle-like — never a metronome */
@keyframes flicker {
  0%, 100% { opacity: .55; }
  12% { opacity: .92; }
  21% { opacity: .6; }
  34% { opacity: .98; }
  47% { opacity: .68; }
  58% { opacity: 1; }
  71% { opacity: .58; }
  86% { opacity: .85; }
}

.moon {
  position: absolute;
  width: var(--moon); height: var(--moon);
  left: 50%; top: 50%; translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 36%, #0a0a0a, var(--ink) 72%);
  box-shadow: 0 0 46px 10px rgba(0, 0, 0, .55);
}

/* success pulse — JS adds .flare to <body> and the diamond ring blazes */
body.flare .flare-dot {
  animation: flarepulse 1.8s cubic-bezier(.2,.7,.3,1) 1;
}
@keyframes flarepulse {
  18% { opacity: 1; transform: scale(2.6); filter: blur(6px); }
}

/* -- torch halo -- */

.torch {
  z-index: 1;   /* above the wheel, below the moon: the disc occludes the light */
  width: 340px; height: 340px;
  left: 0; top: 0;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 214, 150, .16), rgba(240, 163, 67, .05) 45%, transparent 68%);
  mix-blend-mode: screen;
  pointer-events: none;
  opacity: 0;
  transition: opacity .5s ease;
}
.scene.lit .torch { opacity: 1; }

/* ---------- message ---------- */

.content {
  text-align: center;
  display: flex; flex-direction: column; align-items: center;
  gap: 17px;
  /* clears the bottom of the corona glow, not just the scene box */
  margin-top: calc(var(--scene) * 0.12 + 6svh);
}

/* The two display moments (this and .joined h2) are set in the lightest
   weight of the body face, larger and widely tracked, rather than a second
   display family. The corona art carries the drama; the type stays quiet and
   instrument-like, which suits a machined product better than an italic
   serif. Keep these two rules in step with each other. */
.whisper {
  font-family: 'Saira', sans-serif;
  font-weight: 200;
  font-size: clamp(19px, 2.6vw, 26px);
  color: #c7bfae;
  letter-spacing: .1em;
}

.eyebrow {
  font-weight: 400; font-size: 10.5px;
  letter-spacing: .5em; text-indent: .5em;
  color: var(--gold);
}

.count { display: flex; align-items: flex-start; gap: clamp(8px, 1.6vw, 18px); }
.cg { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.cd {
  font-weight: 200;
  font-size: clamp(31px, 6vw, 52px);
  line-height: 1;
  letter-spacing: .05em;
  min-width: 2.3ch;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.cl {
  font-weight: 300; font-size: 9.5px;
  letter-spacing: .42em; text-indent: .42em;
  text-transform: uppercase;
  color: #9a9184;
}
.csep {
  font-weight: 100;
  font-size: clamp(26px, 5vw, 44px);
  line-height: 1.15;
  color: var(--faint);
}

/* ---------- email capture ---------- */

.join { width: min(440px, 100%); margin-top: 6px; }
.join-row { display: flex; align-items: stretch; }

.join input[type="email"] {
  flex: 1; min-width: 0;
  background: transparent;
  border: 0; border-bottom: 1px solid rgba(255, 255, 255, .16);
  padding: 12px 4px;
  /* 16px minimum: anything smaller makes iOS zoom the page on focus */
  font-family: 'Saira', sans-serif; font-weight: 300; font-size: 16px;
  letter-spacing: .04em;
  color: var(--text);
  caret-color: var(--gold);
  border-radius: 0;
  transition: border-color .25s;
}
.join input[type="email"]::placeholder { color: var(--faint); }
.join input[type="email"]:focus { outline: none; border-bottom-color: var(--gold); }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

.join button {
  margin-left: 22px;
  padding: 13px 26px;
  background: transparent;
  border: 1px solid rgba(201, 160, 99, .45);
  color: var(--gold);
  font-family: 'Saira', sans-serif; font-weight: 500; font-size: 11px;
  letter-spacing: .28em; text-indent: .28em;
  text-transform: uppercase;
  cursor: pointer;
  white-space: nowrap;
  transition: background .25s, color .25s, border-color .25s, opacity .25s;
}
.join button:hover, .join button:focus-visible { background: var(--gold); color: var(--ink); border-color: var(--gold); outline: none; }
.join button[disabled] { opacity: .45; pointer-events: none; }

/* call to action under the form. Reuses the tracking of the post-signup
   subline and the colour of the old small print, so nothing new is invented. */
.join-cta {
  margin-top: 14px;
  font-weight: 400; font-size: 11px;
  letter-spacing: .22em; text-indent: .22em;
  text-transform: uppercase;
  color: var(--gold);
}
.join-lead { margin-top: 7px; font-weight: 300; font-size: 12px; letter-spacing: .05em; color: #968d7f; }
.join-status { margin-top: 8px; min-height: 17px; font-weight: 300; font-size: 12.5px; letter-spacing: .05em; color: #d98c6a; }
.join-status.ok { color: var(--gold); }

/* post-signup state (injected by JS) */
.joined h2 {
  font-family: 'Saira', sans-serif; font-weight: 200;
  font-size: clamp(21px, 3vw, 27px); color: var(--flare); letter-spacing: .1em;
}
.joined p { margin-top: 10px; font-weight: 300; font-size: 12px; letter-spacing: .22em; text-indent: .22em; text-transform: uppercase; color: var(--dim); }

/* ---------- footer ---------- */

.foot {
  margin-top: 3.2svh;
  font-weight: 300; font-size: 10.5px;
  letter-spacing: .38em; text-indent: .38em;
  color: #6f675c;
}

/* ---------- staggered entrance ---------- */

.reveal { animation: rise 1.4s cubic-bezier(.2,.7,.3,1) both; }
@keyframes rise { from { opacity: 0; transform: translateY(10px); } }
.r1 { animation-delay: 2.7s; }
.r2 { animation-delay: 3.0s; }
.r3 { animation-delay: 3.2s; }
.r4 { animation-delay: 3.6s; }
.r5 { animation-delay: 4.2s; }

/* ---------- small screens ---------- */

@media (max-width: 640px) {
  :root { --scene: min(74vmin, 34svh); }
  .hero {
    padding: max(4svh, env(safe-area-inset-top))
             max(20px, env(safe-area-inset-right))
             max(2.6svh, env(safe-area-inset-bottom))
             max(20px, env(safe-area-inset-left));
  }
  /* gentler slide so the whole eclipse stays in frame on a narrow screen */
  .wheel-slide { transform: translate(19%, 2%); }
  .moon-slide  { transform: translate(-13%, -2%); }
  /* Phones have very little slack: the form must stay above the fold, so the
     extra breathing room here is deliberately smaller than on desktop. */
  .mark { padding-bottom: calc(var(--scene) * 0.10 + 1.6svh); }
  .content { gap: 14px; margin-top: calc(var(--scene) * 0.07 + 3svh); }
  /* keep the line to one row on a phone: a wrap costs ~25px of the little
     vertical slack there is, and pushes the form towards the fold */
  .whisper { font-size: clamp(16px, 4.4vw, 20px); letter-spacing: .06em; }
  .join-row { flex-direction: column; }
  .join button { margin: 15px 0 0; padding: 15px 26px; }
  .foot { margin-top: 2.2svh; }
  .scene { cursor: auto; }
}

/* ---------- short desktop windows (laptops) ---------- */

@media (min-width: 641px) and (max-height: 800px) {
  /* Short landscape/laptop viewports are the tightest case of all. */
  .mark { padding-bottom: calc(var(--scene) * 0.10 + 1.4svh); }
  .content { gap: 13px; margin-top: calc(var(--scene) * 0.08 + 3svh); }
  .cd { font-size: clamp(28px, 4.6vw, 42px); }
  .csep { font-size: clamp(24px, 3.8vw, 36px); }
  /* tighter tracking on short viewports so the line still fits without wrapping */
  .whisper { font-size: clamp(17px, 2.2vw, 21px); letter-spacing: .06em; }
  .foot { margin-top: 2.4svh; }
}

/* ---------- reduced motion: land on the final frame, no theatrics ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  #stars { opacity: .8; }
}
