/* ══════════════════════════════════════════════════════════════════════════
   Astrelle Systems: landing page.

   Built on the Industry design system's blueprint grammar (square corners,
   hairline borders, "+" registration marks) re-grounded on the Astrelle dark
   palette. Tokens below are the brand standard's own names.

   Amber budget: the brand allows amber on the star, one primary button, and
   the active indicator. This page spends exactly that: the sodium star in
   orbit, the Notify me button, and the one division indicator that walks the
   board. The lock effects add light to those three, never a fourth source.
   ══════════════════════════════════════════════════════════════════════ */

/* Fonts are self-hosted (latin subset, woff2). Program offices and agency
   networks routinely block third-party CDNs: a blocked Google Fonts request
   drops the page to a fallback face and the 86px headline reflows. Shipping
   them from our own origin removes that failure mode and the cross-origin
   round trip with it. */
@font-face {
  font-family: "Barlow";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/barlow-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/barlow-500.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow Condensed";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/barlow-condensed-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow Condensed";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/barlow-condensed-500.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow Condensed";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/barlow-condensed-600.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/jetbrains-mono-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/jetbrains-mono-500.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ground */
  --void: #08090B;
  --deep: #0E1116;
  --panel: #0B0D10;
  --graphite: #1A1F27;
  --slate: #2B333F;

  /* type */
  --ash: #6B7683;
  --mist: #A8B2BE;
  --bone: #E6E9ED;
  --white: #FFFFFF;

  /* amber, rationed */
  --sodium: #EDA83B;
  --filament: #FFD79A;

  /* green */
  --drab: #3F4632;
  --ranger: #6C6F53;
  --field: #7A7F5C;

  --font-heading: "Barlow Condensed", system-ui, sans-serif;
  --font-body: "Barlow", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --bar-x: 36px;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--void);
  color: var(--bone);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; }
h1, h2 { font-family: var(--font-heading); margin: 0; }
p { margin: 0; }

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

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--sodium); outline-offset: 2px; }
::selection { background: rgba(237, 168, 59, .3); }

/* The shell frames the page on very wide displays rather than letting the
   split stretch without limit. Below 1600px the hairlines sit off-screen. */
.shell {
  flex: 1;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 1600px;
  margin-inline: auto;
  border-inline: 1px solid var(--graphite);
}

/* ── blueprint frame ─────────────────────────────────────────────────── */

.blueprint { position: relative; border: 1px solid var(--slate); border-radius: 0; }
.blueprint > .corner { position: absolute; width: 11px; height: 11px; color: var(--ranger); }
.blueprint > .corner::before,
.blueprint > .corner::after { content: ""; position: absolute; background: currentColor; }
.blueprint > .corner::before { left: 5px; top: 0; width: 1px; height: 100%; }
.blueprint > .corner::after  { top: 5px; left: 0; width: 100%; height: 1px; }
.blueprint > .corner.tl { top: -6px; left: -6px; }
.blueprint > .corner.tr { top: -6px; right: -6px; }
.blueprint > .corner.bl { bottom: -6px; left: -6px; }
.blueprint > .corner.br { bottom: -6px; right: -6px; }

/* ── header / footer bars ────────────────────────────────────────────── */

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 18px var(--bar-x);
  background: var(--deep);
}
.bar-top { border-bottom: 1px solid var(--graphite); }
.bar-bottom {
  border-top: 1px solid var(--graphite);
  font: 400 11px/1 var(--font-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ash);
}
.wordmark { width: 150px; height: auto; }

/* Pre-launch marker. Green, not amber: the budget is already spent on the
   star, the button, and the division indicator. */
.status {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: none;
  font: 400 10px/1 var(--font-mono);
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ash);
  white-space: nowrap;
}
.status-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--field);
  animation: standby 3.4s ease-in-out infinite;
}
@keyframes standby { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

/* ── the board ───────────────────────────────────────────────────────── */

.board {
  flex: 1;
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  min-height: 620px;
}

/* ── left: the statement ─────────────────────────────────────────────── */

.statement {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 76px 48px 60px;
  border-right: 1px solid var(--graphite);
}

.statement h1 {
  font-weight: 600;
  font-size: clamp(46px, 6.72vw, 86px);
  line-height: .94;
  letter-spacing: -.015em;
  color: var(--white);
}

.lede {
  margin-top: 30px;
  max-width: 44ch;
  font-size: 17px;
  line-height: 1.6;
  color: var(--mist);
}

/* ── email capture ───────────────────────────────────────────────────── */

.capture {
  margin-top: 44px;
  max-width: 470px;
  background: rgba(14, 17, 22, .6);
  padding: 24px 24px 22px;
}
.capture-kicker {
  display: block;
  margin-bottom: 16px;
  font: 500 10px/1 var(--font-mono);
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--field);
}
.capture-row { display: flex; gap: 10px; }
.capture-input {
  flex: 1;
  min-width: 0;
  background: var(--void);
  border: 1px solid var(--slate);
  border-radius: 0;
  padding: 12px 14px;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--bone);
  caret-color: var(--sodium);
}
.capture-input::placeholder { color: var(--ash); }
.capture-input:hover { border-color: var(--ranger); }
.capture-input:focus { border-color: var(--field); }
.capture-input:focus-visible { border-color: var(--field); outline-offset: 0; }

.capture-btn {
  flex: none;
  border: none;
  border-radius: 0;
  background: var(--sodium);
  color: var(--void);
  padding: 12px 22px;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: .12em;
  text-transform: uppercase;
  cursor: pointer;
}
.capture-btn:hover { background: var(--filament); }
.capture-btn:active { background: #D9962C; }
.capture-btn:disabled { cursor: default; opacity: .45; }

/* honeypot: off-screen for bots, out of reach for people */
.capture-trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.capture-note {
  margin-top: 14px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ash);
}
.capture-status {
  margin-top: 10px;
  font: 400 12px/1.5 var(--font-mono);
  letter-spacing: .06em;
  color: var(--field);
}
.capture-status:empty { display: none; }
.capture-status.is-error { color: #E4736B; }

.capture.is-done .capture-row,
.capture.is-done .capture-note { display: none; }
.capture.is-done .capture-status { margin-top: 0; }

/* ── right: the division board ───────────────────────────────────────── */

.panel {
  position: relative;
  overflow: hidden;
  background-color: var(--panel);
  background-image: radial-gradient(var(--graphite) 1px, transparent 1px);
  background-size: 18px 18px;
}
/* the board reads over the field, not under it */
.panel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 40%, var(--panel) 92%);
  pointer-events: none;
}

.panel-field { position: absolute; inset: 0; }

.ring, .orbit { position: absolute; border-radius: 50%; }
.ring-1, .orbit-1 { top: -140px; right: -180px; width: 620px; height: 620px; }
.ring-2, .orbit-2 { top: -40px;  right: -80px;  width: 420px; height: 420px; }
.ring-3, .orbit-3 { top: 60px;   right: 20px;   width: 220px; height: 220px; }
.ring-1 { border: 1px solid var(--graphite); }
.ring-2 { border: 1px solid #171C23; }
.ring-3 { border: 1px solid #14181E; }

.orbit-1 { animation: orbit 34s linear infinite; }
.orbit-2 { animation: orbit 21s linear infinite reverse; }
.orbit-3 { animation: orbit 13s linear infinite; }

.body { position: absolute; left: 50%; }
.body-star { top: -7px; width: 15px; height: auto; margin-left: -7px; opacity: .85; }
.body-drab { bottom: -5px; width: 11px; height: auto; margin-left: -5px; opacity: .8; }
.body-dot  { top: -2px; width: 4px; height: 4px; margin-left: -2px; border-radius: 50%; background: var(--ranger); }

@keyframes orbit { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* ── the field answers the lock ──────────────────────────────────────────
   Every time the indicator takes a new row the field responds: a shell goes
   out from the centre of the inner ring, the sodium star flares, and ring 3
   picks up the amber for a moment. The star is already on the amber budget,
   so the lock adds light, not a new colour. */
.ping {
  position: absolute;
  /* the centre of .ring-3: top 60 + 110, right 20 + 110 */
  top: 170px;
  right: 130px;
  width: 140px;
  height: 140px;
  margin: -70px -70px 0 0;
  border: 1px solid var(--sodium);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}
.panel-field.is-lock .ping { animation: ping 1500ms cubic-bezier(.2, .6, .3, 1); }
@keyframes ping {
  from { transform: scale(.3);  opacity: .45; }
  to   { transform: scale(3.1); opacity: 0; }
}

.panel-field.is-lock .body-star { animation: flare 1500ms ease-out; }
@keyframes flare {
  0%   { opacity: .85; transform: scale(1); }
  16%  { opacity: 1;   transform: scale(1.6); }
  100% { opacity: .85; transform: scale(1); }
}

.panel-field.is-lock .ring-3 { animation: ring-lock 1500ms ease-out; }
@keyframes ring-lock {
  0%, 100% { border-color: #14181E; }
  20%      { border-color: rgba(237, 168, 59, .24); }
}

.panel-inner { position: relative; z-index: 1; padding: 72px 40px; }

.divisions-board { position: relative; }
.divisions { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.division {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px 0;
  border-bottom: 1px solid var(--graphite);
}
.division:last-child { border-bottom: none; }

.division-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1px solid var(--ranger);
}

/* No-JS fallback: Defense simply stays lit. Once the board comes alive the
   indicator below takes the amber over and every row reverts to a hollow
   ring, so there is still only ever one amber point in the list. */
.division.is-active .division-dot {
  border: none;
  background: var(--sodium);
  box-shadow: 0 0 10px rgba(237, 168, 59, .7);
}
.divisions-board.is-live .division.is-active .division-dot {
  border: 1px solid var(--ranger);
  background: none;
  box-shadow: none;
}

/* ── the traveling indicator ─────────────────────────────────────────────
   The active dot is a single object that walks the list rather than four
   dots taking turns. The board acquires a track, it does not flip a switch.
   JS parks it over a row by that row's own dot offset, so the list stays the
   source of truth for spacing. */
.track {
  position: absolute;
  top: 0;
  left: 0;
  width: 7px;
  height: 7px;
  opacity: 0;
  pointer-events: none;
  transition: transform 760ms cubic-bezier(.65, 0, .35, 1);
}
.divisions-board.is-live .track { opacity: 1; }
.track.is-instant { transition: none; }

.track-dot {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--sodium);
  box-shadow: 0 0 10px rgba(237, 168, 59, .7);
  transition: transform 760ms cubic-bezier(.65, 0, .35, 1);
}
/* the tracer stretches along its travel and snaps back on arrival */
.track.is-moving .track-dot { transform: scaleY(2.6); }

/* a hairline runs out under the row as it locks, then clears */
.division::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: linear-gradient(90deg, var(--sodium), transparent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  opacity: 0;
  pointer-events: none;
}
.divisions-board.is-live .division.is-active::after { animation: lock-sweep 1200ms ease-out; }
@keyframes lock-sweep {
  0%   { transform: scaleX(0); opacity: 0; }
  22%  { opacity: .55; }
  60%  { transform: scaleX(1); opacity: .4; }
  100% { transform: scaleX(1); opacity: 0; }
}

/* With the taglines gone the names carry the row on their own, so they take
   their natural width instead of sitting in a 150px column. */
.division-name {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 24px;
  letter-spacing: .02em;
  color: var(--bone);
}
.division.is-active .division-name { color: var(--white); }

/* ══════════════════════════════════════════════════════════════════════
   Responsive. The 1280px board is the reference. Below 1080px the split
   stacks: statement first, division board beneath it.
   ══════════════════════════════════════════════════════════════════════ */

@media (max-width: 1080px) {
  .board { grid-template-columns: 1fr; }
  .statement {
    border-right: none;
    border-bottom: 1px solid var(--graphite);
    padding: 64px 40px 52px;
  }
  .statement h1 { font-size: clamp(46px, 8.4vw, 86px); }
  .panel { min-height: 520px; }
}

@media (max-width: 720px) {
  :root { --bar-x: 20px; }

  .wordmark { width: 132px; }
  .bar-bottom { flex-direction: column; align-items: flex-start; gap: 10px; line-height: 1.4; }

  .board { min-height: 0; }
  .statement { padding: 48px 20px 44px; }
  .statement h1 { font-size: clamp(40px, 11.5vw, 64px); }
  .lb { display: none; }

  .lede { margin-top: 24px; font-size: 16px; }

  .capture { margin-top: 40px; padding: 20px 20px 18px; }
  .capture-row { flex-direction: column; }
  .capture-btn { padding: 13px 22px; }

  .panel-inner { padding: 56px 20px 48px; }
  .panel { min-height: 0; }

  .panel-field { transform: scale(.68); transform-origin: 100% 0; }

  .division { padding: 18px 0; }
  .division-name { font-size: 22px; }
}

/* Motion is a signature here, not decoration, but it yields on request. */
@media (prefers-reduced-motion: reduce) {
  .orbit-1, .orbit-2, .orbit-3 { animation: none; }
  .status-dot { animation: none; }
  /* The board stops walking (app.js holds it on Defense) and the field stops
     answering, so nothing here should be mid-flight. */
  .ping, .panel-field.is-lock .ping,
  .panel-field.is-lock .body-star,
  .panel-field.is-lock .ring-3,
  .division.is-active::after,
  .divisions-board.is-live .division.is-active::after { animation: none; }
  .track, .track-dot { transition: none; }
  *, *::before, *::after { transition-duration: .01ms !important; }
}
