/* Twistr — the design system.
 *
 * Editorial rather than crypto: a lot of white, one strong typeface, hairline
 * rules, and almost no chrome. The interface is black on white. The four
 * colours belong to the mechanic — a colour on this page always means a colour
 * on the wheel, never a mood, a status or a gradient. That is the only rule
 * the palette has, and everything else follows from it.
 */

:root {
  /* --ground is the page; --bg is the white of the things sitting on it. They
     were one token, so lifting the page off white would have taken the nav
     pill, the cards and the gate with it. */
  --ground:    #FAF9F6;
  --bg:        #FFFFFF;
  --tint:      #F7F7F5;
  --card:      #FFFFFF;
  --field:     #F3F3F1;
  --line:      #E8E8E4;
  --line-hi:   #D2D2CC;

  --ink:       #101114;
  --ink-soft:  #2C2E33;
  --prose:     #4C5058;
  --muted:     #767A82;
  --dim:       #A2A6AD;

  --red:       #E4322B;
  --yellow:    #FDD208;
  --green:     #2FA84F;
  --blue:      #1B75BC;

  --r:         16px;
  --r-sm:      10px;
  --sans:      "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono:      "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --sh-sm:     0 1px 2px rgba(16, 17, 20, .04), 0 6px 18px -14px rgba(16, 17, 20, .3);
  --sh:        0 1px 3px rgba(16, 17, 20, .05), 0 18px 40px -28px rgba(16, 17, 20, .35);
  --sh-lg:     0 2px 6px rgba(16, 17, 20, .05), 0 44px 80px -44px rgba(16, 17, 20, .45);

  --nav-h:     64px;
  --nav-gap:   14px;   /* how far the panel floats off the top and the sides */
  --ease:      cubic-bezier(.22, .68, .28, 1);
}

/* ---------- the ground ----------
 *
 * Flat white read as unfinished. This is the least that fixes it: a fine dot
 * grid for grain, and four very faint blooms in the wheel's own colours — the
 * palette rule holds even here, a colour on this page always means a colour on
 * the wheel. Fixed rather than scrolled, so the page travels across it.
 *
 * Every number is deliberately low. At .05 the dots are texture; at .12 they
 * are a pattern competing with the type, and the whole point is that nobody
 * should notice this directly.
 */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    radial-gradient(rgba(16, 17, 20, .05) 1px, transparent 1px),
    radial-gradient(52rem 34rem at 8% -4%, rgba(228, 50, 43, .05), transparent 64%),
    radial-gradient(46rem 30rem at 95% 6%, rgba(253, 210, 8, .07), transparent 62%),
    radial-gradient(50rem 34rem at 88% 62%, rgba(27, 117, 188, .05), transparent 64%),
    radial-gradient(44rem 30rem at 4% 82%, rgba(47, 168, 79, .05), transparent 64%);
  background-size: 22px 22px, auto, auto, auto, auto;
}
@media (prefers-reduced-transparency: reduce) {
  body::before { display: none; }
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { scroll-behavior: smooth; }

body {
  margin: 0; background: var(--ground); color: var(--ink);
  font: 400 16px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -0.035em; line-height: 1.02; }
h1 { font-size: clamp(52px, 8.5vw, 104px); letter-spacing: -0.05em; }
h2 { font-size: clamp(28px, 3.6vw, 44px); }
h3 { font-size: 19px; letter-spacing: -0.02em; }
p { margin: 0; }
a { color: inherit; text-decoration: none; }

.sp-wrap { width: min(1200px, 100% - 48px); margin-inline: auto; }
.sp-wrap-narrow { width: min(780px, 100% - 48px); }

.sp-sr, .sp-skip {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.sp-skip:focus {
  position: fixed; top: calc(var(--nav-h) + var(--nav-gap) * 2); left: 24px; z-index: 90; width: auto; height: auto;
  clip: auto; clip-path: none; background: var(--ink); color: #fff;
  padding: 10px 14px; border-radius: 999px; font-size: 14px;
}

.sp-kicker {
  font: 600 11px/1 var(--sans); letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted);
}
.sp-kicker-sm { font-size: 10px; }
.sp-flag {
  margin-left: 8px; padding: 3px 8px; border-radius: 999px;
  background: var(--ink); color: #fff; letter-spacing: .12em;
}

/* ---------- the four colours ---------- */

[data-color="red"]    { --c: var(--red);    --on: #fff; }
[data-color="yellow"] { --c: var(--yellow); --on: #101114; }
[data-color="green"]  { --c: var(--green);  --on: #fff; }
[data-color="blue"]   { --c: var(--blue);   --on: #fff; }
[data-color="none"]   { --c: var(--line-hi); --on: #101114; }

.sp-dot {
  width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: none;
  background: var(--c, var(--dim)); box-shadow: inset 0 0 0 1px rgba(16, 17, 20, .12);
}

/* ---------- controls ---------- */

.sp-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  border: 1.5px solid transparent; border-radius: 999px; cursor: pointer;
  background: var(--field); color: var(--ink);
  padding: 13px 24px; font: 600 15px/1 var(--sans);
  transition: background .18s var(--ease), color .18s, border-color .18s, transform .14s var(--ease);
}
.sp-btn:hover { transform: translateY(-1px); }
.sp-btn:active { transform: none; }
.sp-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.sp-btn[disabled] { cursor: not-allowed; transform: none; }

.sp-btn-dark { background: var(--ink); color: #fff; }
.sp-btn-dark:hover { background: var(--ink-soft); }
.sp-btn-dark[disabled] { background: #C4C6CA; }

.sp-btn-outline { background: transparent; border-color: var(--line-hi); }
.sp-btn-outline:hover { border-color: var(--ink); }

.sp-btn-lg { padding: 18px 34px; font-size: 16.5px; }
.sp-btn-block { width: 100%; }

/* the spin button: the biggest single control on the site, because it is the
   moment the product is about */
.sp-btn-spin {
  margin-top: 18px; padding: 18px 60px; border-radius: 999px;
  background: var(--ink); color: #fff;
  font: 700 17px/1 var(--sans); letter-spacing: .12em; text-transform: uppercase;
}
.sp-btn-spin:hover { background: var(--ink-soft); }
.sp-btn-spin[disabled] { background: #C4C6CA; }

.sp-link {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: 600 15px/1.4 var(--sans); color: var(--ink-soft);
  transition: color .16s;
}
.sp-link:hover { color: var(--ink); }
.sp-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 4px; }
.sp-link-lg { font-size: 16.5px; }
.sp-link-quiet { color: var(--muted); font-weight: 500; font-size: 13.5px; }

.sp-chip {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  border: 1.5px solid var(--line); border-radius: 999px; background: var(--bg);
  color: var(--muted); padding: 8px 15px; font: 600 13px/1 var(--sans);
  transition: color .16s, border-color .16s, background .16s;
}
.sp-chip:hover { color: var(--ink); border-color: var(--line-hi); }
.sp-chip.is-on { color: #fff; background: var(--ink); border-color: var(--ink); }
.sp-chip:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.sp-tag {
  font: 600 10.5px/1 var(--sans); letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 6px 11px;
}

/* ---------- nav ---------- */

/* A floating panel rather than a bar welded to the top of the window: it sits
   inside the same 1200px column the rest of the page uses, so the brand lines
   up with the headings underneath it and the page visibly runs behind it. */
.sp-nav {
  position: sticky; top: var(--nav-gap); z-index: 60; height: var(--nav-h);
  display: flex; align-items: center; gap: 28px;
  width: min(1200px, 100% - 48px); margin: var(--nav-gap) auto 0;
  padding: 0 10px 0 26px;
  background: rgba(255, 255, 255, .88); backdrop-filter: blur(16px) saturate(1.3);
  border: 1px solid var(--line); border-radius: 999px;
  box-shadow: var(--sh);
  transition: border-radius .2s var(--ease);
}
/* It is a link and it does something, so it has to look like one under the
   pointer. It had neither a hover state nor a focus ring. */
.sp-brand {
  display: inline-flex; align-items: center; gap: 9px;
  font: 700 19px/1 var(--sans); letter-spacing: -0.04em;
  color: var(--ink); text-decoration: none; border-radius: 6px;
  transition: opacity .16s;
}
.sp-mark-logo { width: 22px; height: 22px; display: block; flex: none; }
.sp-brand:hover { opacity: .62; }
.sp-brand:focus-visible { outline: 2px solid var(--ink); outline-offset: 5px; }
.sp-nav-links { display: flex; gap: 22px; margin-inline: auto; font: 500 14.5px/1 var(--sans); color: var(--muted); }
.sp-nav-links a { padding: 6px 0; border-bottom: 1.5px solid transparent; white-space: nowrap; transition: color .16s, border-color .16s; }
.sp-nav-links a:hover { color: var(--ink); }
.sp-nav-links a.is-here { color: var(--ink); border-bottom-color: var(--ink); }
.sp-nav-right { display: flex; align-items: center; gap: 16px; }
.sp-nav .sp-btn { padding: 11px 18px; font-size: 14px; }

.sp-burger { display: none; width: 40px; height: 40px; border: 0; background: none; cursor: pointer; padding: 0; }
.sp-burger span { display: block; height: 1.5px; background: var(--ink); margin: 5px auto; width: 20px; transition: transform .2s var(--ease); }
.sp-burger[aria-expanded="true"] span:first-child { transform: translateY(3.2px) rotate(45deg); }
.sp-burger[aria-expanded="true"] span:last-child { transform: translateY(-3.2px) rotate(-45deg); }

/* ---------- hero ---------- */

/* Full-bleed so the drifting sixteen can pass the edges of the window, with
   the copy and the wheel still inside the same column as everything else.
   The clipping lives here rather than on the drift layer, so a chip that hangs
   off the side cannot widen the page. */
/* One screen, and nothing of the next one. The nav sits in normal flow above
   this, so its height and the gap it floats by come off the top — otherwise
   the first screen is the nav plus a full viewport and the board peeks in at
   the bottom, which is the thing this is for.
   
   `min-height`, not `height`: on a phone the copy and the wheel together are
   taller than the window, and a fixed height would either squash them or spill
   them out of a section that clips. Taller than one screen also means the next
   section is not visible, which is the same answer by another route.
   
   dvh over svh: svh is the window with the browser's chrome showing, so when
   the chrome retracts the hero stops short and the board slides into view —
   exactly the gap being closed. vh first for anything that does not know dvh. */
.sp-hero {
  position: relative; overflow: hidden; isolation: isolate;
  display: grid; align-content: center;
  min-height: calc(100vh - var(--nav-h) - var(--nav-gap));
  min-height: calc(100dvh - var(--nav-h) - var(--nav-gap));
}
.sp-hero-in {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(32px, 6vw, 88px); align-items: center;
  width: min(1200px, 100% - 48px); margin-inline: auto;
  padding: clamp(40px, 5vw, 72px) 0;
}

/* ---------- the drifting sixteen ----------
 *
 * Every asset on the board, once each, floating behind the hero on a disc of
 * its own colour. Depth is done with size and opacity rather than blur: a
 * blurred element that animates repaints every frame, and sixteen of them is
 * how a landing page starts dropping frames on a laptop.
 *
 * Two elements per chip on purpose. The outer one places it and plays the
 * arrival once; the inner one floats forever. One element cannot do both,
 * because the second animation would replace the first.
 */
/* No wash, no floor, no texture: the hero's ground is the page's own white.
   Sixteen lit spheres are already the colour on this screen, and anything
   behind them competes with the one headline. */
.sp-floaters { position: absolute; inset: 0; z-index: -1; pointer-events: none; }

.sp-float {
  position: absolute; left: var(--x); top: var(--y);
  width: var(--s); height: var(--s); margin: calc(var(--s) / -2);
  opacity: 0;
  animation: sp-float-arrive 1s var(--ease) both var(--delay);
}
.sp-float-in {
  display: block; width: 100%; height: 100%;
  animation: sp-float-drift var(--dur) ease-in-out infinite alternate;
  animation-delay: var(--offset);
}

/* The sphere. Its shading is written in `em` and the disc's font-size is its
   own diameter, so one set of numbers holds at 38px and at 94px — a highlight
   in fixed pixels is a pinprick on the big ones and a wash on the small.
   Four layers, in the order light actually arrives:
     the body gradient, lit from the top left;
     the terminator and the ground bounce, as inset shadows;
     the rim, where the edge catches light from behind;
     and the cast shadow underneath. */
.sp-float-disc {
  position: relative; display: grid; place-items: center;
  width: 100%; height: 100%; border-radius: 50%;
  font-size: var(--s);
  background: radial-gradient(circle at var(--lx) var(--ly),
    var(--c-hi) 0%, var(--c) 44%, var(--c-lo) 100%);
  box-shadow:
    inset 0 -0.10em 0.18em -0.06em rgba(0, 0, 0, .42),
    inset -0.05em -0.05em 0.12em -0.03em var(--c-rim),
    inset 0 0.04em 0.10em -0.03em rgba(255, 255, 255, .5),
    0 0.16em 0.24em -0.12em rgba(16, 17, 20, .5),
    0 0.30em 0.40em -0.22em rgba(16, 17, 20, .35);
}

/* The logo is printed on the sphere, not floating in front of it: a soft inner
   shadow sets it into the surface, and the gloss above passes over both. */
.sp-float-face {
  position: relative; z-index: 1;
  display: grid; place-items: center; width: 62%; height: 62%; border-radius: 50%;
  background: radial-gradient(circle at 34% 28%, #fff 0%, #F4F4F2 100%);
  box-shadow: inset 0 0.015em 0.05em rgba(16, 17, 20, .22), 0 0.01em 0.02em rgba(16, 17, 20, .1);
}
.sp-float-face .sp-mark { width: 74%; height: 62%; }
.sp-float-face .sp-glyph { color: var(--c); }

/* One gloss over the whole ball. This is the layer that makes the white face
   read as part of the sphere rather than a sticker on it. */
.sp-float-gloss {
  position: absolute; inset: 0; z-index: 2; border-radius: 50%; pointer-events: none;
  background:
    radial-gradient(38% 26% at var(--lx) calc(var(--ly) - 6%),
      rgba(255, 255, 255, .95), rgba(255, 255, 255, 0) 68%),
    radial-gradient(52% 34% at 68% 94%,
      rgba(255, 255, 255, .26), rgba(255, 255, 255, 0) 72%);
}

@keyframes sp-float-arrive {
  from { opacity: 0; transform: translateY(30px) scale(.82); }
  to   { opacity: var(--o); transform: none; }
}
/* Air, not a lift: it sways across as well as up, and the tilt lags the sway. */
@keyframes sp-float-drift {
  from { transform: translate3d(var(--swayA), var(--riseA), 0) rotate(var(--tiltA)); }
  to   { transform: translate3d(var(--swayB), var(--riseB), 0) rotate(var(--tiltB)); }
}

.sp-hero.is-still .sp-float-in { animation-play-state: paused; }
/* It lives in the copy, so that when the hero stacks and grows past the window
   it can simply stop being pinned and sit under the buttons, where it is on
   screen. Pinned to the hero's bottom edge it was reachable only by scrolling,
   which is the one group that does not need it. */
.sp-hero-motion { position: absolute; left: clamp(20px, 4vw, 48px); bottom: 20px; margin: 0; }

/* A short window is the case this breaks in: the hero grows past its own floor
   to fit the copy, and the two controls pinned to its bottom edge end up below
   the fold — visible only to someone who scrolls, which is the one group that
   does not need them. The wheel takes a height cap and the headline steps down
   so the content fits inside the floor instead of pushing past it. */
@media (max-height: 880px) {
  .sp-hero-in { padding-block: clamp(20px, 3vh, 48px); }
  .sp-hero-wheel { gap: 14px; }
  .sp-hero-wheel .sp-wheel { width: min(600px, 92vw, 56vh); }
  .sp-lede { margin-top: 20px; }
  .sp-hero-live { margin-top: 14px; }
  .sp-hero-cta { margin-top: 22px; }
  .sp-hero-facts { margin-top: 18px; }
  .sp-eyebrow { margin-bottom: 16px; padding-block: 6px; }
}
/* Shorter still and the live chip and the numbers are the two things that can
   go: the headline, the lede and the buttons are the page. */
@media (max-height: 760px) {
  .sp-hero-facts { display: none; }
  .sp-hero-live { margin-top: 12px; }
  .sp-hero-live-chip { padding-block: 5px; }
}
@media (max-height: 880px) and (min-width: 861px) {
  .sp-hero h1 { font-size: clamp(44px, 6.4vw, 82px); }
}
/* Three lines of headline is the biggest single block in the copy, so on a
   window this short it is the one worth stepping down again: the live chip
   costs about the height this gives back. */
@media (max-height: 760px) and (min-width: 861px) {
  .sp-hero h1 { font-size: clamp(40px, 5vw, 66px); }
}

/* A hero that fills the window can read as the whole site. This says it is not. */
.sp-hero-more {
  position: absolute; right: clamp(20px, 4vw, 48px); bottom: 20px; margin: 0;
  display: inline-flex; align-items: center; gap: 10px;
  font: 600 10.5px/1 var(--sans); letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted); background: none; border: 0; padding: 0; cursor: pointer;
}
.sp-hero-more:hover { color: var(--ink); }
.sp-hero-more:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 4px; }
.sp-hero-more i { font-style: normal; animation: sp-nudge 2.4s ease-in-out infinite; }
@keyframes sp-nudge {
  0%, 60%, 100% { transform: translateY(0); }
  30%           { transform: translateY(4px); }
}
/* The eyebrow is a badge rather than a line of grey caps: it is the first thing
   on the page and it was reading as a caption for something above it. */
.sp-eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font: 600 11.5px/1 var(--sans); letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-soft); margin-bottom: 26px;
  padding: 8px 15px 8px 12px; border: 1.5px solid var(--line); border-radius: 999px;
  background: var(--card);
}
.sp-eyebrow-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--red);
  box-shadow: 0 0 0 0 rgba(228, 50, 43, .5);
  animation: sp-pulse 2.6s ease-out infinite;
}
@keyframes sp-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(228, 50, 43, .45); }
  70%  { box-shadow: 0 0 0 9px rgba(228, 50, 43, 0); }
  100% { box-shadow: 0 0 0 0 rgba(228, 50, 43, 0); }
}

/* The stops carry the four colours the wheel draws from. It is the only colour
   in the headline and it is the same colour the product is about. */
.sp-hero h1 b { font-weight: inherit; }
.sp-hero h1 b:nth-of-type(1) { color: var(--red); }
.sp-hero h1 b:nth-of-type(2) { color: var(--yellow); }
.sp-hero h1 b:nth-of-type(3) { color: var(--green); }

.sp-lede { margin-top: 26px; font-size: clamp(16px, 1.5vw, 19px); line-height: 1.6; color: var(--prose); max-width: 42ch; }

/* The one live thing in the copy: the board, cycling. Fixed width in ch so a
   long name does not shove the line about on every change. */
.sp-hero-live { margin-top: 20px; display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.sp-hero-live-lead { font: 500 14.5px/1 var(--sans); color: var(--muted); }
.sp-hero-live-chip {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 7px 16px 7px 8px; border-radius: 999px;
  border: 1.5px solid var(--c, var(--line-hi)); background: var(--card);
  transition: border-color .4s var(--ease);
}
.sp-hero-live-chip[data-color="red"]    { --c: var(--red); }
.sp-hero-live-chip[data-color="yellow"] { --c: var(--yellow); }
.sp-hero-live-chip[data-color="green"]  { --c: var(--green); }
.sp-hero-live-chip[data-color="blue"]   { --c: var(--blue); }
.sp-hero-live-mark {
  width: 24px; height: 24px; border-radius: 50%; background: #fff;
  border: 1.5px solid var(--c); display: block;
  background-size: 62% 62%; background-repeat: no-repeat; background-position: center;
}
.sp-hero-live-chip b {
  font: 600 15px/1 var(--sans); color: var(--ink); min-width: 9ch;
  animation: sp-live-in .45s var(--ease) both;
}
@keyframes sp-live-in {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}

.sp-hero-cta { margin-top: 30px; display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.sp-hero-cta .sp-btn-dark {
  box-shadow: 0 10px 22px -8px rgba(16, 17, 20, .5);
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), background .16s;
}
.sp-hero-cta .sp-btn-dark:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 30px -10px rgba(16, 17, 20, .55);
}

/* The three numbers that describe the whole mechanic, in the place someone
   looks after the buttons. */
.sp-hero-facts {
  list-style: none; margin: 28px 0 0; padding: 0;
  display: flex; gap: 22px; flex-wrap: wrap;
  font: 500 13px/1 var(--sans); color: var(--muted);
}
.sp-hero-facts li { display: inline-flex; align-items: baseline; gap: 6px; }
.sp-hero-facts li + li { padding-left: 22px; border-left: 1px solid var(--line); }
.sp-hero-facts b { font: 700 15px/1 var(--sans); color: var(--ink); letter-spacing: -.02em; }

.sp-hero-wheel { display: grid; justify-items: center; gap: 18px; }
.sp-wheel-caption {
  display: inline-flex; align-items: center; gap: 10px;
  font: 500 13px/1 var(--sans); color: var(--muted);
}
.sp-wheel-caption::before {
  content: ""; width: 26px; height: 1.5px; background: var(--line-hi);
}

/* ---------- the wheel ---------- */

.sp-wheel { position: relative; width: min(600px, 92vw); aspect-ratio: 1; display: grid; place-items: center; }
/* The wheel is the screen, so it takes the height it can and no more: without
   the vh cap a 700px wheel pushed the SPIN button off the bottom on every
   desktop, which is the one control the screen exists for. */
.sp-wheel-big { width: min(700px, 90vw, 64vh); margin-inline: auto; }

/* The quarter names are printed into the rim, the way they are on the board.
   They sat outside it as chips, and a spinner whose quarters are labelled by
   four captions beside it is a diagram of a spinner.

   Each one is placed on its quarter's own diagonal — the centre offset is
   cos(45°) of the mid-rim radius, as a percentage of the wheel's box — and
   turned to lie along the rim rather than across it. */
.sp-wheel-label {
  position: absolute; z-index: 2;
  font: 700 clamp(8px, 1.5vw, 10.5px)/1 var(--sans);
  letter-spacing: .14em; text-transform: uppercase;
  color: rgba(16, 17, 20, .55); white-space: nowrap;
}
/* left/top, not a second translate: a percentage inside `transform: translate`
   is a percentage of the element itself, which on a 70px label moved them 18px
   and piled all four on the hub. These are percentages of the wheel's box.

   29.76% off centre is cos(45°) of the mid-rim radius: the face is 92% of the box,
   so SVG radius 91.5 of 200 lands at 42.09% of the box, and the diagonal takes
   .7071 of that. */
.sp-wheel-tl { left: 20.24%; top: 20.24%; transform: translate(-50%, -50%) rotate(-45deg); }
.sp-wheel-tr { left: 79.76%; top: 20.24%; transform: translate(-50%, -50%) rotate(45deg); }
.sp-wheel-bl { left: 20.24%; top: 79.76%; transform: translate(-50%, -50%) rotate(45deg); }
.sp-wheel-br { left: 79.76%; top: 79.76%; transform: translate(-50%, -50%) rotate(-45deg); }

/* the face tilts a little under the cursor, which is the only thing that makes
   a flat circle feel like an object you could reach out and turn */
.sp-wheel-face {
  position: relative; width: 92%; aspect-ratio: 1;
  transform: rotateX(var(--tiltX, 0deg)) rotateY(var(--tiltY, 0deg));
  transform-style: preserve-3d;
  transition: transform .5s var(--ease);
  filter: drop-shadow(0 10px 14px rgba(16, 17, 20, .10))
          drop-shadow(0 38px 52px rgba(16, 17, 20, .16));
}
.sp-wheel-svg { width: 100%; height: 100%; display: block; }
.sp-wheel-svg .sp-rim { stroke: rgba(16, 17, 20, .52); stroke-width: 1.4; }
.sp-wheel-svg .sp-rim-in { fill: none; stroke: rgba(16, 17, 20, .3); stroke-width: 1.2; }
.sp-wheel-svg .sp-face { stroke: none; }
.sp-wheel-svg .sp-quad { fill: rgba(16, 17, 20, .022); }
.sp-wheel-svg .sp-cross { stroke: rgba(16, 17, 20, .34); stroke-width: 1.2; }
.sp-wheel-svg .sp-tick { stroke: rgba(16, 17, 20, .22); stroke-width: 1; stroke-linecap: round; }
.sp-wheel-svg .sp-node { transition: r .25s var(--ease), opacity .25s; }
.sp-wheel-svg .sp-node-gloss { pointer-events: none; }
.sp-wheel-svg .sp-node-cast { fill: rgba(16, 17, 20, .22); }
.sp-wheel-svg .sp-node-ring { fill: none; stroke: rgba(16, 17, 20, .22); stroke-width: .8; }
.sp-wheel-svg .sp-node-disc { fill: #fff; }
.sp-wheel-svg .sp-node-glyph { fill: none; stroke: rgba(16, 17, 20, .5); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.sp-wheel-svg .sp-node-pic { pointer-events: none; }
.sp-wheel-svg .sp-hub { stroke: rgba(16, 17, 20, .38); stroke-width: 1.1; }
.sp-wheel-svg .sp-hub-cast { fill: rgba(16, 17, 20, .16); }
.sp-wheel-svg .sp-hub-in { fill: none; stroke: rgba(16, 17, 20, .14); stroke-width: 1; }

.sp-wheel-arrow {
  position: absolute; inset: 0; color: var(--ink);
  transform: rotate(var(--rot, 0deg)); transform-origin: 50% 50%;
  transition: transform 5s cubic-bezier(.17, .84, .19, 1);
  filter: drop-shadow(0 6px 10px rgba(16, 17, 20, .28));
}
.sp-wheel-arrow svg { width: 100%; height: 100%; display: block; fill: currentColor; }
.sp-arrow-eye { fill: #fff; }

/* the hero wheel drifts on its own so the page is alive before anyone touches it */
.sp-hero-wheel .sp-wheel-arrow { animation: sp-drift 14s ease-in-out infinite; }
@keyframes sp-drift {
  0%, 100% { transform: rotate(-6deg); }
  50%      { transform: rotate(6deg); }
}
.sp-wheel-svg .sp-node.is-hot { r: 14.5; }

/* ---------- sections ---------- */

/* The nav is sticky, so anything scrolled to by an anchor has to start below
   it — without this every section heading arrives hidden under the bar. */
.sp-sec, .sp-hero-in, .sp-stage { scroll-margin-top: calc(var(--nav-h) + var(--nav-gap) * 2 + 12px); }

.sp-sec { padding: clamp(64px, 9vw, 120px) 0; border-top: 1px solid var(--line); }
/* A veil, not a fill: an opaque band would cut a flat stripe through the
   ground and the blooms would stop at its edges. */
.sp-sec-tint { background: rgba(16, 17, 20, .028); }
.sp-sec-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 32px; flex-wrap: wrap; margin-bottom: clamp(32px, 4vw, 52px);
}
.sp-sec-head h2 { margin-top: 14px; }
.sp-sec-note { font-size: 14.5px; color: var(--muted); max-width: 42ch; }

/* ---------- the ticker ---------- */

.sp-ticker { overflow: hidden; border-block: 1px solid var(--line); }
.sp-ticker-track { display: flex; gap: 34px; white-space: nowrap; width: max-content; padding: 12px 0; animation: sp-marquee 58s linear infinite; }
.sp-ticker:hover .sp-ticker-track { animation-play-state: paused; }
.sp-tick { display: inline-flex; align-items: center; gap: 9px; font: 500 12px/1 var(--mono); color: var(--muted); }
.sp-tick b { color: var(--ink); font-weight: 500; }
@keyframes sp-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ---------- the board ---------- */

.sp-board-scroll { overflow-x: auto; margin-inline: -4px; padding: 4px; }
.sp-board {
  display: grid; grid-template-columns: 112px repeat(4, minmax(132px, 1fr));
  gap: 10px; min-width: 660px;
}
.sp-board-head, .sp-board-side {
  display: flex; align-items: center; gap: 8px;
  font: 600 11px/1.2 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.sp-board-side { justify-content: flex-end; text-align: right; }
.sp-board-corner { min-height: 34px; }

.sp-cell {
  position: relative; display: grid; gap: 10px; justify-items: center; text-align: center;
  padding: 20px 12px 18px; cursor: pointer;
  background: var(--card); border: 1.5px solid var(--line); border-radius: var(--r);
  transition: border-color .18s, transform .18s var(--ease), box-shadow .18s;
}
.sp-cell:hover, .sp-cell.is-on { border-color: var(--c); transform: translateY(-3px); box-shadow: var(--sh); }
.sp-cell:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.sp-cell-node {
  width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center;
  background: var(--c); color: var(--on);
  box-shadow: inset 0 0 0 1px rgba(16, 17, 20, .14);
}
.sp-cell b { font: 600 14px/1.25 var(--sans); }
.sp-cell em { font: 500 11px/1 var(--mono); font-style: normal; color: var(--muted); }

.sp-board-read {
  display: grid; grid-template-columns: auto 1fr; gap: 20px; align-items: center;
  margin-top: 28px; padding: 22px 24px;
  background: var(--card); border: 1.5px solid var(--c, var(--line)); border-radius: var(--r);
  box-shadow: var(--sh-sm);
}
.sp-board-read .sp-cell-node { width: 56px; height: 56px; }
.sp-board-read h3 { font-size: 22px; }
.sp-board-read p { margin-top: 6px; font-size: 14px; color: var(--muted); }

/* ---------- the pad ---------- */

.sp-verify:empty { display: none; }
.sp-verify {
  margin-bottom: 28px; padding: 18px 22px;
  background: var(--card); border: 1.5px solid var(--line); border-radius: var(--r);
}
.sp-verify-head { font: 600 11px/1.4 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.sp-verify-list { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; }
.sp-verify-list li { display: grid; grid-template-columns: auto auto 1fr; align-items: center; gap: 10px; font-size: 13.5px; }
.sp-verify-list b { font-weight: 600; }
.sp-verify-list em { font-style: normal; font-size: 12.5px; color: var(--muted); }
.sp-verify-list li.is-ok em { color: var(--green); }
.sp-verify-hint { font-size: 12.5px; color: var(--muted); grid-column: 1 / -1; }
.sp-verify-note { margin-top: 12px; font-size: 12.5px; color: var(--muted); }

.sp-steps { list-style: none; display: flex; gap: 10px; flex-wrap: wrap; margin: 0 0 36px; padding: 0; }
.sp-steps li {
  display: inline-flex; align-items: center; gap: 9px;
  font: 600 12.5px/1 var(--sans); color: var(--dim);
  border: 1.5px solid var(--line); border-radius: 999px; padding: 9px 16px; background: var(--bg);
  transition: color .18s, border-color .18s;
}
.sp-steps li span { font-family: var(--mono); font-weight: 500; }
.sp-steps li.is-on { color: var(--ink); border-color: var(--ink); }
.sp-steps li.is-done { color: var(--muted); border-color: var(--line-hi); }

/* One stage at a time: the flow is the interface.
   A stage's own layout has to be declared here, next to the rule that reveals
   it, and never on the .sp-stage-* class — those sit lower in the file and a
   `display` on one of them beats `.sp-stage { display: none }`, which leaves
   that stage on screen at every step. */
.sp-stage { display: none; animation: sp-in .4s var(--ease) both; }
.sp-pad[data-step="1"] .sp-stage[data-stage="1"],
.sp-pad[data-step="2"] .sp-stage[data-stage="2"],
.sp-pad[data-step="4"] .sp-stage[data-stage="4"],
.sp-pad[data-step="5"] .sp-stage[data-stage="5"] { display: block; }
.sp-pad[data-step="3"] .sp-stage[data-stage="3"] { display: grid; justify-items: center; gap: 34px; }
@keyframes sp-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.sp-card {
  background: var(--card); border: 1.5px solid var(--line); border-radius: var(--r);
  padding: clamp(24px, 3vw, 34px); box-shadow: var(--sh-sm);
}
/* 01 — the form, and what it is making, side by side */
.sp-make {
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: 24px; align-items: start;
}
.sp-aside { display: grid; gap: 20px; position: sticky; top: calc(var(--nav-h) + var(--nav-gap) * 2); }

.sp-preview {
  display: grid; justify-items: center; gap: 13px;
  padding: clamp(18px, 2.4vw, 26px) 20px;
  background: linear-gradient(180deg, var(--tint), #fff);
  border: 1.5px solid var(--line); border-radius: var(--r);
}
.sp-preview-note { font: 500 12px/1 var(--mono); color: var(--dim); }

/* The same lit sphere as the hero, at the size a preview wants. It is the one
   on the page with no colour yet, because on this screen there is no pairing —
   so it takes the neutral, and says so underneath. */
.sp-orb {
  position: relative; display: grid; place-items: center;
  width: clamp(104px, 16vw, 132px); aspect-ratio: 1; border-radius: 50%;
  font-size: clamp(104px, 16vw, 132px);
  background: radial-gradient(circle at 32% 26%, var(--c-hi, #EFEFEC) 0%, var(--c) 46%, var(--c-lo, #8E9096) 100%);
  box-shadow:
    inset 0 -0.10em 0.18em -0.06em rgba(0, 0, 0, .34),
    inset 0 0.04em 0.10em -0.03em rgba(255, 255, 255, .55),
    0 0.14em 0.22em -0.10em rgba(16, 17, 20, .38),
    0 0.26em 0.36em -0.20em rgba(16, 17, 20, .28);
  transition: background .3s var(--ease);
}
.sp-orb-face {
  position: relative; z-index: 1;
  display: grid; place-items: center; align-content: center; gap: 3px;
  width: 62%; height: 62%; border-radius: 50%; text-align: center;
  background: radial-gradient(circle at 34% 28%, #fff 0%, #F4F4F2 100%);
  box-shadow: inset 0 0.015em 0.05em rgba(16, 17, 20, .2);
}
.sp-orb-face b { font: 700 clamp(15px, 2.6vw, 19px)/1 var(--mono); letter-spacing: -0.02em; max-width: 84%; overflow: hidden; text-overflow: ellipsis; }
.sp-orb-face i { font: 600 8.5px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; font-style: normal; color: var(--muted); }
/* The picture sits in the orb's inner disc, under the gloss, so the sphere's
   own lighting passes over it rather than the picture sitting on top of a ball. */
.sp-orb-pic {
  position: absolute; z-index: 1; width: 62%; height: 62%;
  border-radius: 50%; object-fit: cover;
  box-shadow: inset 0 0.015em 0.05em rgba(16, 17, 20, .2);
}
.sp-orb.has-pic .sp-orb-face {
  background: none; box-shadow: none; z-index: 2;
  width: auto; height: auto; padding: 5px 11px; border-radius: 999px;
  align-self: end; margin-bottom: 8%;
  background: rgba(255, 255, 255, .92);
  backdrop-filter: blur(2px);
}
/* The base rule caps the ticker at 84% of the face; on an auto-width chip that
   is a percentage of a width the text is setting, and "TICKER" came out
   "TICK…". The chip takes the cap instead. */
.sp-orb.has-pic .sp-orb-face { max-width: 82%; }
.sp-orb.has-pic .sp-orb-face b { font-size: clamp(11px, 1.8vw, 13px); max-width: none; }
.sp-orb.has-pic .sp-orb-face i { display: none; }

.sp-orb-gloss {
  position: absolute; inset: 0; z-index: 3; border-radius: 50%; pointer-events: none;
  background:
    radial-gradient(38% 26% at 32% 20%, rgba(255, 255, 255, .95), rgba(255, 255, 255, 0) 68%),
    radial-gradient(52% 34% at 68% 94%, rgba(255, 255, 255, .24), rgba(255, 255, 255, 0) 72%);
}

.sp-live h3 { margin-top: 12px; font-size: 21px; }
.sp-live .sp-rows { margin: 18px 0 14px; }

.sp-form { width: 100%; }
.sp-form fieldset { border: 0; margin: 0; padding: 0; display: grid; gap: 22px; }
.sp-form fieldset[disabled] { opacity: .55; }

.sp-field label, .sp-field-label {
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
  font: 600 14px/1.3 var(--sans); margin-bottom: 10px;
}
.sp-field label i, .sp-field-label i { font: 400 12px/1 var(--mono); font-style: normal; color: var(--dim); }
.sp-field input, .sp-field textarea {
  width: 100%; background: var(--field); color: var(--ink);
  border: 1.5px solid transparent; border-radius: var(--r-sm);
  padding: 15px 17px; font: 500 15.5px/1.45 var(--sans); resize: vertical;
}
.sp-field input:focus, .sp-field textarea:focus { outline: none; border-color: var(--ink); background: #fff; }
.sp-field input::placeholder, .sp-field textarea::placeholder { color: var(--dim); font-weight: 400; }
#fTicker, #fSupply, #poolAmount { font-family: var(--mono); font-weight: 400; }
/* ---------- the image drop ----------
 *
 * The file input covers the whole box and is transparent, so the box itself is
 * the button and the drop target. A styled label next to a hidden input needs
 * its own drag handlers, its own keyboard handling and its own focus ring; a
 * real input stretched over the box comes with all three. */
.sp-drop {
  position: relative; display: flex; align-items: center;
  min-height: 78px; padding: 12px 14px;
  background: var(--field); border: 1.5px dashed var(--line-hi); border-radius: var(--r-sm);
  transition: border-color .16s, background .16s;
}
.sp-drop:hover { border-color: var(--ink-soft); }
.sp-drop.is-over { border-color: var(--ink); border-style: solid; background: #fff; }
.sp-drop.is-full { border-style: solid; border-color: var(--line); background: var(--field); }

.sp-drop-input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; padding: 0; border: 0;
}
.sp-drop-input:focus-visible + .sp-drop-empty,
.sp-drop:focus-within { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: var(--r-sm); }
.sp-drop.is-full .sp-drop-input { cursor: default; }

.sp-drop-empty {
  display: flex; align-items: center; gap: 11px;
  font: 500 14px/1.4 var(--sans); color: var(--muted);
}
.sp-drop-empty b { font-weight: 700; color: var(--ink); }
.sp-drop-empty svg { flex: none; color: var(--dim); }

.sp-drop-has { display: flex; align-items: center; gap: 14px; width: 100%; }
.sp-drop-has img {
  flex: none; width: 52px; height: 52px; border-radius: 9px; object-fit: cover;
  background: #fff; border: 1.5px solid var(--line);
}
.sp-drop-meta { display: grid; gap: 4px; min-width: 0; }
.sp-drop-meta b {
  font: 600 14px/1.2 var(--sans); color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sp-drop-meta i { font: 400 12px/1 var(--mono); font-style: normal; color: var(--muted); }
/* above the input, or the input's own click area swallows it */
.sp-drop-clear {
  position: relative; z-index: 1; margin-left: auto; flex: none;
  background: none; border: 1.5px solid var(--line-hi); border-radius: 999px;
  padding: 7px 14px; cursor: pointer;
  font: 600 12.5px/1 var(--sans); color: var(--ink-soft);
}
.sp-drop-clear:hover { border-color: var(--ink); color: var(--ink); }
.sp-drop-clear:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.sp-drop.is-bad { border-color: var(--red); border-style: solid; background: #fff; }

.sp-help { margin-top: 9px; font-size: 12.5px; color: var(--muted); }
.sp-help-final { margin-top: 14px; text-align: center; }
.sp-err { display: none; margin-top: 9px; font: 600 12.5px/1.4 var(--sans); color: var(--red); }
.sp-err.is-on { display: block; }
.sp-field input[aria-invalid="true"], .sp-field textarea[aria-invalid="true"] { border-color: var(--red); background: #fff; }

/* the wallet, said where it matters rather than only in the section header */
.sp-note {
  margin-top: 26px; padding: 18px 20px;
  background: var(--tint); border-left: 3px solid var(--ink); border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.sp-note p { font-size: 13.5px; line-height: 1.6; color: var(--prose); }
.sp-note b { font-weight: 700; color: var(--ink); }
.sp-note .sp-btn { margin-top: 14px; padding: 10px 18px; font-size: 13.5px; }
.sp-note.is-on { border-left-color: var(--green); }

/* the one field nobody gets to fill in */
.sp-pairing-slot {
  margin-top: 26px; padding: 20px 22px; text-align: center;
  border: 1.5px dashed var(--c, var(--line-hi)); border-radius: var(--r-sm); background: var(--field);
}
.sp-pairing-slot b { display: block; margin-top: 10px; font: 700 19px/1.2 var(--sans); letter-spacing: -0.02em; }
.sp-pairing-slot em { display: block; margin-top: 6px; font: 500 12px/1 var(--mono); font-style: normal; color: var(--muted); }
.sp-form > .sp-btn { margin-top: 26px; }

/* 02 — the spin */
.sp-stage-spin { text-align: center; }
.sp-stage-title { margin: 10px 0 18px; font-size: clamp(24px, 3vw, 36px); }
.sp-status { margin-top: 14px; min-height: 2.6em; font-size: 14.5px; line-height: 1.6; color: var(--muted); }
.sp-stage-foot { margin-top: 10px; display: flex; align-items: center; justify-content: center; gap: 20px; }

/* 03 — the result (its display lives with the stage rules above) */
.sp-result {
  width: min(560px, 100%); text-align: center; padding: clamp(28px, 4vw, 44px);
  background: var(--card); border: 1.5px solid var(--c, var(--line)); border-radius: var(--r);
  box-shadow: var(--sh);
}
.sp-result-combo {
  margin-top: 14px; font: 700 clamp(22px, 3vw, 34px)/1.1 var(--sans);
  letter-spacing: .02em; text-transform: uppercase;
}
.sp-result-asset {
  margin-top: 30px; padding-top: 30px; border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center; gap: 18px; text-align: left;
}
.sp-result-mark {
  width: 74px; height: 74px; border-radius: 50%; display: grid; place-items: center; flex: none;
  background: var(--c); color: var(--on); box-shadow: inset 0 0 0 1px rgba(16, 17, 20, .14);
}
.sp-result-asset b { display: block; margin-top: 8px; font: 700 30px/1 var(--sans); letter-spacing: -0.03em; }
.sp-locked {
  display: inline-block; margin-top: 26px; padding: 8px 16px; border-radius: 999px;
  background: var(--ink); color: #fff;
  font: 600 11px/1 var(--sans); letter-spacing: .16em; text-transform: uppercase;
}
.sp-result-note { margin-top: 18px; font-size: 13.5px; line-height: 1.6; color: var(--muted); }
.sp-stage-cta { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; justify-content: center; }

/* 04 — the confirmation */
.sp-confirm { width: min(560px, 100%); margin-inline: auto; }
.sp-confirm-head { display: flex; align-items: center; gap: 18px; margin: 16px 0 26px; }
.sp-confirm-mark {
  width: 76px; height: 76px; border-radius: 50%; flex: none;
  display: grid; place-items: center; align-content: center; gap: 2px; text-align: center;
  background: var(--c, var(--field)); color: var(--on, var(--ink));
  box-shadow: inset 0 0 0 1px rgba(16, 17, 20, .14);
}
.sp-confirm-mark b { font: 700 15px/1 var(--mono); letter-spacing: -0.02em; max-width: 62px; overflow: hidden; text-overflow: ellipsis; }
.sp-confirm-mark i { font: 600 8.5px/1 var(--sans); letter-spacing: .12em; font-style: normal; opacity: .78; }
.sp-confirm-sub { margin-top: 6px; font: 500 12px/1 var(--mono); color: var(--muted); }

.sp-rows { margin: 0 0 26px; display: grid; }
.sp-rows > div { display: flex; align-items: baseline; justify-content: space-between; gap: 18px; padding: 14px 0; border-top: 1px solid var(--line); }
.sp-rows > div:first-child { border-top: 0; }
.sp-rows dt { font-size: 14px; color: var(--muted); }
.sp-rows dd { margin: 0; font: 600 14px/1.3 var(--sans); text-align: right; }
.sp-rows dd.is-mono { font-family: var(--mono); font-weight: 500; }
.sp-rows a { text-decoration: underline; text-underline-offset: 2px; }

/* 05 — the record */
.sp-record { width: min(620px, 100%); margin-inline: auto; border-top: 3px solid var(--c, var(--ink)); }
.sp-record-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.sp-record-coin { display: flex; align-items: center; gap: 18px; padding: 20px 0; }
.sp-record-coin b { display: block; font: 700 21px/1.2 var(--sans); letter-spacing: -0.02em; }
.sp-record-coin em { font: 500 12.5px/1 var(--mono); font-style: normal; color: var(--muted); }
.sp-record-desc { margin-bottom: 18px; font-size: 14.5px; color: var(--prose); }
.sp-record-note { font-size: 13.5px; line-height: 1.6; color: var(--muted); }
.sp-record-foot { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-top: 26px; }

.sp-pool { margin-top: 26px; padding-top: 26px; border-top: 1px solid var(--line); }
.sp-pool-copy { margin: 10px 0 18px; font-size: 14px; line-height: 1.6; color: var(--prose); }
.sp-pool-note { margin-top: 12px; font-size: 13px; line-height: 1.55; color: var(--muted); }
.sp-pool-note a { text-decoration: underline; text-underline-offset: 2px; }

/* ---------- how it works ---------- */

.sp-how { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.sp-how li { background: var(--bg); padding: clamp(26px, 3vw, 40px); }
.sp-how span { font: 500 12px/1 var(--mono); color: var(--dim); }
.sp-how h3 { margin: 18px 0 10px; font-size: 22px; }
.sp-how p { font-size: 14.5px; color: var(--prose); }

/* ---------- asset desk ---------- */

.sp-desk { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 12px; }
.sp-desk-card {
  display: grid; grid-template-columns: auto 1fr; gap: 14px; align-items: center;
  padding: 18px; background: var(--card); border: 1.5px solid var(--line); border-radius: var(--r);
  cursor: default; transition: border-color .18s, transform .18s var(--ease);
}
.sp-desk-card:hover { border-color: var(--c); transform: translateY(-2px); }
.sp-desk-card:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.sp-desk-mark {
  width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
  background: var(--c); color: var(--on); box-shadow: inset 0 0 0 1px rgba(16, 17, 20, .14);
}
.sp-desk-body b { display: block; font: 600 15px/1.2 var(--sans); }
.sp-desk-body em { font: 500 11.5px/1 var(--mono); font-style: normal; color: var(--muted); }
.sp-desk-combo {
  grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; padding-top: 14px;
  border-top: 1px solid var(--line);
  font: 600 10.5px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}

/* ---------- proof ---------- */

.sp-search { display: flex; align-items: center; gap: 10px; border: 1.5px solid var(--line); border-radius: 999px; background: var(--bg); padding: 0 18px; height: 44px; }
.sp-search:focus-within { border-color: var(--ink); }
.sp-search svg { width: 16px; height: 16px; flex: none; fill: none; stroke: var(--muted); stroke-width: 2; }
.sp-search input { border: 0; background: transparent; color: var(--ink); font: 500 14px/1 var(--sans); width: 170px; outline: none; }
.sp-search input::placeholder { color: var(--dim); }

.sp-proof-bar { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-bottom: 24px; }
.sp-filters { display: flex; gap: 8px; flex-wrap: wrap; }
.sp-sort { margin-left: auto; display: inline-flex; align-items: center; gap: 10px; font: 500 13.5px/1 var(--sans); color: var(--muted); }
.sp-select { position: relative; }
.sp-select-btn {
  display: inline-flex; align-items: center; gap: 10px; cursor: pointer;
  background: var(--bg); color: var(--ink); border: 1.5px solid var(--line);
  border-radius: 999px; padding: 10px 16px; font: 600 13px/1 var(--sans); transition: border-color .16s;
}
.sp-select-btn::after { content: ""; width: 7px; height: 7px; border-right: 1.6px solid var(--muted); border-bottom: 1.6px solid var(--muted); transform: translateY(-2px) rotate(45deg); transition: transform .18s; }
.sp-select-btn[aria-expanded="true"] { border-color: var(--ink); }
.sp-select-btn[aria-expanded="true"]::after { transform: translateY(1px) rotate(225deg); }
.sp-select-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.sp-select-menu { position: absolute; z-index: 30; top: calc(100% + 8px); right: 0; min-width: 100%; margin: 0; padding: 6px; list-style: none; background: var(--card); border: 1.5px solid var(--line-hi); border-radius: 14px; box-shadow: var(--sh); }
.sp-select-menu li { padding: 10px 14px; border-radius: 9px; cursor: pointer; white-space: nowrap; font: 600 13px/1 var(--sans); color: var(--prose); }
.sp-select-menu li:hover, .sp-select-menu li:focus { background: var(--field); color: var(--ink); outline: none; }
.sp-select-menu li[aria-selected="true"] { color: var(--ink); background: var(--field); }

.sp-launches { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.sp-launch {
  display: grid; grid-template-columns: auto minmax(0, 1.4fr) minmax(0, 1fr) auto auto;
  gap: 20px; align-items: center; padding: 18px 22px; background: var(--bg);
  transition: background .16s;
}
.sp-launch:hover { background: var(--tint); }
.sp-launch-mark { width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center; background: var(--c); color: var(--on); box-shadow: inset 0 0 0 1px rgba(16,17,20,.14); }
.sp-launch-name b { font: 600 15px/1.25 var(--sans); }
.sp-launch-name em { font: 500 12px/1 var(--mono); font-style: normal; color: var(--muted); }
.sp-launch-pair { display: grid; gap: 4px; }
.sp-launch-pair b { font: 600 14px/1 var(--sans); }
.sp-launch-pair em { font: 600 10.5px/1 var(--sans); letter-spacing: .12em; text-transform: uppercase; font-style: normal; color: var(--muted); }
.sp-launch-time { font: 500 12.5px/1 var(--mono); color: var(--muted); white-space: nowrap; }
.sp-launch-tx { font: 500 12.5px/1 var(--mono); }
.sp-launch-tx a { text-decoration: underline; text-underline-offset: 3px; }
.sp-launch-tx span { color: var(--dim); }

.sp-empty { text-align: center; color: var(--muted); font-size: 15px; padding: 56px 0; border: 1px dashed var(--line-hi); border-radius: var(--r); }

.sp-proof-stats { margin-top: 36px; display: grid; gap: 20px; }
.sp-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.sp-kpi { background: var(--bg); padding: 24px; margin: 0; }
.sp-kpi dt { font: 600 10.5px/1.3 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.sp-kpi dd { margin: 14px 0 0; font: 700 30px/1 var(--sans); letter-spacing: -0.04em; }
.sp-kpi dd small { font: 500 12.5px/1 var(--sans); letter-spacing: 0; color: var(--muted); margin-left: 8px; }

.sp-figure { margin: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: clamp(22px, 3vw, 30px); }
.sp-figure figcaption { max-width: 64ch; margin-bottom: 26px; }
.sp-figure figcaption p { margin-top: 8px; font-size: 14px; color: var(--muted); }
.sp-figure-note { margin-top: 20px; font-size: 12.5px; color: var(--dim); }

/* The bars are the four wheel colours, so green (3.0:1) and yellow (1.4:1) fall
   under the contrast floor against white. Every bar therefore carries a visible
   ink label with its share and count, each fill gets a hairline ring, and the
   reference rule sits above the fills with a white edge behind the dashes. */
.sp-meter { display: grid; gap: 16px; }
.sp-meter-row { display: grid; grid-template-columns: 110px 1fr 122px; align-items: center; gap: 18px; }
.sp-meter-name { display: flex; align-items: center; gap: 10px; font: 600 14px/1 var(--sans); }
.sp-meter-track { display: block; position: relative; height: 24px; background: var(--field); border-radius: 6px; }
.sp-meter-fill { display: block; height: 100%; border-radius: 4px 6px 6px 4px; background: var(--c); box-shadow: inset 0 0 0 1px rgba(16,17,20,.2); transition: width .55s var(--ease); }
.sp-meter-ref { display: block; position: absolute; top: -6px; bottom: -6px; width: 0; z-index: 2; border-left: 1.5px dashed rgba(16,17,20,.5); filter: drop-shadow(1px 0 0 rgba(255,255,255,.9)) drop-shadow(-1px 0 0 rgba(255,255,255,.9)); }
.sp-meter-ref span { position: absolute; top: -22px; left: 0; transform: translateX(-50%); font: 600 10px/1 var(--sans); letter-spacing: .1em; text-transform: uppercase; color: var(--dim); white-space: nowrap; }
.sp-meter-val { font: 600 14px/1 var(--sans); text-align: right; }
.sp-meter-val small { display: block; margin-top: 5px; font: 400 11.5px/1 var(--mono); color: var(--muted); }

.sp-proof-foot { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 24px; font-size: 13px; color: var(--muted); }

/* ---------- faq ---------- */

.sp-sec details { border-bottom: 1px solid var(--line); padding: 22px 0; }
.sp-sec summary { cursor: pointer; list-style: none; font: 600 17.5px/1.4 var(--sans); letter-spacing: -0.015em; transition: color .16s; }
.sp-sec summary::-webkit-details-marker { display: none; }
.sp-sec summary:hover { color: var(--muted); }
.sp-sec summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 4px; }
.sp-sec details p { margin-top: 14px; font-size: 15px; line-height: 1.7; color: var(--prose); max-width: 68ch; }

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

.sp-foot { border-top: 1px solid var(--line); padding: clamp(48px, 6vw, 72px) 0 40px; }
.sp-foot-top { display: flex; justify-content: space-between; gap: 40px; flex-wrap: wrap; }
.sp-foot-brand { font: 700 26px/1 var(--sans); letter-spacing: -0.04em; }
.sp-foot-tag { margin-top: 10px; font-size: 14.5px; color: var(--muted); }
.sp-foot-links { display: flex; flex-wrap: wrap; gap: 12px 28px; align-content: start; }
.sp-foot-bar { display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-top: 48px; padding-top: 22px; border-top: 1px solid var(--line); font-size: 12.5px; color: var(--muted); }
.sp-foot-status { font: 600 10.5px/1.6 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--dim); }
.sp-foot-note { margin-top: 20px; font-size: 12px; line-height: 1.75; color: var(--dim); max-width: 100ch; }

/* ---------- the door ---------- */

.sp-gate { width: min(600px, 94vw); padding: 0; border: 1.5px solid var(--ink); border-radius: 22px; background: var(--bg); color: var(--ink); box-shadow: var(--sh-lg); }
.sp-gate::backdrop { background: rgba(16, 17, 20, .55); backdrop-filter: blur(6px); }
.sp-gate-in { padding: clamp(26px, 4vw, 38px); }
.sp-gate h2 { font-size: clamp(26px, 4vw, 36px); margin: 10px 0 16px; }
.sp-gate-lede { font-size: 15px; line-height: 1.65; color: var(--prose); }
.sp-gate-list { margin: 22px 0 0; padding: 0; list-style: none; display: grid; gap: 12px; }
.sp-gate-list li { position: relative; padding-left: 26px; font-size: 14px; line-height: 1.6; color: var(--prose); }
.sp-gate-list li::before { content: ""; position: absolute; left: 0; top: .55em; width: 10px; height: 10px; border-radius: 50%; }
.sp-gate-list li:nth-child(1)::before { background: var(--red); }
.sp-gate-list li:nth-child(2)::before { background: var(--yellow); }
.sp-gate-list li:nth-child(3)::before { background: var(--green); }
.sp-gate-list li:nth-child(4)::before { background: var(--blue); }
.sp-gate-list b { color: var(--ink); }
.sp-gate-check { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start; margin-top: 26px; padding: 16px 18px; border: 1.5px solid var(--line-hi); border-radius: 14px; cursor: pointer; font-size: 13.5px; line-height: 1.55; color: var(--prose); }
.sp-gate-check:hover { border-color: var(--ink); }
.sp-gate-check input { width: 20px; height: 20px; accent-color: var(--ink); margin-top: 1px; cursor: pointer; }
.sp-gate-foot { margin-top: 22px; }

/* the mark a square wears: its logo when there is a file, the drawn sign when
   there is not. Stacked, with the image invisible until it has really loaded. */
.sp-glyph { display: block; }
.sp-mark { position: relative; display: block; width: var(--m); height: var(--m); }
.sp-mark .sp-glyph { position: absolute; inset: 0; margin: 0 !important; }
.sp-logo { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; opacity: 0; transition: opacity .2s; }
.sp-mark.has-logo .sp-glyph { visibility: hidden; }
.sp-mark.has-logo .sp-logo { opacity: 1; }

/* A real logo arrives in its own colours, so it gets a white disc to sit on —
   a red Tesla on a red circle is not a logo, it is a red circle. The colour is
   the whole code of this product, so it does not go away: it becomes the ring.
   A cell with no logo file keeps the coloured disc and its drawn mark. */
.sp-cell-node.has-logo, .sp-desk-mark.has-logo, .sp-result-mark.has-logo,
.sp-launch-mark.has-logo, .sp-confirm-mark.has-logo {
  background: #fff;
  box-shadow: inset 0 0 0 2px var(--c), inset 0 0 0 3px rgba(16, 17, 20, .06);
}
/* More of the disc than a line drawing needs, and wider than it is tall: a
   wordmark like Coca-Cola's is short and wide, and a square box would shrink
   it to the height of a letter. A square logo is still limited by the height,
   so it is unaffected. */
.has-logo > .sp-mark { width: 76%; height: 64%; }

/* ---------- responsive ---------- */

@media (max-width: 1080px) {
  .sp-nav-links { gap: 16px; font-size: 13.5px; }
}

/* Stacking the hero puts the wheel under the copy and roughly doubles its
   height, so it is only worth doing when the window has the height to spend.
   A 1024×800 laptop has room for two columns and none at all for one: stacked
   there, the hero ran 240px past the fold and took the motion control with it.
   Below 860px there is no horizontal room either way, so it stacks regardless. */
@media (max-width: 1080px) and (min-height: 860px), (max-width: 860px) {
  .sp-hero-in { grid-template-columns: 1fr; gap: 44px; }
  .sp-hero-copy { max-width: 620px; }
}

@media (max-width: 860px) {
  /* The preview is a mirror of the form. Stacked, it repeats what was just
     typed a screen further down, so it goes above the form rather than under
     it — seen before you fill anything in, ignored afterwards. */
  .sp-make { grid-template-columns: 1fr; gap: 20px; }
  .sp-aside { position: static; order: -1; }
  .sp-form { width: min(620px, 100%); margin-inline: auto; }
  .sp-aside { width: min(620px, 100%); margin-inline: auto; }

  .sp-hero-motion { position: static; margin-top: 24px; }
  /* and the scroll cue has nothing to say when the wheel is already half
     below the fold telling you the same thing */
  .sp-hero-more { display: none; }

  /* one column, so the hero is nearly twice as tall and every percentage in
     the slot table points somewhere else. Smaller, and the two that lived in
     the gap between the copy and the wheel have no gap to live in. */
  .sp-float { width: calc(var(--s) * .66); height: calc(var(--s) * .66); margin: calc(var(--s) * -.33); }
  .sp-float[data-zone="inner"] { display: none; }

  .sp-burger { display: block; }
  .sp-nav { flex-wrap: wrap; }
  .sp-nav-links {
    order: 3; width: 100%; margin: 0; display: none;
    flex-direction: column; gap: 2px; padding: 8px 0 18px;
  }
  .sp-nav.is-open { height: auto; border-radius: 26px; padding-bottom: 4px; }
  .sp-nav.is-open .sp-nav-links { display: flex; }
  .sp-nav-links a { padding: 12px 0; font-size: 16px; border-bottom: 1px solid var(--line); }
  /* the last rule would otherwise cut across the panel's rounded corner */
  .sp-nav-links a:last-child { border-bottom: 0; }
  .sp-nav-right { margin-left: auto; }
  .sp-launch { grid-template-columns: auto 1fr; gap: 12px 16px; }
  .sp-launch-pair, .sp-launch-time, .sp-launch-tx { grid-column: 2; }
}

@media (max-width: 600px) {
  .sp-float { width: calc(var(--s) * .5); height: calc(var(--s) * .5); margin: calc(var(--s) * -.25); }
  .sp-float[data-zone="band"] { display: none; }
  .sp-floaters { opacity: .62; }   /* six discs on a phone, and quieter */

  .sp-wrap, .sp-wrap-narrow, .sp-hero-in { width: calc(100% - 32px); }
  /* the bar is brand, wallet and menu at this width and nothing else: the
     fourth control pushed the row onto a second line, which a fixed-height
     sticky header then spilled over the top of the page */
  .sp-nav { width: calc(100% - 24px); padding: 0 8px 0 18px; gap: 12px; }
  .sp-nav-links { padding-inline: 10px 8px; }
  .sp-nav-right > .sp-btn { display: none; }
  .sp-nav-right { gap: 8px; }
  .sp-nav .sp-link { font-size: 13.5px; }
  .sp-hero-cta { gap: 16px; }
  .sp-btn-spin { width: 100%; padding: 18px; }
  .sp-meter-row { grid-template-columns: 96px 1fr; }
  .sp-meter-val { grid-column: 2; text-align: left; }
  .sp-meter-val small { display: inline; margin-left: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .sp-ticker-track, .sp-hero-wheel .sp-wheel-arrow { animation: none; }
  .sp-float { animation: none; opacity: var(--o); }
  .sp-float-in { animation: none; }
  .sp-wheel-arrow { transition-duration: .2s; }
  .sp-stage { animation: none; }
  .sp-btn, .sp-cell, .sp-desk-card, .sp-meter-fill, .sp-wheel-face { transition: none; }
}
