/**
 * Retire — holding page.
 *
 * The app's design system, ported off Tailwind and onto plain CSS. Token names,
 * values, type roles, easing and component anatomy are copied from
 * `webapp/src/app/globals.css`, `tailwind.config.ts` and `shared/ui/*` so this
 * page is the same brand rather than an impression of it. Change the palette in
 * one place — the two token blocks below — and it propagates, exactly as it does
 * in the app.
 */

/* ------------------------------------------------------------------ fonts --
 * Self-hosted, latin subset, both variable. Fraunces is requested with its full
 * axis set: `opsz` is a real optical-size axis, and the type roles below drive
 * it per role. Without it every size gets the same middling drawing, which is
 * why serif headings so often look flat.
 */
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Fraunces';
  src: url('../fonts/fraunces-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Fraunces';
  src: url('../fonts/fraunces-italic-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}

/* ----------------------------------------------------------------- tokens --
 * Semantic HSL channels without alpha, so any of them can be used at partial
 * opacity. A warm, heritage scheme: deep ink-green grounds, ivory type, a
 * champagne-gold accent used sparingly. Dark is the primary experience; light
 * is the ivory-paper counterpart.
 */
:root {
  --background: 40 33% 95%;
  --surface: 40 44% 99%;
  --surface-muted: 40 26% 92%;
  --border: 40 20% 85%;
  --foreground: 156 34% 12%;
  --muted: 155 12% 38%;

  --primary: 158 52% 24%;
  --primary-foreground: 40 44% 98%;
  --accent: 38 46% 46%;
  --accent-foreground: 40 44% 98%;

  --success: 158 52% 30%;
  --warning: 34 68% 44%;

  --radius: 0.75rem;
  --glow-a: 158 52% 24%;
  --glow-b: 38 46% 46%;

  /* The campaign stills are near-black frames; on ivory paper they read as a
     hole punched in the page, so there they drop to a ghost. */
  --backdrop-opacity: 0.14;
  --backdrop-grayscale: 1;
  /* The watermark carries further on paper than it does on ink; the dark theme
     needs a lighter hand or it stops being a texture and starts being copy. */
  --bloodline-opacity: 0.05;
  --luxe: cubic-bezier(0.22, 1, 0.36, 1);
  --measure: 64rem;
}

.dark {
  --background: 150 14% 5%;
  --surface: 150 12% 8%;
  --surface-muted: 150 10% 12%;
  --border: 150 9% 16%;
  --foreground: 40 30% 92%;
  --muted: 150 8% 58%;

  --primary: 158 46% 44%;
  --primary-foreground: 150 30% 6%;
  --accent: 40 58% 62%;
  --accent-foreground: 150 30% 6%;

  --success: 158 46% 48%;
  --warning: 40 70% 58%;

  --glow-a: 158 60% 30%;
  --glow-b: 40 58% 52%;
  --backdrop-opacity: 0.45;
  --backdrop-grayscale: 0.9;
  --bloodline-opacity: 0.028;
}

/* ------------------------------------------------------------------- base -- */
*,
*::before,
*::after {
  box-sizing: border-box;
  border: 0 solid hsl(var(--border));
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: hsl(var(--background));
  color: hsl(var(--foreground));
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-feature-settings: 'cv11', 'ss01';
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Layered ambient depth: two large, very soft radial glows fixed behind
   everything, giving the flat ground a "lit room" quality. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(60rem 60rem at 12% -10%, hsl(var(--glow-a) / 0.14), transparent 60%),
    radial-gradient(50rem 50rem at 100% 8%, hsl(var(--glow-b) / 0.1), transparent 55%);
}

img,
video {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
  text-decoration: none;
}

::selection {
  background: hsl(var(--accent) / 0.28);
  color: hsl(var(--foreground));
}

* {
  scrollbar-width: thin;
  scrollbar-color: hsl(var(--border)) transparent;
}
*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
*::-webkit-scrollbar-thumb {
  background-color: hsl(var(--border));
  border-radius: 9999px;
  border: 3px solid transparent;
  background-clip: content-box;
}

:focus-visible {
  outline: 2px solid hsl(var(--accent));
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  z-index: 80;
}
.skip-link:focus {
  left: 1rem;
  top: 1rem;
  padding: 0.5rem 1rem;
  border-radius: calc(var(--radius) - 4px);
  background: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* ------------------------------------------------------------------- type --
 * Six roles, not a pile of ad-hoc sizes. Each is a composition — family,
 * optical size, weight, tracking, leading and numerals together. Sizes are
 * fluid rather than breakpoint-stepped, and the lower bound of each clamp is
 * the phone value, which is the one designed first.
 */
h1,
h2 {
  font-family: 'Fraunces', Georgia, serif;
  letter-spacing: -0.02em;
  margin: 0;
}
h3,
h4,
p,
figure,
ul {
  margin: 0;
}

.type-display {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(2.75rem, 1.9rem + 4.2vw, 4.5rem);
  font-weight: 600;
  font-variation-settings: 'opsz' 144, 'wght' 600, 'SOFT' 0, 'WONK' 0;
  line-height: 0.9;
  letter-spacing: -0.032em;
  font-variant-numeric: tabular-nums lining-nums;
}

.type-figure {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(1.75rem, 1.5rem + 1.1vw, 2.125rem);
  font-weight: 600;
  font-variation-settings: 'opsz' 72, 'wght' 600, 'SOFT' 0, 'WONK' 0;
  line-height: 1;
  letter-spacing: -0.022em;
  font-variant-numeric: tabular-nums lining-nums;
}

.type-title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(1.75rem, 1.4rem + 1.6vw, 2.375rem);
  font-weight: 600;
  font-variation-settings: 'opsz' 48, 'wght' 600, 'SOFT' 20, 'WONK' 0;
  line-height: 1.1;
  letter-spacing: -0.021em;
}

.type-heading {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.0625rem;
  font-weight: 600;
  font-variation-settings: 'opsz' 24, 'wght' 600, 'SOFT' 40, 'WONK' 0;
  line-height: 1.3;
  letter-spacing: -0.012em;
}

.type-label {
  font-size: 0.6875rem;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* Tickers keep the casing their issuer chose.
 *
 * `$TripleT` is deliberately camel-cased, and the label role uppercases
 * everything — which would silently render it `$TRIPLET`, a different
 * wordmark. `$RETIRE` and `$TROLL` are upper-case on their own, so nothing
 * about the row's look changes; only the one ticker that carries information
 * in its capitals keeps it. */
.type-label--ticker {
  text-transform: none;
}

.type-body {
  font-size: 0.9375rem;
  line-height: 1.65;
  letter-spacing: -0.004em;
}

.type-numeric {
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.006em;
}

.text-muted {
  color: hsl(var(--muted));
}
.text-accent {
  color: hsl(var(--accent));
}

/* Gradient ink for display headlines: ivory running into gold. */
.text-gradient {
  background-image: linear-gradient(120deg, hsl(var(--foreground)), hsl(var(--accent)));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The one typographic signature: a heavy uppercase sans statement interrupted
   by the serif in italic, given a display optical size so its contrast holds up
   next to Inter Black instead of looking limp. */
.statement {
  font-weight: 900;
  text-transform: uppercase;
  font-size: clamp(2.5rem, 1.4rem + 5.4vw, 4rem);
  line-height: 0.94;
  letter-spacing: -0.028em;
  margin: 0;
  font-family: 'Inter', system-ui, sans-serif;
}
.statement em {
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-variation-settings: 'opsz' 144, 'wght' 600, 'SOFT' 0, 'WONK' 1;
  text-transform: none;
  letter-spacing: -0.02em;
}

/* ---------------------------------------------------------------- layout -- */
.shell {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: 1rem;
}
@media (min-width: 640px) {
  .shell {
    padding-inline: 1.5rem;
  }
}

main {
  display: block;
  padding-block: 2rem 4rem;
}

.stack > * + * {
  margin-top: 1.5rem;
}
.stack-lg > * + * {
  margin-top: 3.5rem;
}

/* ---------------------------------------------------------------- header -- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  height: 4rem;
  display: flex;
  align-items: center;
  border-bottom: 1px solid hsl(var(--border));
  background: hsl(var(--background) / 0.7);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
.site-header .shell {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  border-radius: calc(var(--radius) - 4px);
  padding: 0.25rem;
}
.brand__mark {
  display: flex;
  height: 2.25rem;
  width: 2.25rem;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  background: hsl(var(--foreground));
  color: hsl(var(--background));
  box-shadow: 0 4px 20px -4px hsl(150 20% 4% / 0.12);
  transition: transform 0.3s var(--luxe);
}
.brand:hover .brand__mark {
  background: hsl(var(--accent));
  color: hsl(var(--accent-foreground));
}
.brand__mark svg {
  height: 1.15rem;
  width: 1.15rem;
}

/* The wordmark is set lowercase and tight, against the wide-tracked uppercase
   the campaign art uses. That contrast is deliberate: the burned-in RETIRE on
   the plates is campaign type — poster-scale, made to be photographed — and
   repeating it at 17px in a header gives you the worst of both, a shout too
   small to hear. `onsol` drops to the accent at the same weight, not a lighter
   one: splitting a single word by weight makes it read as two words, splitting
   it by colour alone keeps it one. */
.brand__word {
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.015em;
}
.brand__word i {
  font-style: normal;
  color: hsl(var(--accent));
}

.site-nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.25rem;
}
.site-nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  /* 2.5rem tall rather than the 2rem the padding alone gave. Header nav is the
     one place on a phone where a mis-tap costs you the page you were reading. */
  min-height: 2.5rem;
  border-radius: calc(var(--radius) - 4px);
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: hsl(var(--muted));
  transition: color 0.2s, background-color 0.2s;
}
.site-nav a::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  height: 1rem;
  width: 2px;
  transform: translateY(-50%);
  border-radius: 9999px;
  background: hsl(var(--accent));
  opacity: 0;
  transition: opacity 0.3s;
}
.site-nav a:hover {
  color: hsl(var(--foreground));
  background: hsl(var(--surface-muted));
}
.site-nav a[aria-current='page'] {
  color: hsl(var(--foreground));
  background: hsl(var(--accent) / 0.1);
}
.site-nav a[aria-current='page']::before {
  opacity: 1;
}
@media (max-width: 30rem) {
  .site-nav a.is-optional {
    display: none;
  }
}

/* --------------------------------------------------------------- buttons -- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  overflow: hidden;
  border-radius: calc(var(--radius) - 4px);
  height: 2.75rem;
  padding-inline: 1.5rem;
  font-family: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: all 0.3s var(--luxe);
}
.btn:hover {
  transform: translateY(-1px);
}
.btn:active {
  transform: none;
}
.btn--lg {
  height: 3rem;
  padding-inline: 2rem;
  font-size: 1rem;
}
.btn--sm {
  height: 2.25rem;
  padding-inline: 1rem;
}
.btn > span {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.btn--primary {
  background: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
  box-shadow: 0 4px 20px -4px hsl(150 20% 4% / 0.28), 0 2px 6px -2px hsl(150 20% 4% / 0.18);
}
.btn--primary:hover {
  box-shadow: 0 18px 50px -12px hsl(150 24% 4% / 0.4), 0 6px 16px -8px hsl(150 20% 4% / 0.25);
}
.btn--secondary {
  border: 1px solid hsl(var(--border));
  background: hsl(var(--surface));
  color: hsl(var(--foreground));
  box-shadow: 0 1px 2px 0 hsl(150 20% 4% / 0.06);
}
.btn--secondary:hover {
  border-color: hsl(var(--accent) / 0.4);
  background: hsl(var(--surface-muted));
}
.btn--ghost {
  background: transparent;
  color: hsl(var(--foreground));
}
.btn--ghost:hover {
  background: hsl(var(--surface-muted));
}

/* Filled variants get a slow diagonal sweep of light on hover — the small
   light-passing-over-metal cue that reads as premium. */
.btn--primary::after {
  content: '';
  position: absolute;
  inset-block: 0;
  left: -33%;
  width: 33%;
  transform: skewX(-12deg);
  background: hsl(0 0% 100% / 0.25);
  filter: blur(12px);
  opacity: 0;
  transition: opacity 0.2s;
}
.btn--primary:hover::after {
  opacity: 1;
  animation: shine 0.9s ease-out;
}

/* ----------------------------------------------------------------- cards -- */
.card {
  border: 1px solid hsl(var(--border));
  border-radius: var(--radius);
  background: hsl(var(--surface));
  padding: 1.5rem;
  box-shadow:
    0 4px 20px -4px hsl(150 20% 4% / 0.12),
    0 2px 6px -2px hsl(150 20% 4% / 0.08),
    inset 0 0 0 1px hsl(var(--accent) / 0.14);
}
.card--interactive {
  transition: transform 0.3s var(--luxe), border-color 0.3s, box-shadow 0.3s;
}
.card--interactive:hover {
  transform: translateY(-4px);
  border-color: hsl(var(--accent) / 0.4);
  box-shadow:
    0 18px 50px -12px hsl(150 24% 4% / 0.28),
    0 6px 16px -8px hsl(150 20% 4% / 0.18),
    inset 0 0 0 1px hsl(var(--accent) / 0.14);
}

.grid {
  display: grid;
  gap: 1rem;
}
@media (min-width: 48rem) {
  .grid--3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .grid--2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.callout {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  border: 1px solid hsl(var(--primary) / 0.3);
  border-radius: calc(var(--radius) - 4px);
  background: hsl(var(--primary) / 0.06);
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  line-height: 1.6;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  border: 1px solid hsl(var(--border));
  border-radius: 9999px;
  background: hsl(var(--background) / 0.6);
  padding: 0.375rem 1rem 0.375rem 0.375rem;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.pill__mark {
  display: flex;
  height: 1.5rem;
  width: 1.5rem;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: hsl(var(--foreground));
  color: hsl(var(--background));
}
.pill__mark svg {
  height: 0.875rem;
  width: 0.875rem;
}

/* The launch state, said above the fold.
 *
 * The hero pill names the coins; this one names the status, and they sit side
 * by side rather than one inside the other because they answer two different
 * questions. A visitor who reads nothing else should still leave knowing the
 * doors are shut — the page is a promise, and a promise that does not say it is
 * a promise reads as a product you failed to find the login for. */
.pill-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.pill--status {
  gap: 0.5rem;
  padding: 0.375rem 0.875rem;
  border-color: hsl(var(--accent) / 0.4);
  background: hsl(var(--accent) / 0.08);
}
.pill--status .type-label {
  color: hsl(var(--accent));
}
/* A slow pulse, not a blink. It reads as "live and being worked on" rather
   than as a notification demanding to be cleared. */
.pill__dot {
  display: block;
  height: 0.4375rem;
  width: 0.4375rem;
  flex: none;
  border-radius: 9999px;
  background: hsl(var(--accent));
  box-shadow: 0 0 0 0 hsl(var(--accent) / 0.55);
  animation: pulse 2.6s var(--luxe) infinite;
}
@media (prefers-reduced-motion: reduce) {
  .pill__dot {
    animation: none;
  }
}

/* Eyebrow with its gold tick, exactly as `PageHeader` sets it. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  color: hsl(var(--accent));
}
.eyebrow::before {
  content: '';
  height: 1px;
  width: 1.5rem;
  background: hsl(var(--accent) / 0.5);
}

.page-header {
  margin-bottom: 2.5rem;
  border-bottom: 1px solid hsl(var(--border));
  padding-bottom: 1.5rem;
}
.page-header > * + * {
  margin-top: 0.625rem;
}

/* ------------------------------------------------------------------ hero -- */
.hero {
  position: relative;
  overflow: hidden;
  border: 1px solid hsl(var(--border));
  border-radius: 1rem;
  background: hsl(var(--surface) / 0.4);
  padding: 3.5rem 1.5rem;
  box-shadow:
    0 4px 20px -4px hsl(150 20% 4% / 0.12),
    inset 0 0 0 1px hsl(var(--accent) / 0.14);
}
@media (min-width: 640px) {
  .hero {
    padding: 5rem 2.5rem;
  }
}
.hero__content {
  position: relative;
}
.hero__content > * + * {
  margin-top: 1.5rem;
}

/* The garment loop, blurred hard. The clip has RETIRE printed across the fabric
   itself; at full resolution those wordmarks sit behind the headline and fight
   it. Blurred, it becomes what a backdrop should be — slow light on material. */
.backdrop {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.backdrop__media {
  position: absolute;
  inset: 0;
  filter: blur(14px);
  transform: scale(1.24);
}
.backdrop__media img,
.backdrop__media video {
  position: absolute;
  inset: 0;
  height: 100%;
  width: 100%;
  object-fit: cover;
  object-position: center 45%;
  opacity: var(--backdrop-opacity);
  filter: grayscale(var(--backdrop-grayscale)) contrast(1.05);
}
.backdrop__media video {
  opacity: 0;
  transition: opacity 0.8s var(--luxe);
}
.backdrop__media video.is-ready {
  opacity: var(--backdrop-opacity);
}
/* Reading scrim in two passes, thinning toward the top-right — the one quadrant
   with no copy over it, and so the only place the asset reads as an image. */
.backdrop::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      to right,
      hsl(var(--background)),
      hsl(var(--background) / 0.85) 45%,
      hsl(var(--background) / 0.2)
    ),
    linear-gradient(to top, hsl(var(--background)), hsl(var(--background) / 0.15) 55%, transparent);
}
.backdrop__wash {
  position: absolute;
  inset: 0;
  mix-blend-mode: soft-light;
  background: radial-gradient(55rem 40rem at 88% 18%, hsl(var(--accent) / 0.45), transparent 65%);
}

/* The signature outline watermark. */
.bloodline {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.25rem;
  overflow: hidden;
  user-select: none;
  pointer-events: none;
  opacity: var(--bloodline-opacity);
  transform: skewY(-8deg) scale(1.4);
}
.bloodline p {
  white-space: nowrap;
  font-size: 2.25rem;
  font-weight: 900;
  text-transform: uppercase;
  line-height: 1;
  letter-spacing: -0.025em;
  -webkit-text-stroke: 1px currentColor;
  -webkit-text-fill-color: transparent;
  color: hsl(var(--foreground));
}
@media (min-width: 640px) {
  .bloodline p {
    font-size: 3.75rem;
  }
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}
/* On a phone two buttons of different widths read as a ragged edge, not as a
   hierarchy. Below the fold of a 6" screen they go full width and stack. */
@media (max-width: 32rem) {
  .hero__actions .btn {
    width: 100%;
  }
}
.hero__fine {
  font-size: 0.75rem;
  line-height: 1.6;
  color: hsl(var(--muted));
  max-width: 34rem;
}

/* ---------------------------------------------------------------- status -- */
.status__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}
.progress {
  position: relative;
  height: 6px;
  width: 100%;
  overflow: hidden;
  border-radius: 9999px;
  background: hsl(var(--surface-muted));
  box-shadow: inset 0 0 0 1px hsl(var(--border));
}
.progress__fill {
  position: absolute;
  inset-block: 0;
  left: 0;
  width: 0;
  border-radius: 9999px;
  background: linear-gradient(90deg, hsl(var(--primary)), hsl(var(--accent)));
  transition: width 1.6s var(--luxe);
}
/* A slow highlight travelling the filled span: the page is a status board, and
   this is the only thing on it that says "still moving". */
.progress__fill::after {
  content: '';
  position: absolute;
  inset-block: 0;
  left: -40%;
  width: 40%;
  background: linear-gradient(90deg, transparent, hsl(0 0% 100% / 0.35), transparent);
  animation: sweep 2.8s var(--luxe) infinite;
}

.phases {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}
@media (min-width: 40rem) {
  .phases {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.75rem 2rem;
  }
}
.phase {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: hsl(var(--muted));
}
.phase__dot {
  margin-top: 0.3rem;
  height: 0.6rem;
  width: 0.6rem;
  flex: none;
  border-radius: 9999px;
  border: 2px solid hsl(var(--border));
}
.phase--done .phase__dot {
  background: hsl(var(--success));
  border-color: hsl(var(--success));
}
.phase--done {
  color: hsl(var(--foreground));
}
.phase--active .phase__dot {
  background: hsl(var(--accent));
  border-color: hsl(var(--accent));
  box-shadow: 0 0 0 0 hsl(var(--accent) / 0.6);
  animation: pulse 2.4s var(--luxe) infinite;
}
.phase--active {
  color: hsl(var(--foreground));
}

/* ----------------------------------------------------------------- plate --
 * A campaign piece presented as itself: a dark plate mounted on the page.
 * `object-fit: contain` on a black ground, deliberately — every asset carries
 * its own burned-in lockup, so cropping would cut the wordmark.
 */
.plate {
  position: relative;
  overflow: hidden;
  border: 1px solid hsl(var(--border));
  border-radius: var(--radius);
  background: hsl(150 14% 4%);
  box-shadow: 0 4px 20px -4px hsl(150 20% 4% / 0.16), 0 2px 6px -2px hsl(150 20% 4% / 0.1);
}
.plate > img,
.plate > video {
  position: absolute;
  inset: 0;
  height: 100%;
  width: 100%;
  object-fit: contain;
}
/* Inner vignette + gold hairline: sets the plate *into* the page rather than
   leaving it sitting on the surface as a pasted rectangle. */
.plate::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 6rem 1rem hsl(150 20% 2% / 0.55), inset 0 0 0 1px hsl(var(--accent) / 0.16);
}
.plate figcaption,
figure > figcaption {
  margin-top: 0.75rem;
  color: hsl(var(--muted));
}

/* ----------------------------------------------------------------- video -- */
.film {
  position: relative;
}
.film__frame {
  aspect-ratio: 16 / 9;
}
/* ------------------------------------------------------------ media -- */
/* One plaque, not two floating circles.
 *
 * The app landed on this treatment first and the landing page follows it: a
 * single frosted pill in the corner holding every control, divided by a
 * hairline, with the same gold inner trim the cards wear. Two separate round
 * buttons in two corners read as two unrelated affordances someone bolted on;
 * one plaque reads as furniture that belongs to the frame.
 *
 * It never fully hides. At rest it sits at 70% on pointer devices and comes to
 * full strength on hover or keyboard focus; on touch there is no hover at all,
 * so it stays at full strength permanently — `@media (hover: hover)` is what
 * expresses that difference. A control that only appears on hover is a control
 * a phone user never sees. */
.media-plaque {
  position: absolute;
  right: 0.75rem;
  bottom: 0.75rem;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 0.125rem;
  padding: 0.25rem;
  border: 1px solid hsl(0 0% 100% / 0.14);
  border-radius: 9999px;
  background: hsl(0 0% 0% / 0.45);
  box-shadow:
    0 2px 12px -2px hsl(150 20% 2% / 0.6),
    inset 0 0 0 1px hsl(var(--accent) / 0.22);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  transition: opacity 0.3s var(--luxe);
}
@media (hover: hover) {
  .media-plaque {
    opacity: 0.7;
  }
  .film:hover .media-plaque {
    opacity: 1;
  }
}
.media-plaque:focus-within {
  opacity: 1;
}

.media-btn {
  display: flex;
  height: 2.25rem;
  width: 2.25rem;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 9999px;
  background: transparent;
  color: hsl(0 0% 100% / 0.85);
  cursor: pointer;
  transition:
    background-color 0.2s var(--luxe),
    color 0.2s var(--luxe),
    transform 0.2s var(--luxe);
}
/* The hover fill covers the glyph's own cell rather than the whole plaque, so
   which control you are about to press is never ambiguous. */
.media-btn:hover {
  background: hsl(0 0% 100% / 0.1);
  color: hsl(0 0% 100%);
}
.media-btn:active {
  transform: scale(0.94);
  background: hsl(0 0% 100% / 0.14);
}
/* Inset, because an offset ring on a 4px-padded pill is clipped by its own
   container. */
.media-btn:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px hsl(var(--accent));
}
.media-btn svg {
  height: 1.05rem;
  width: 1.05rem;
}
.media-plaque__rule {
  width: 1px;
  height: 1rem;
  margin: 0 0.125rem;
  background: hsl(0 0% 100% / 0.15);
}

/* A whisper of shade under the plaque so it holds against a bright frame. It
   goes when the film starts — the film is then the subject. */
.film__scrim {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  height: 30%;
  pointer-events: none;
  background: linear-gradient(to top, hsl(150 20% 2% / 0.6), transparent);
  transition: opacity 0.5s var(--luxe);
}
.film.is-playing .film__scrim {
  opacity: 0;
}

/* ------------------------------------------------------------- coins -- */
/* The roster. One frame ratio across the row rather than each asset's native
   aspect: the three pieces are 8:5, 16:9 and 16:9, and honouring each steps the
   row up and down for no reason a viewer could name. A shared 16:9 frame with
   `object-fit: contain` costs the widest piece a few pixels of pillarbox on a
   black ground nobody will notice, and buys a row that lines up. */
.coins {
  display: grid;
  gap: 1.5rem 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 40rem) {
  .coins {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
.coin figure {
  margin: 0;
}
.coin .plate {
  aspect-ratio: 16 / 9;
}
.coin figcaption {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin-top: 0.75rem;
}
/* The engraved initial. Three unrelated illustrations shrunk to 24px would turn
   a considered page into a sticker sheet, so the small identity is a monogram
   in the display serif — one house treatment applied to each coin. */
.coin__chip {
  display: inline-flex;
  height: 1.75rem;
  width: 1.75rem;
  flex: none;
  align-items: center;
  justify-content: center;
  border: 1px solid hsl(var(--accent) / 0.3);
  border-radius: 9999px;
  background: hsl(var(--accent) / 0.1);
  color: hsl(var(--accent));
  font-family: 'Fraunces', Georgia, serif;
  font-size: 0.6875rem;
  font-variation-settings: 'opsz' 14, 'wght' 500, 'SOFT' 0, 'WONK' 0;
  letter-spacing: -0.04em;
}
.coin__name {
  display: block;
  font-size: 0.875rem;
  font-weight: 500;
  color: hsl(var(--foreground));
}
.coin__line {
  display: block;
  font-size: 0.8125rem;
  color: hsl(var(--muted));
}

/* ----------------------------------------------------------------- steps -- */
.step__index {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 2.5rem;
  font-variation-settings: 'opsz' 72, 'wght' 600, 'SOFT' 0, 'WONK' 0;
  line-height: 1;
  color: hsl(var(--accent) / 0.55);
}

/* No rule on the list itself: the section header already draws one, and two
   hairlines a paragraph apart read as an accident. */
.faq details {
  border-bottom: 1px solid hsl(var(--border));
}
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.125rem 0;
  cursor: pointer;
  list-style: none;
  font-weight: 500;
  transition: color 0.2s;
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary:hover {
  color: hsl(var(--accent));
}
.faq summary::after {
  content: '+';
  font-size: 1.25rem;
  line-height: 1;
  color: hsl(var(--accent));
  transition: transform 0.3s var(--luxe);
}
.faq details[open] summary::after {
  transform: rotate(45deg);
}
.faq details p {
  padding-bottom: 1.125rem;
  color: hsl(var(--muted));
  max-width: 46rem;
}

/* ---------------------------------------------------------------- footer -- */
.site-footer {
  border-top: 1px solid hsl(var(--border));
  background: hsl(var(--surface) / 0.4);
  padding-block: 2.5rem;
}
.site-footer .shell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  font-size: 0.875rem;
  color: hsl(var(--muted));
}
.footer__links a:hover {
  color: hsl(var(--accent));
}

.social {
  display: flex;
  gap: 0.5rem;
}
.social a {
  display: flex;
  height: 2.5rem;
  width: 2.5rem;
  align-items: center;
  justify-content: center;
  border: 1px solid hsl(var(--border));
  border-radius: calc(var(--radius) - 4px);
  color: hsl(var(--muted));
  transition: all 0.3s var(--luxe);
}
.social a:hover {
  transform: translateY(-2px);
  border-color: hsl(var(--accent) / 0.4);
  color: hsl(var(--accent));
}
.social svg {
  height: 1.125rem;
  width: 1.125rem;
}

/* ---------------------------------------------------------------- motion -- */
@keyframes rise-in {
  from {
    opacity: 0;
    transform: translateY(14px);
    filter: blur(6px);
  }
  to {
    opacity: 1;
    transform: none;
    filter: none;
  }
}
@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(6px);
    filter: blur(4px);
  }
  to {
    opacity: 1;
    transform: none;
    filter: none;
  }
}
@keyframes shine {
  from {
    transform: translateX(-120%) skewX(-12deg);
  }
  to {
    transform: translateX(220%) skewX(-12deg);
  }
}
@keyframes sweep {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(350%);
  }
}
@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 hsl(var(--accent) / 0.55);
  }
  70% {
    box-shadow: 0 0 0 8px hsl(var(--accent) / 0);
  }
  100% {
    box-shadow: 0 0 0 0 hsl(var(--accent) / 0);
  }
}

.animate-rise-in {
  animation: rise-in 0.6s var(--luxe) both;
}
.animate-fade-in {
  animation: fade-in 0.4s var(--luxe) both;
}

/* Sections arrive as you reach them, with the same rise the app uses on route
   change. Anything above the fold animates on load instead — gating the hero
   behind an observer buys nothing and stakes it on a callback firing. */
.reveal {
  opacity: 0;
}
.reveal.is-visible {
  animation: rise-in 0.7s var(--luxe) both;
}
.no-js .reveal {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal {
    opacity: 1;
  }
}

/* ---------------------------------------------------------- theme toggle -- */
.theme-toggle {
  width: 2.25rem;
  padding: 0;
}
.theme-toggle svg {
  height: 1.15rem;
  width: 1.15rem;
}
