@font-face {
  font-family: "Geist";
  src: url("/fonts/geist-300-600-latin.woff2") format("woff2");
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #0a0b0d;
  --fg: #f2f3f5;
  --muted: #9097a0;
  --subtle: #7b828b;
  --line: rgba(255, 255, 255, 0.08);
  --field-line: rgba(255, 255, 255, 0.16);
  --field-line-strong: rgba(255, 255, 255, 0.2);
  --mark: var(--fg);

  /* Generations: established, maturing, emerging. Light to brand slate, as the logo's dots fade on white. */
  --dot-1: #e6e9ee;
  --dot-2: #7d8796;
  --dot-3: #323e4f;

  --gutter: clamp(20px, 4vw, 56px);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --glide: cubic-bezier(0.55, 0, 0.15, 1);
}

/* Light: follows the visitor's system setting. The wordmark and dots take the logo's own slate and tints. */
@media (prefers-color-scheme: light) {
  :root {
    --bg: #f7f7f5;
    --fg: #14181f;
    --muted: #555c66;
    --subtle: #686f79;
    --line: rgba(20, 24, 31, 0.1);
    --field-line: rgba(20, 24, 31, 0.18);
    --field-line-strong: rgba(20, 24, 31, 0.24);
    --mark: #323e4f;
    --dot-1: #323e4f;
    --dot-2: #5b6572;
    --dot-3: #989fa7;
  }
}

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

html {
  background: var(--bg);
  color-scheme: dark light;
  -webkit-text-size-adjust: 100%;
}

body {
  position: relative;
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: var(--gutter);
  padding-bottom: max(var(--gutter), env(safe-area-inset-bottom));
  overflow-x: hidden;
  font-family: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.6;
  color: var(--muted);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1,
p {
  margin: 0;
  font: inherit;
}

.row {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px 32px;
}

.fine {
  font-size: 13px;
  color: var(--subtle);
  white-space: nowrap;
}

/* Header */

.origin {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
}

/* A small monochrome flag: white at partial strength, so it sits with the light text. */
.flag {
  display: block;
  width: 19px;
  height: 10px;
  fill: var(--fg);
  opacity: 0.55;
}

.flag-canton {
  stroke: var(--bg);
  stroke-width: 0.5;
  paint-order: stroke;
}

/* Est on top, origin beneath, both right-aligned: two short lines mirroring the two-line wordmark. */
.top-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  line-height: 1.35;
  text-align: right;
}

.top-meta p {
  margin: 0;
}

/* Phones carry the origin line in the footer instead (see the small-screen rules). */
.origin-foot {
  display: none;
}

.logo {
  width: clamp(132px, 11vw, 168px);
  line-height: 0;
}

.wordmark {
  display: block;
  width: 100%;
  height: auto;
  color: var(--mark);
  overflow: visible;
}

/* Statement */

.main {
  position: relative;
  z-index: 1;
  align-self: end;
  padding: 12vh 0 clamp(40px, 7vh, 88px);
}

.title {
  max-width: 15ch;
  font-size: clamp(36px, 5.4vw, 84px);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -0.035em;
  color: var(--fg);
  text-wrap: balance;
}

.sectors {
  --glyph: 22px;
  display: flex;
  flex-wrap: wrap;
  row-gap: 6px;
  margin: calc(clamp(24px, 2.8vw, 40px) + var(--glyph) + 12px) 0 0;
  padding: 0;
  list-style: none;
}

/* Each name is a button that lights its sector. It reserves its bold width, so lighting a sector
   never nudges its neighbours. */
.sectors .name {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: font-weight 0.6s var(--ease), color 0.3s ease;
}

.sectors .name:hover {
  color: var(--fg);
}

.sectors .name:focus-visible {
  outline: 1px solid var(--line);
  outline-offset: 4px;
  border-radius: 2px;
}

.sectors .name::after {
  content: attr(data-label);
  content: attr(data-label) / "";
  height: 0;
  overflow: hidden;
  visibility: hidden;
  font-weight: 500;
}

.sectors li.is-current .name {
  font-weight: 500;
}

/* A fine-line drawing of the lit sector, drawn in above its name. */
.glyph {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 6px);
  translate: -50% 0;
  width: var(--glyph);
  height: var(--glyph);
  overflow: visible;
  fill: none;
  stroke: var(--fg);
  stroke-width: 1.1;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s var(--ease);
}

.glyph path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 0.6s var(--ease);
}

.sectors li.is-current .glyph {
  opacity: 0.9;
}

.sectors li.is-current .glyph path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1.8s var(--glide) 0.3s;
}

/* Defense // Health // Technology // Infrastructure. The slashes are decoration, so screen readers skip them. */
.sectors li:not(:last-child)::after {
  content: "//";
  content: "//" / "";
  margin: 0 0.75em;
  color: var(--subtle);
}

/* One line about the sector currently lit. All four share one grid cell, so the space is always sized
   to the longest and nothing moves when they change. */
.sector-lines {
  display: grid;
  margin: 14px 0 0;
  font-size: 14px;
  color: var(--muted);
}

.sector-lines p {
  grid-area: 1 / 1;
  margin: 0;
  opacity: 0;
  transform: translateY(4px);
  text-wrap: balance;
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

.sector-lines p.is-current {
  opacity: 1;
  transform: none;
  transition-delay: 0.25s;
}

.foot {
  padding-top: 20px;
  border-top: 1px solid var(--line);
}

/* Generations: the logo's three dots as developments moving through the group.
   Each step, the emerging dot firms up and rises, and the established one graduates out of view.
   Without script they simply rest as the lockup's cascade. */

@property --part {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}

.gens {
  --d: clamp(60px, min(7.4vw, 11.5vh), 112px);
  --part: 0px;
  position: absolute;
  left: 74%;
  /* Centred on the headline's middle line (measured by site.js); 47% until then. */
  top: var(--hero-mid, 47%);
  z-index: 2;
  width: var(--d);
  height: calc(var(--d) * 3);
  translate: -50% -50%;
  outline: none;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  transition: scale 1.4s var(--ease), --part 0.9s var(--ease);
}

.gens:focus-visible::after {
  content: "";
  position: absolute;
  inset: -14px;
  border: 1px solid var(--line);
  border-radius: calc(var(--d) / 2 + 14px);
}

/* Each step the stack glides up one place, top first, each dot following the one above it a beat later,
   so it moves like a wave rather than a block. Leaving and arriving dots travel a full step, shrinking
   slightly as they fade, so no two dots ever overlap. */
.gen {
  --slot: 1;
  --size: 1;
  --lag: 0s;
  position: absolute;
  left: 0;
  top: var(--d);
  width: var(--d);
  height: var(--d);
  border-radius: 50%;
  background: var(--dot-3);
  transform: translateY(calc((var(--slot) - 1) * var(--d))) scale(var(--size));
  transition:
    transform 1.5s var(--glide) var(--lag),
    background-color 1.5s var(--glide) var(--lag),
    opacity 1.1s var(--glide) var(--lag),
    scale 0.35s var(--ease),
    box-shadow 0.35s ease;
  will-change: transform, opacity;
}

/* The middle dot gives under a press, so the visitor knows they have the right one: it settles in at
   once, then keeps sinking very slowly for as long as the hold lasts. Letting go eases it back (above).
   The door still waits for the full hold. */
.gen.is-pressed {
  scale: 0.94;
  box-shadow: inset 0 calc(var(--d) * 0.03) calc(var(--d) * 0.14) rgba(0, 0, 0, 0.24);
  transition:
    transform 1.5s var(--glide) var(--lag),
    background-color 1.5s var(--glide) var(--lag),
    opacity 1.1s var(--glide) var(--lag),
    scale 1.8s cubic-bezier(0.12, 0.75, 0.25, 1),
    box-shadow 1.8s cubic-bezier(0.12, 0.75, 0.25, 1);
}

/* Dots waiting below or leaving above are invisible; they must not catch presses either. */
.gen[data-slot="-1"],
.gen[data-slot="3"] {
  pointer-events: none;
}

.gen[data-slot="-1"] {
  --slot: -1;
  --size: 0.72;
  opacity: 0;
  background: var(--dot-1);
}

.gen[data-slot="0"] {
  --slot: 0;
  --lag: 0.06s;
  background: var(--dot-1);
}

.gen[data-slot="1"] {
  --slot: 1;
  --lag: 0.12s;
  background: var(--dot-2);
}

.gen[data-slot="2"] {
  --slot: 2;
  --lag: 0.18s;
}

.gen[data-slot="3"] {
  --slot: 3;
  --size: 0.72;
  opacity: 0;
}

.gen.is-jump {
  transition: none;
}

/* The door: the stack parts, top and bottom dots stepping aside around the panel. */

.gens.is-open {
  pointer-events: none;
}

.gens.is-open .gen,
.gens.is-hushed .gen {
  --lag: 0s;
}

.gens.is-open .gen[data-slot="0"] {
  transform: translateY(calc(-1 * var(--part)));
}

.gens.is-open .gen[data-slot="1"] {
  opacity: 0;
  transform: scale(0.4);
}

.gens.is-open .gen[data-slot="2"] {
  transform: translateY(var(--part));
}

.gens.is-hushed .gen {
  opacity: 0;
}

.sectors li {
  transition: color 1.2s var(--ease);
}

.sectors li.is-current {
  color: var(--fg);
}

.main {
  transition: opacity 0.6s var(--ease);
}

.is-door-open .main {
  opacity: 0.12;
}

.door {
  position: absolute;
  left: 74%;
  /* Centred on the headline's middle line (measured by site.js); 47% until then. */
  top: var(--hero-mid, 47%);
  z-index: 3;
  width: min(340px, calc(100vw - 2 * var(--gutter)));
  translate: -50% -50%;
  opacity: 0;
  transition: opacity 0.6s var(--ease);
}

.door.is-shown {
  opacity: 1;
}

.door[hidden],
.door [hidden] {
  display: none;
}

.door-close {
  position: absolute;
  top: -44px;
  right: -8px;
  width: 32px;
  height: 32px;
  padding: 8px;
  border: 0;
  background: none;
  color: var(--subtle);
  cursor: pointer;
}

.door-close:hover,
.door-close:focus-visible {
  color: var(--fg);
}

.door svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.door form {
  display: grid;
}

.door-label {
  margin: 0 0 6px;
  font-size: 12px;
  color: var(--subtle);
}

.door-hello {
  margin: 0 0 28px;
  font-size: 15px;
  color: var(--fg);
}

.door input,
.door textarea {
  width: 100%;
  margin: 0 0 22px;
  padding: 6px 0 10px;
  border: 0;
  border-bottom: 1px solid var(--field-line);
  border-radius: 0;
  background: none;
  color: var(--fg);
  font: inherit;
  font-size: 15px;
  outline: none;
  resize: none;
  transition: border-color 0.3s ease;
}

.door input:focus,
.door textarea:focus {
  border-bottom-color: var(--fg);
}

.door-line {
  display: flex;
  align-items: flex-end;
  gap: 12px;
}

.door-line input {
  margin: 0;
  font-size: 18px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}

.door-go {
  flex: none;
  width: 36px;
  height: 36px;
  padding: 9px;
  border: 1px solid var(--field-line);
  border-radius: 50%;
  background: none;
  color: var(--fg);
  cursor: pointer;
  transition: border-color 0.3s ease, background-color 0.3s ease;
}

.door-go:hover,
.door-go:focus-visible {
  border-color: var(--fg);
  outline: none;
}

.door-send {
  justify-self: start;
  margin-top: 6px;
  padding: 10px 22px;
  border: 1px solid var(--field-line-strong);
  border-radius: 999px;
  background: none;
  color: var(--fg);
  font: inherit;
  cursor: pointer;
  transition: border-color 0.3s ease, background-color 0.3s ease, color 0.3s ease;
}

.door-send:hover,
.door-send:focus-visible {
  border-color: var(--fg);
  background: var(--fg);
  color: var(--bg);
  outline: none;
}

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

.door-done {
  margin: 0;
  font-size: 15px;
  color: var(--fg);
  text-align: center;
}

.door.is-busy {
  pointer-events: none;
}

.door.is-busy form {
  opacity: 0.5;
}

.door-code.is-wrong .door-line {
  animation: nope 0.42s ease;
}

@keyframes nope {
  20% { transform: translateX(-6px); }
  45% { transform: translateX(5px); }
  70% { transform: translateX(-3px); }
}

/* Entrance */

@media (prefers-reduced-motion: no-preference) {
  /* backwards, not both: once in, elements return to their own opacity so states can dim them. */
  .in {
    animation: in 1.2s var(--ease) backwards;
  }

  .d1 { animation-delay: 0.1s; }
  .d2 { animation-delay: 0.35s; }
  .d3 { animation-delay: 0.6s; }
  .d4 { animation-delay: 0.85s; }

  .wordmark .dot {
    transform-box: fill-box;
    transform-origin: center;
    animation: in 1s var(--ease) backwards;
  }

  .wordmark .dot-1 { animation-delay: 0.5s; }
  .wordmark .dot-2 { animation-delay: 0.62s; }
  .wordmark .dot-3 { animation-delay: 0.74s; }

  /* On load each dot flickers on like an old bulb catching: a faint catch, a drop, a brighter sputter,
     a dip, then steady. Top dot first, each a beat later, so at most two are ever mid-flicker together.
     Runs once; site.js lifts .is-igniting before the first generation step. */
  .gens.is-igniting .gen[data-slot="0"],
  .gens.is-igniting .gen[data-slot="1"],
  .gens.is-igniting .gen[data-slot="2"] {
    animation: ignite 0.9s linear backwards;
  }

  .gens.is-igniting .gen[data-slot="0"] { animation-delay: 0.35s; }
  .gens.is-igniting .gen[data-slot="1"] { animation-delay: 0.52s; }
  .gens.is-igniting .gen[data-slot="2"] { animation-delay: 0.69s; }
}

@keyframes ignite {
  0%, 8% { opacity: 0; }
  9%, 15% { opacity: 0.5; }
  16%, 39% { opacity: 0; }
  40%, 46% { opacity: 0.85; }
  47%, 57% { opacity: 0.2; }
  58%, 100% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .gen,
  .gen.is-pressed {
    transition: opacity 0.4s ease, background-color 0.4s ease, scale 0.2s ease, box-shadow 0.2s ease;
  }

  .glyph path,
  .sectors li.is-current .glyph path {
    stroke-dashoffset: 0;
    transition: none;
  }
}

@keyframes in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Small screens: the stack moves into the open space above the statement,
   and the door takes the middle of the screen. */

@media (max-width: 720px) {
  /* Phones: the dots turn ninety degrees into a row just above the statement, in the small RSG mark's
     order (emerging left, established right). Generations arrive from the left and graduate out to the
     right, so the motion reads as forward progress. */
  body {
    grid-template-rows: auto 1fr auto auto;
  }

  .gens {
    --d: clamp(34px, 10.5vw, 52px);
    position: relative;
    left: auto;
    top: auto;
    grid-row: 2;
    justify-self: start;
    align-self: end;
    width: calc(var(--d) * 3);
    height: var(--d);
    margin: 32px 0 30px;
    translate: none;
  }

  .gen {
    top: 0;
    left: var(--d);
    transform: translateX(calc((1 - var(--slot)) * var(--d))) scale(var(--size));
  }

  /* While the door is open on a phone the row simply fades where it is. */
  .gens.is-open .gen[data-slot] {
    transform: translateX(calc((1 - var(--slot)) * var(--d))) scale(var(--size));
  }

  .main {
    grid-row: 3;
    padding-top: 8px;
  }

  .foot {
    grid-row: 4;
  }

  .door {
    position: fixed;
    inset: 0;
    width: auto;
    display: grid;
    align-content: center;
    padding: 96px var(--gutter) 40px;
    overflow-y: auto;
    background: var(--bg);
    translate: none;
  }

  .door-close {
    position: fixed;
    top: calc(var(--gutter) - 6px);
    right: calc(var(--gutter) - 8px);
  }

  .is-door-open .head {
    z-index: 4;
    pointer-events: none;
  }

  /* Keep Defense // Health // Technology // Infrastructure on one line on phones. */
  .sectors {
    --glyph: 20px;
    font-size: 13px;
  }

  .sectors li:not(:last-child)::after {
    margin: 0 0.5em;
  }

  /* The origin line is too long to sit beside the wordmark on a phone: the header keeps Est, and the
     origin moves to the foot as its own line. */
  .top-meta .origin {
    display: none;
  }

  .foot .origin-foot {
    display: flex;
  }

  .foot {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
}

/* 404 */

.missing {
  grid-template-rows: 1fr;
}

.missing-main {
  align-self: center;
  justify-self: center;
  text-align: center;
}

.missing-note {
  margin: 0 0 24px;
}

.missing-link {
  color: var(--fg);
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  padding-bottom: 4px;
}

.missing-link:hover,
.missing-link:focus-visible {
  border-bottom-color: var(--fg);
}

/* The very narrowest phones (320px): one more notch so the sectors still sit on one line. */
@media (max-width: 340px) {
  .sectors {
    font-size: 11.5px;
  }

  .sectors li:not(:last-child)::after {
    margin: 0 0.3em;
  }
}
