/* Strategy page (buy page) and the terms page. Tokens come from base.css, each planet's palette too (.look-*).
   Everything is dark. */

/* Saturn's hero photo is flatter than the others: less shade, and a little more contrast (its --hero-filter, base.css). */
.look-ringed .sp-hero {
  --shade: 0.1;
}

.sp-icon {
  flex: none;
}

/* ------------------------------------------------------------------ hero: a still photo of the planet, huge, on the left */

.sp-hero {
  /* Planet disc on screen: diameter --D, centre (--X, --Y) inside the hero box.
     --kw, --kh, --share, --y, --mk, --mx, --my and the disc numbers --dcx, --dcy, --dd (from manifest.json)
     are set on the element by templates/strategy.mjs, which also builds the img sizes attribute from them. */
  --D: min(calc(var(--kw) * 100vw), calc(var(--kh) * 100vh));
  --X: calc((var(--share) - 0.5) * var(--D));
  --Y: calc(var(--y) * 100%);
  /* Shown width of the whole (square) image. */
  --W: calc(var(--D) / var(--dd));
  /* How dark the photo is made ("a little darkened"): 0.3 means brightness 0.7. */
  --shade: 0.3;

  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: center;
  min-height: max(600px, 100svh);
  background: var(--space);
}

/* The preview banner pushes the hero down, keep the first screen exactly one screen high. */
body:has(> .preview-banner) .sp-hero {
  min-height: max(600px, calc(100svh - 37px));
}

/* How much of the halo and the nebula below shows: 1, but 0 while the arrival opens on plain space, from which it
   comes up with the stars (arrival block). Registered so it can fade; where it is not, it switches halfway. */
@property --sp-glow {
  syntax: "<number>";
  inherits: false;
  initial-value: 1;
}

/* The page's space tone, a soft halo of the planet's own colour around its disc (dark right at the limb, so the
   photo's edge never shows a light ring) and its nebula pair: one high on the text side, one low behind the planet. */
.sp-hero__space {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(circle calc(var(--D) * 0.5 + 520px) at var(--X) var(--Y), rgb(var(--globe-night-rgb) / var(--sp-glow, 1)) calc(var(--D) * 0.5), rgb(var(--globe-night-rgb) / calc(0.6 * var(--sp-glow, 1))) calc(var(--D) * 0.5 + 40px), rgb(var(--tint, 255 255 255) / calc(0.2 * var(--sp-glow, 1))) calc(var(--D) * 0.5 + 200px), rgb(var(--tint, 255 255 255) / 0) calc(var(--D) * 0.5 + 520px)),
    radial-gradient(60% 55% at 82% 26%, rgb(var(--nebula-1) / calc(0.22 * var(--sp-glow, 1))), transparent 72%),
    radial-gradient(55% 60% at 30% 92%, rgb(var(--nebula-2) / calc(0.26 * var(--sp-glow, 1))), transparent 70%),
    var(--space);
}

/* Faint stars behind the planet: the photo's stars, tinted (multiplied by --star-wash) and screened onto the blue,
   so its black never covers the blue, and kept off the planet's disc. */
.sp-hero__space::before {
  content: "";
  position: absolute;
  inset: 0;
  background-color: #000; /* the wash multiplies to black, not grey, where the photo is not painted */
  background-image: var(--star-wash), url("../planets/starfield.webp");
  background-size: 100% 100%, 100% 100%, 100% 100%, 1400px auto;
  background-repeat: no-repeat, no-repeat, no-repeat, repeat;
  background-position: center;
  background-blend-mode: multiply, multiply, multiply, normal;
  mix-blend-mode: screen;
  opacity: 0.6;
  -webkit-mask: radial-gradient(circle calc(var(--D) * 0.5 + 4px) at var(--X) var(--Y), transparent calc(100% - 6px), #000 100%);
  mask: radial-gradient(circle calc(var(--D) * 0.5 + 4px) at var(--X) var(--Y), transparent calc(100% - 6px), #000 100%);
}

.sp-hero__frame {
  position: absolute;
  left: calc(var(--X) - var(--dcx) * var(--W));
  top: calc(var(--Y) - var(--dcy) * var(--W));
  width: var(--W);
  height: var(--W);
  transform-origin: calc(var(--dcx) * 100%) calc(var(--dcy) * 100%);
}

/* The planet's tone (--hero-filter, base.css): its --planet-filter, warmer, brighter and more colourful than the file,
   as its globe is; the globe reads it back from here as its colour grade (strategy-planet3d.js). */
.sp-hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  filter: var(--hero-filter, var(--planet-filter));
}

/* The planet in 3D (assets/js/strategy-planet3d.js): a canvas over the photo, in the same place, under the reading
   shade and the gradients. Hidden until its first frame is drawn; its script sizes it to the part of the globe that is
   in the hero. Once the globe has taken over (sp-hero--3d) the photo under it is hidden, so the two never show
   doubled. The photo stays the first image, the fallback and what prints. */
.sp-hero__gl {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* base.css shows every canvas as a block, which would beat the hidden attribute: a canvas whose context is gone then
   shows as a grey broken image over the photo. */
.sp-hero__gl[hidden] {
  display: none;
}

.sp-hero--3d .sp-hero__frame {
  visibility: hidden;
}

/* The globe draws its own atmosphere: the photo's glow along the limb (::after below) fades out while the canvas
   shows, with the globe's 300 ms fade, and comes back with the photo. The night disc under it and the stars' mask
   stay, on the same circle as the globe's limb. */
.sp-hero--gl .sp-hero__space::after {
  --sp-limb: 0;
}

/* The globe fades in over the photo (300 ms; 600 ms for a late one, which comes while someone may be reading, with the
   limb glow's fade lengthened to match), and when 3D gives up on a slow device the photo comes back the same way.
   Leaving outranks the arrival's own rule for the canvas (html.sp-dawn-3d .sp-hero__gl), so it fades out also when
   3D gives up during first light. */
.sp-hero__gl.is-fading {
  animation: sp-show 0.3s cubic-bezier(0.4, 0, 0.2, 1) both;
}

.sp-hero__gl.is-fading.is-late {
  animation-duration: 0.6s;
}

.sp-hero--late .sp-hero__space::after {
  transition-duration: 0.6s;
}

.sp-hero .sp-hero__gl.is-leaving {
  animation: sp-out 0.3s cubic-bezier(0.4, 0, 0.2, 1) both;
}

@media print, (forced-colors: active) {
  .sp-hero__gl {
    display: none;
  }

  .sp-hero--3d .sp-hero__frame {
    visibility: visible;
  }

  .sp-hero--gl .sp-hero__space::after {
    --sp-limb: 1;
  }
}

/* Darkens the photo evenly. A layer (not a filter) so the arrival effect can fade it cheaply. In the space tone the
   planets were tuned under (--planet-shade-rgb, base.css), so the lighter page tones leave the planet as it was. */
.sp-hero__shade {
  position: absolute;
  inset: 0;
  background: rgb(var(--planet-shade-rgb) / var(--shade));
}

/* How much of the photo's atmosphere (the glow hugging the limb, below) shows: 1, but 0 while the 3D globe shows
   (sp-hero--gl), which draws its own. Registered so it can fade with the globe; where it is not, it switches, and
   every use falls back to 1 (unset and unregistered, it would void the whole background). */
@property --sp-limb {
  syntax: "<number>";
  inherits: false;
  initial-value: 1;
}

/* Keeps the header, the text side and the bottom edge dark so every line of text stays readable. That shade would
   hide the halo and the nebula, so the planet's atmosphere (a soft glow hugging the limb) and its nebula pair are
   drawn again on top of it, faint enough that the text keeps 7:1 or more. The shade under the header lies over the
   planet, so it is in the tone the planets were tuned under (--planet-shade-rgb); the bottom edge fades into the
   page's own space. */
.sp-hero__space::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(circle calc(var(--D) * 0.5 + 240px) at var(--X) var(--Y), rgb(var(--tint, 255 255 255) / 0) calc(var(--D) * 0.5 - 2px), rgb(var(--tint, 255 255 255) / calc(0.2 * var(--sp-limb, 1))) calc(var(--D) * 0.5 + 6px), rgb(var(--tint, 255 255 255) / calc(0.07 * var(--sp-limb, 1))) calc(var(--D) * 0.5 + 70px), rgb(var(--tint, 255 255 255) / 0) calc(var(--D) * 0.5 + 240px)),
    radial-gradient(48% 46% at 88% 18%, rgb(var(--nebula-1) / 0.2), transparent 72%),
    radial-gradient(46% 50% at 72% 100%, rgb(var(--nebula-2) / 0.22), transparent 70%),
    linear-gradient(180deg, rgb(var(--planet-shade-rgb) / 0.72) 0, rgb(var(--planet-shade-rgb) / 0.34) var(--header-h), rgb(var(--planet-shade-rgb) / 0) calc(var(--header-h) + 150px)),
    linear-gradient(0deg, var(--space) 0, rgb(var(--space-rgb) / 0.6) 70px, rgb(var(--space-rgb) / 0) 220px),
    linear-gradient(90deg, rgb(var(--space-rgb) / 0) 0, rgb(var(--space-rgb) / 0) 46%, rgb(var(--space-rgb) / 0.62) 55%, rgb(var(--space-rgb) / 0.86) 64%, rgb(var(--space-rgb) / 0.9) 100%);
  transition: --sp-limb 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.sp-hero__inner {
  position: relative;
  display: flex;
  justify-content: flex-end;
  padding-top: calc(var(--header-h) + 28px);
  padding-bottom: 56px;
}

.sp-hero__content {
  width: min(470px, 42vw);
}

.sp-hero__back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  margin: 0 0 14px -4px;
  padding: 0 4px;
  color: var(--on-dark-muted);
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  transition: color 0.15s ease;
}

.sp-hero__back:hover {
  color: var(--on-dark);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.sp-hero__eyebrow {
  display: block;
  margin: 0 0 0.6rem;
}

.sp-hero__title {
  margin: 0 0 0.3em;
  font-size: clamp(2.52rem, 1.344rem + 3.192vw, 4.2rem);
  font-weight: 400;
  line-height: 1.19;
  letter-spacing: 0;
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.55);
}

/* The lobby's same-page arrival focuses the name (lobby-land.js: tabindex -1), as a new page would start there: no
   ring for that, from the keyboard either, since nothing about the name changed. */
.sp-hero__title[tabindex="-1"]:focus {
  outline: none;
}

.sp-hero__tagline {
  max-width: 34ch;
  margin: 0 0 16px;
  font-size: clamp(1.0625rem, 0.98rem + 0.3vw, 1.25rem);
  line-height: 1.55;
  color: var(--on-dark);
  text-shadow: 0 1px 18px rgba(0, 0, 0, 0.6);
}

/* The first three things you get, in the buy box under the price (.sp-buy .sp-hero__gets has the rest). */
.sp-hero__gets {
  display: grid;
  gap: 6px;
  margin: 0 0 24px;
  padding: 0;
  list-style: none;
  color: var(--on-dark);
  font-size: 1rem;
  line-height: 1.4;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.6);
}

.sp-hero__gets li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

/* The ticks in the planet's light colour. */
.sp-hero__gets svg {
  flex: none;
  margin-top: 1px;
  color: rgb(var(--tint-hi, var(--on-dark-rgb)));
}

/* The page's lead, between the tagline and the buy box (heroStats in templates/results.mjs): the net result big in
   gold with "on one contract" beside it, the three figures of the gold cards in one row under it, and the label that
   says they are simulated, small. The eye goes to the gold first, then to the price and Subscribe (the owner,
   2026-10-09); win rate, profit factor and Sortino are one click down, in the results' "All the numbers". */
.sp-hero__stats {
  margin: 0 0 14px;
}

.sp-hero__lead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 10px;
  margin: 0 0 6px;
}

.sp-hero__lead-value {
  color: var(--accent);
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.3rem + 1.1vw, 2.2rem);
  font-weight: 400;
  line-height: 1.1;
  white-space: nowrap;
  text-shadow: 0 1px 18px rgb(var(--space-rgb) / 0.7);
}

.sp-hero__lead-note {
  color: var(--on-dark);
  font-size: 0.9375rem;
  text-shadow: 0 1px 14px rgb(var(--space-rgb) / 0.7);
}

/* The hero coming in on a page of its own (strategy-hero.js, motion on): hidden before the first paint
   (html.sp-intro, from the page's <head>, with a failsafe), then its pieces rise and fade in one after another, the
   tagline word by word (each in a .sp-word, inline-block so it can rise). The net result counts up (.is-counting:
   its final width kept, so the note beside it does not move) and then one gold shimmer crosses it (.sp-shine, once:
   a light band in the gold, drawn through the letters). Its dark halo moves from text-shadow to a drop-shadow filter
   meanwhile: a text-shadow is painted over text clipped from its background and would dim the gold. Never on paper;
   in forced colours the system's colours. */
html:where([data-motion="on"]).sp-intro :is(.sp-hero__eyebrow, .sp-hero__title, .sp-hero__tagline, .sp-hero__stats) {
  opacity: 0;
}

.sp-word {
  display: inline-block;
}

.sp-hero__lead-value.is-counting {
  display: inline-block;
}

.sp-hero__lead-value.sp-shine {
  background: linear-gradient(100deg, var(--accent) 0 38%, #fff1c4 50%, var(--accent) 62% 100%);
  background-size: 300% 100%;
  background-position: 100% 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: none;
  filter: drop-shadow(0 1px 9px rgb(var(--space-rgb) / 0.7));
  animation: sp-shine 1.4s cubic-bezier(0.4, 0, 0.2, 1) 1 both;
}

@keyframes sp-shine {
  to {
    background-position: 0 0;
  }
}

@media print, (forced-colors: active) {
  html.sp-intro :is(.sp-hero__eyebrow, .sp-hero__title, .sp-hero__tagline, .sp-hero__stats) {
    opacity: 1;
  }

  .sp-hero__lead-value.sp-shine {
    background: none;
    color: inherit;
    filter: none;
    animation: none;
  }
}

.sp-hero__stats-list {
  display: grid;
  grid-template-columns: repeat(3, auto);
  justify-content: start;
  gap: 2px 28px;
  margin: 0 0 6px;
}

.sp-hero__stat {
  min-width: 0;
}

.sp-hero__stat dt {
  margin: 0;
  color: var(--on-dark-muted);
  font-size: 0.8125rem;
  line-height: 1.35;
  white-space: nowrap;
}

.sp-hero__stat dd {
  margin: 0;
  color: var(--on-dark);
  font-family: var(--font-mono);
  font-size: 1.0625rem;
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
  white-space: nowrap;
}

.sp-hero__stats-label {
  margin: 0;
  color: rgb(var(--tint-hi, var(--on-dark-rgb)));
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  line-height: 1.4;
  text-transform: uppercase;
}

/* Narrow phones: the three spread over the row, the label a little closer set. */
@media (max-width: 420px) {
  .sp-hero__stats-list {
    justify-content: space-between;
    gap: 2px 12px;
  }

  .sp-hero__stats-label {
    letter-spacing: 0.06em;
  }

  .sp-hero__stat dt {
    font-size: 0.75rem;
  }

  .sp-hero__stat dd {
    font-size: 1rem;
  }
}

/* The shared header sits on top of the planet: a soft shadow helps the cream text. */
.sp-page .site-header__nav a,
.sp-hero__back {
  text-shadow: 0 1px 12px rgb(var(--space-rgb) / 0.85);
}

/* ------------------------------------------------------------------ buy box */

.sp-buy {
  padding: 16px 22px 18px;
  background: rgb(var(--space-2-rgb) / 0.8);
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
  box-shadow: 0 30px 80px rgb(var(--night-rgb) / 0.55);
  scroll-margin: 24px;
}

.sp-buy:focus {
  outline: none;
}

.sp-buy__price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  margin: 0 0 8px;
}

.sp-buy__price-amount {
  font-family: var(--font-display);
  font-size: 1.68rem;
  font-weight: 400;
  line-height: 1.19;
  letter-spacing: 0;
}

.sp-buy__price-amount--soon {
  font-size: 1.26rem;
}

/* The price is the other thing in the accent, wherever it stands: here, in the sticky bar and in the last call to
   action. "Price coming soon" is not a price, so it stays cream. */
.sp-buy__price-amount,
.sp-buybar__price-amount,
.sp-cta__price-amount {
  color: var(--accent);
}

.sp-buy__price-amount--soon,
.sp-cta__price-amount--soon {
  color: var(--on-dark);
}

.sp-buy__price-note {
  color: var(--on-dark-muted);
  font-size: 0.875rem;
}

/* What you get, between the price and the consent: price, contents and button read as one offer. */
.sp-buy .sp-hero__gets {
  margin: 0 0 12px;
  padding: 0 0 14px;
  border-bottom: 1px solid var(--line-dark);
  text-shadow: none;
}

/* "Before you subscribe", right above the two boxes and the button: what the law asks a buyer to see before paying,
   one short line each, in small print (smaller than the lines under the button: the box is to fit a 900 px screen). */
.sp-buy__before {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0 12px;
  align-items: baseline;
  margin: 0 0 4px;
  padding: 0 0 8px;
  border-bottom: 1px solid var(--line-dark);
  color: rgb(var(--on-dark-rgb) / 0.8);
  font-size: 0.8125rem;
  line-height: 1.4;
}

/* The links to the terms and the privacy page stand on the title's row, at its end; the rows under them. */
.sp-buy__before-list {
  grid-column: 1 / -1;
  grid-row: 2;
}

.sp-buy__before-title {
  margin: 0 0 4px;
  color: var(--on-dark-muted);
  font-size: 0.6825rem;
  line-height: 1.4;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.sp-buy__before-list {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The two confirmations, one row each, a little closer than the rows' padding would put them. */
.sp-buy__consents {
  margin: 0 0 4px;
}

.sp-buy__consent + .sp-buy__consent {
  margin-top: -6px;
}

.sp-buy__consent {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: 12px;
  align-items: start;
  margin: 0 -10px;
  padding: 9px 10px;
  border-radius: 12px;
}

.sp-buy__consent label {
  font-size: 0.9375rem;
  line-height: 1.45;
  cursor: pointer;
}

.sp-buy__check {
  appearance: none;
  -webkit-appearance: none;
  display: grid;
  place-content: center;
  width: 24px;
  height: 24px;
  margin: 0;
  border: 1.5px solid var(--on-dark);
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

.sp-buy__check::after {
  content: "";
  width: 16px;
  height: 16px;
  background: var(--space);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4.5 12.5l5 5L19.5 7' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M4.5 12.5l5 5L19.5 7' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  transform: scale(0);
  transition: transform 0.15s ease;
}

.sp-buy__check:checked {
  background: var(--on-dark);
}

.sp-buy__check:checked::after {
  transform: scale(1);
}

.sp-buy__check:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
}

/* Only the boxes still unticked light up (where :has() is missing, both do). */
.sp-buy.is-nudged .sp-buy__consent {
  animation: sp-nudge 0.9s ease;
}

.sp-buy.is-nudged .sp-buy__consent:has(.sp-buy__check:checked) {
  animation: none;
}

@keyframes sp-nudge {
  0%,
  100% { background: transparent; }
  25% { background: rgb(var(--on-dark-rgb) / 0.12); }
}

/* The links to the terms of sale and the privacy page, on the row of "Before you subscribe". */
.sp-buy__terms {
  grid-column: 2;
  grid-row: 1;
  margin: 0;
  white-space: nowrap;
}

.sp-buy__terms a {
  color: var(--on-dark-muted);
}

.sp-buy__terms a:hover {
  color: var(--on-dark);
}

.sp-buy__terms a,
.sp-faq a,
.sp-faq__more a {
  text-underline-offset: 3px;
}

.sp-buy__form {
  margin: 0;
}

.sp-buy__btn {
  width: 100%;
  min-height: 56px;
  font-size: 1.0625rem;
  letter-spacing: 0.02em;
}

/* Not active yet (box not ticked): still in the accent, outlined with a faint fill, so the eye finds the button before
   the tick and it never looks switched off. The buy button sits in a form with a required box, so the browser itself
   blocks the purchase until it is ticked (also without JS and from the keyboard); strategy.js adds aria-disabled and
   its own nudge. */
.sp-buy__btn[aria-disabled="true"],
.sp-buy:has(.sp-buy__check:not(:checked)) .sp-buy__btn[data-buy] {
  opacity: 1;
  background: rgb(var(--accent-rgb) / 0.1);
  color: var(--accent);
  box-shadow: inset 0 0 0 1.5px rgb(var(--accent-rgb) / 0.8);
  cursor: not-allowed;
}

.sp-buy__btn[aria-disabled="true"]:hover,
.sp-buy:has(.sp-buy__check:not(:checked)) .sp-buy__btn[data-buy]:hover {
  background: rgb(var(--accent-rgb) / 0.16);
}

/* No payment link yet ("Payment will be connected soon"): nothing to buy, so no accent on the button, nor on its focus
   ring. */
.sp-buy--soon .sp-buy__btn[aria-disabled="true"],
.sp-buy--soon .sp-buy__btn[aria-disabled="true"]:hover {
  background: rgb(var(--on-dark-rgb) / 0.06);
  color: rgb(var(--on-dark-rgb) / 0.72);
  box-shadow: inset 0 0 0 1px rgb(var(--on-dark-rgb) / 0.22);
}

.sp-buy--soon .sp-buy__btn:focus-visible {
  outline-color: var(--focus);
}

.sp-buy__btn[aria-disabled="true"]:active {
  transform: none;
}

.sp-buy__hint {
  margin: 10px 0 0;
  color: var(--on-dark-muted);
  font-size: 0.875rem;
  line-height: 1.45;
}

.sp-buy--soon .sp-buy__hint {
  color: var(--on-dark);
}

/* Both hints share one grid cell, so swapping them never moves the lines below. */
.sp-buy__hint {
  display: grid;
}

.sp-buy__hint > span {
  grid-area: 1 / 1;
}

.sp-buy__hint-on {
  visibility: hidden;
}

/* "Thank you" only once every box is ticked; until then the hint says what is missing (strategy.js names the box). */
.sp-buy:not(:has(.sp-buy__check:not(:checked))) .sp-buy__hint-off {
  visibility: hidden;
}

.sp-buy:not(:has(.sp-buy__check:not(:checked))) .sp-buy__hint-on {
  visibility: visible;
}

/* Calm lines right under the button, close to it: delivery, payment, the right to complain. */
.sp-buy__facts {
  display: grid;
  gap: 6px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
  color: rgb(var(--on-dark-rgb) / 0.8);
  font-size: 0.9063rem;
  line-height: 1.45;
}

.sp-buy__facts li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

.sp-buy__facts svg {
  width: 18px;
  height: 18px;
  margin-top: 1px;
  color: rgb(var(--on-dark-rgb) / 0.62);
}

.sp-buy__facts a {
  color: var(--on-dark);
  text-underline-offset: 3px;
}

/* Wide screens under 1,000 px tall: the box leaves out the short list of what you get, as short phones do (the
   section "What you get" lists it), so the price and Subscribe come up (the owner, 2026-10-09). They stand in the
   first screen at 1440 x 900 and taller, not on shorter laptops (at 1366 x 768 Subscribe ends 85 px under it without
   the test banner; README). The phone layout (below) keeps its own rules: the first query cannot match it, and the
   second only where it is short too. */
@media (min-width: 861px) and (max-height: 999px), (min-aspect-ratio: 3/2) and (max-height: 999px) {
  .sp-buy .sp-hero__gets {
    display: none;
  }
}

/* ------------------------------------------------------------------ arrival from the lobby: eclipse and first light */

/* The page opens on plain space from the lobby, the tone the lobby's departure ended on (arrivalHead and arrivalRun
   in templates/strategy.mjs). The name comes out of the dark first, with a hairline drawn under it; then the planet
   catches first light (a crescent with a warm rim along its limb) and daylight sweeps across it; then the page
   settles into its reading light and the price rises.
   Classes on <html>:
     sp-arrive         before the start: everything is hidden (with a failsafe that shows it after 2.6 s)
     sp-veil           the photo is hidden
     sp-arrive-run     the timeline: each element plays its keyframes, delayed by its --a-* token
     sp-dawn           the photo fades in under the umbra (a soft disc of space over the planet), which then slides off,
                       from --sp-dawn (set once the photo has decoded)
     sp-dawn-3d        instead of sp-dawn when the 3D globe is ready: its canvas fades in from --sp-dawn and its own
                       sun makes the crescent, the rim and the sweep (strategy-planet3d.js), so umbra and rim stay out;
                       if 3D gives up meanwhile, sp-dawn takes over from the same moment (a negative --sp-dawn)
     sp-arrive--short  the short version (second and later arrivals in a session): other tokens only
     sp-arrive-settle  300 ms after a tap skipped the arrival: nothing takes that tap
   --sp-skip is the part of the dark lead the navigation used up. Everything here is transform and opacity. */

.sp-hero__rim,
.sp-hero__umbra {
  display: none;
}

/* A photo layer that waits for its file (arrivalRun) fades in once decoded. The 1600 stand-in (.sp-hero__img--ph)
   sits before the sharper one in the DOM, so the sharper one fades in over it. */
.sp-hero__img.is-pending {
  opacity: 0;
}

.sp-hero__img.is-shown {
  opacity: 1;
  transition: opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

/* The arrival's timeline and its rules, with the motion setting on only (html[data-motion], base.css: calm and off
   open the page as it is, and the scripts add none of these classes then). The gate is in :where(), so every rule
   weighs what it did inside the media query it replaces. */

/* The timeline, in ms from the start of the page's own clock: delays (--a-*) and durations (--d-*). The dawn's
   own numbers count from the moment it starts (300 ms, or later if the photo is late). Keep END, DAWN_AT and
   DAWN in arrivalRun equal to these. */
:root:where([data-motion="on"]) {
  --sp-skip: 0ms;
  --sp-dawn: 0ms;
  --ease-fade: cubic-bezier(0.4, 0, 0.2, 1);
  --a-eyebrow: 120ms;
  --d-eyebrow: 360ms;
  --a-title: 160ms;
  --d-title: 480ms;
  --a-rule: 280ms;
  --d-rule: 360ms;
  --a-rule-out: 1000ms;
  --d-rule-out: 300ms;
  --a-tagline: 480ms;
  --a-buy: 600ms;
  --d-copy: 420ms;
  --a-dusk: 760ms; /* the readability gradients */
  --d-dusk: 400ms;
  --a-chrome: 800ms; /* header, banner, Back and everything below the hero */
  --d-chrome: 300ms;
  --a-shade: 820ms; /* the photo steps down from first light to reading light */
  --d-shade: 500ms;
  --a-stars: 1000ms;
  --d-stars: 340ms;
  --d-frame: 300ms; /* the photo fades in under the umbra */
  --a-rim-out: 600ms;
  --d-rim-out: 300ms;
  --rise: 10px;
}

/* Short version: about 1.3 s, no hairline, one sweep. */
:root:where([data-motion="on"]).sp-arrive--short {
  --a-eyebrow: 80ms;
  --d-eyebrow: 300ms;
  --a-title: 100ms;
  --d-title: 360ms;
  --a-tagline: 260ms;
  --a-buy: 340ms;
  --d-copy: 380ms;
  --a-dusk: 400ms;
  --d-dusk: 350ms;
  --a-chrome: 500ms;
  --d-chrome: 250ms;
  --a-shade: 450ms;
  --d-shade: 400ms;
  --a-stars: 600ms;
  --d-stars: 300ms;
  --d-frame: 200ms;
  --a-rim-out: 300ms;
  --d-rim-out: 250ms;
}

/* Geometry. The umbra is a disc of diameter --ud over the planet's disc (--X, --Y, --D). At dawn it slides along
   (--dvx, --dvy) toward the night side: a tenth of its diameter for first light, then all the way off. The rim is
   a thread of light on the limb (an ellipse for the flattened Jupiter and Saturn), only on an arc of --arc-w
   either side of --arc on the lit side (conic angles: 0deg up, 90deg right). */
:where(html[data-motion="on"]) .sp-hero {
  --ud: calc(var(--D) * 1.12);
  --dvx: -1;
  --dvy: 0;
  --oblate: 1;
  --rim: 0.38;
  --rim-x: 0;
  --rim-k: 1;
  --arc: 90deg;
  --arc-w: 60deg;
}

/* Saturn: the umbra also covers the rings, whose tips catch the light first. */
:where(html[data-motion="on"]) .look-ringed .sp-hero {
  --ud: calc(var(--W) * 1.42);
  --oblate: 0.9;
  --rim: 0.22;
  --arc-w: 35deg;
}

:where(html[data-motion="on"]) .look-gas .sp-hero {
  --oblate: 0.935;
}

/* Where a photo's limb is not quite the manifest's disc, the rim follows the photo (measured on the files): Earth's
   disc sits a little left and is a touch taller than wide, Neptune's lit limb a little inside. --rim-x is in discs,
   --rim-k scales the radius. */
:where(html[data-motion="on"]) .look-ocean .sp-hero {
  --rim-x: -0.0057;
  --rim-k: 0.9964;
  --oblate: 1.0174;
}

:where(html[data-motion="on"]) .look-ice .sp-hero {
  --rim-k: 0.993;
}

html:where([data-motion="on"]).sp-veil .sp-hero__frame {
  opacity: 0;
}

/* Shown from the moment the photo starts to fade in: before that the dark is the page's own (the umbra's soft
   edge over the same tone would not round to exactly the same colour). Laid out at a quarter of its size and
   scaled up, so its layer stays small; the soft edge is eased in steps so it never bands. */
html:where([data-motion="on"]).sp-dawn .sp-hero__umbra {
  display: block;
  position: absolute;
  left: calc(var(--X) - var(--ud) / 8);
  top: calc(var(--Y) - var(--ud) / 8);
  width: calc(var(--ud) / 4);
  height: calc(var(--ud) / 4);
  transform: scale(4);
  background: radial-gradient(closest-side, var(--space) 90%, rgb(var(--space-rgb) / 0.896) 92%, rgb(var(--space-rgb) / 0.648) 94%, rgb(var(--space-rgb) / 0.352) 96%, rgb(var(--space-rgb) / 0.104) 98%, rgb(var(--space-rgb) / 0) 100%);
  opacity: 0;
  /* 1040 ms: first light (0.1 of the diameter), a short hold, then daylight sweeps across. */
  animation:
    sp-umbra 1040ms linear var(--sp-dawn) both,
    sp-on 1ms step-start var(--sp-dawn) forwards;
}

html:where([data-motion="on"]).sp-dawn.sp-arrive--short .sp-hero__umbra {
  animation:
    sp-umbra-short 600ms cubic-bezier(0.45, 0, 0.2, 1) var(--sp-dawn) both,
    sp-on 1ms step-start var(--sp-dawn) forwards;
}

/* The size of the hero box, not of the disc: a 2 px core on the limb with a soft bloom, masked to the lit arc.
   It lies under the umbra, so the moving terminator reveals it along the limb. */
html:where([data-motion="on"]).sp-dawn .sp-hero__rim {
  --r: calc(var(--D) / 2 * var(--rim-k));
  display: block;
  position: absolute;
  inset: 0;
  background: radial-gradient(calc(var(--r) + 16px) calc((var(--r) + 16px) * var(--oblate)) at calc(var(--X) + var(--rim-x) * var(--D)) var(--Y), rgb(255 244 226 / 0) calc(var(--r) - 12px), rgb(255 244 226 / 0.16) calc(var(--r) - 5px), rgb(255 244 226 / 0.6) calc(var(--r) - 2px), rgb(255 244 226) calc(var(--r) - 1px), rgb(255 244 226) calc(var(--r) + 1px), rgb(255 244 226 / 0.34) calc(var(--r) + 3px), rgb(255 244 226 / 0.1) calc(var(--r) + 8px), rgb(255 244 226 / 0) calc(var(--r) + 16px));
  -webkit-mask: conic-gradient(from 0deg at var(--X) var(--Y), transparent calc(var(--arc) - var(--arc-w)), #000 calc(var(--arc) - var(--arc-w) / 3), #000 calc(var(--arc) + var(--arc-w) / 3), transparent calc(var(--arc) + var(--arc-w)));
  mask: conic-gradient(from 0deg at var(--X) var(--Y), transparent calc(var(--arc) - var(--arc-w)), #000 calc(var(--arc) - var(--arc-w) / 3), #000 calc(var(--arc) + var(--arc-w) / 3), transparent calc(var(--arc) + var(--arc-w)));
  --on: var(--rim);
  opacity: 0;
  animation:
    sp-on 1ms step-start var(--sp-dawn) forwards,
    sp-out var(--d-rim-out) var(--ease-fade) calc(var(--sp-dawn) + var(--a-rim-out)) both;
}

html:where([data-motion="on"]).sp-dawn .sp-hero__frame {
  animation: sp-show var(--d-frame) linear var(--sp-dawn) both;
}

/* First light in 3D: the globe shows up as the photo would (it starts in backlight: a disc of the page's space
   tone with the atmosphere's ring), and the photo stays veiled. */
html:where([data-motion="on"]).sp-dawn-3d .sp-hero__umbra,
html:where([data-motion="on"]).sp-dawn-3d .sp-hero__rim {
  display: none;
}

html:where([data-motion="on"]).sp-dawn-3d .sp-hero__gl {
  animation: sp-show var(--d-frame) linear var(--sp-dawn) both;
}

/* Before the start. The failsafe shows the page after 2.6 s if the runner never starts. */
html:where([data-motion="on"]).sp-arrive .preview-banner,
html:where([data-motion="on"]).sp-arrive .site-header,
html:where([data-motion="on"]).sp-arrive .sp-hero__content > *,
html:where([data-motion="on"]).sp-arrive main > :not(.sp-hero),
html:where([data-motion="on"]).sp-arrive .site-footer,
html:where([data-motion="on"]).sp-arrive .sp-hero__space::after {
  opacity: 0;
  animation: sp-show 1ms 2.6s both;
}

html:where([data-motion="on"]).sp-arrive .sp-hero__space::before {
  opacity: 0;
  animation: sp-show-stars 1ms 2.6s both;
}

/* The halo and the nebula too, so the page opens on the same plain space the lobby left. */
html:where([data-motion="on"]).sp-arrive .sp-hero__space {
  --sp-glow: 0;
  animation: sp-show-glow 1ms 2.6s both;
}

html:where([data-motion="on"]).sp-arrive .sp-hero__frame {
  animation: sp-show 1ms 2.6s both;
}

/* While it comes in, and just after a tap skipped the arrival, nothing on top takes a tap (the consent boxes,
   Subscribe, Back, the header). Not before the start: if the runner never started, the failsafe page must work. */
html:where([data-motion="on"]).sp-arrive-run .preview-banner,
html:where([data-motion="on"]).sp-arrive-run .site-header,
html:where([data-motion="on"]).sp-arrive-run .sp-hero__content,
html:where([data-motion="on"]).sp-arrive-settle .preview-banner,
html:where([data-motion="on"]).sp-arrive-settle .site-header,
html:where([data-motion="on"]).sp-arrive-settle .sp-hero__content {
  pointer-events: none;
}

/* The timeline. Opacity and the rise ease differently, so they are two animations; --rise is how far it rises. */
html:where([data-motion="on"]).sp-arrive-run .sp-hero__content > * {
  animation:
    sp-fade var(--d-copy) var(--ease-fade) calc(var(--a-buy) - var(--sp-skip)) both,
    sp-rise var(--d-copy) cubic-bezier(0.2, 0.7, 0.2, 1) calc(var(--a-buy) - var(--sp-skip)) both;
}

html:where([data-motion="on"]).sp-arrive-run .sp-hero__eyebrow {
  --rise: 6px;
  animation:
    sp-fade var(--d-eyebrow) var(--ease-fade) calc(var(--a-eyebrow) - var(--sp-skip)) both,
    sp-rise var(--d-eyebrow) cubic-bezier(0.22, 1, 0.36, 1) calc(var(--a-eyebrow) - var(--sp-skip)) both;
}

/* The title card: the real H1, in its own place and type. */
html:where([data-motion="on"]).sp-arrive-run .sp-hero__title {
  position: relative;
  animation:
    sp-fade var(--d-title) var(--ease-fade) calc(var(--a-title) - var(--sp-skip)) both,
    sp-rise var(--d-title) cubic-bezier(0.16, 1, 0.3, 1) calc(var(--a-title) - var(--sp-skip)) both;
}

/* The hairline under the name (the logo's ring stroke): drawn from the left, then gone. Full version only. */
html:where([data-motion="on"]).sp-arrive-run:not(.sp-arrive--short) .sp-hero__title::after {
  content: "";
  position: absolute;
  left: 0;
  top: calc(100% + 0.1em);
  width: 2.2em;
  height: 1px;
  background: rgb(var(--on-dark-rgb) / 0.35);
  transform-origin: left;
  animation:
    sp-rule var(--d-rule) cubic-bezier(0.65, 0, 0.35, 1) calc(var(--a-rule) - var(--sp-skip)) both,
    sp-out var(--d-rule-out) var(--ease-fade) calc(var(--a-rule-out) - var(--sp-skip)) both;
}

html:where([data-motion="on"]).sp-arrive-run .sp-hero__tagline {
  animation:
    sp-fade var(--d-copy) var(--ease-fade) calc(var(--a-tagline) - var(--sp-skip)) both,
    sp-rise var(--d-copy) cubic-bezier(0.2, 0.7, 0.2, 1) calc(var(--a-tagline) - var(--sp-skip)) both;
}

html:where([data-motion="on"]).sp-arrive-run .preview-banner,
html:where([data-motion="on"]).sp-arrive-run .site-header,
html:where([data-motion="on"]).sp-arrive-run .sp-hero__back,
html:where([data-motion="on"]).sp-arrive-run main > :not(.sp-hero),
html:where([data-motion="on"]).sp-arrive-run .site-footer {
  animation: sp-fade var(--d-chrome) var(--ease-fade) calc(var(--a-chrome) - var(--sp-skip)) both;
}

html:where([data-motion="on"]).sp-arrive-run .sp-hero__space::after {
  animation: sp-fade var(--d-dusk) var(--ease-fade) calc(var(--a-dusk) - var(--sp-skip)) both;
}

html:where([data-motion="on"]).sp-arrive-run .sp-hero__shade {
  animation: sp-shade var(--d-shade) var(--ease-fade) calc(var(--a-shade) - var(--sp-skip)) both;
}

html:where([data-motion="on"]).sp-arrive-run .sp-hero__space::before {
  animation: sp-fade var(--d-stars) var(--ease-fade) calc(var(--a-stars) - var(--sp-skip)) both;
}

html:where([data-motion="on"]).sp-arrive-run .sp-hero__space {
  animation: sp-glow var(--d-stars) var(--ease-fade) calc(var(--a-stars) - var(--sp-skip)) both;
}

/* The lobby's same-page landing (assets/js/lobby-land.js; arrivalRun's land()). The fly-over has rolled the globe
   into the rest pose on the look's plain space; the page comes in round it: its sky (the halo, the nebula, the stars
   and the readability gradients), the header and Back come up, and the text comes in one piece after another,
   --l-step apart, each a small rise (--l-rise) and a fade: the eyebrow and the name, the tagline, the numbers over the
   box with the price, Subscribe with its box, and the lines under it. The rest of the page is simply there below. Keep
   LAND in land() equal to the last piece's end (4 steps and --l-copy). */
:root:where([data-motion="on"]) {
  --l-step: 300ms;
  --l-copy: 420ms;
  --l-sky: 600ms;
  --l-rise: 8px;
}

:root:where([data-motion="on"]).sp-land--short {
  --l-step: 250ms;
  --l-copy: 380ms;
  --l-sky: 500ms;
}

html:where([data-motion="on"]).sp-land .sp-hero__space {
  animation: sp-glow var(--l-sky) var(--ease-fade) both;
}

html:where([data-motion="on"]).sp-land .sp-hero__space::before,
html:where([data-motion="on"]).sp-land .sp-hero__space::after {
  animation: sp-fade var(--l-sky) var(--ease-fade) both;
}

html:where([data-motion="on"]).sp-land .preview-banner,
html:where([data-motion="on"]).sp-land .site-header,
html:where([data-motion="on"]).sp-land .sp-hero__back {
  animation: sp-fade var(--l-copy) var(--ease-fade) both;
}

html:where([data-motion="on"]).sp-land .sp-hero__eyebrow,
html:where([data-motion="on"]).sp-land .sp-hero__title {
  --pop: 0;
}

html:where([data-motion="on"]).sp-land .sp-hero__tagline {
  --pop: 1;
}

html:where([data-motion="on"]).sp-land .sp-buy > * {
  --pop: 3;
}

html:where([data-motion="on"]).sp-land .sp-buy__price,
html:where([data-motion="on"]).sp-land .sp-hero__stats {
  --pop: 2;
}

html:where([data-motion="on"]).sp-land .sp-buy > .sp-buy__facts {
  --pop: 4;
}

html:where([data-motion="on"]).sp-land :is(.sp-hero__eyebrow, .sp-hero__title, .sp-hero__tagline, .sp-buy > *, .sp-hero__stats) {
  --rise: var(--l-rise);
  animation:
    sp-fade var(--l-copy) var(--ease-fade) calc(var(--pop) * var(--l-step)) both,
    sp-rise var(--l-copy) cubic-bezier(0.2, 0.7, 0.2, 1) calc(var(--pop) * var(--l-step)) both;
}

/* The box comes with Subscribe: its fill, edge and shadow fade in round the price already there. */
html:where([data-motion="on"]).sp-land .sp-buy {
  animation: sp-box var(--l-copy) var(--ease-fade) calc(3 * var(--l-step)) both;
}

/* While it comes in nothing on top takes a tap (a tap shows it all at once instead), as in the arrival above. */
html:where([data-motion="on"]).sp-land .preview-banner,
html:where([data-motion="on"]).sp-land .site-header,
html:where([data-motion="on"]).sp-land .sp-hero__content {
  pointer-events: none;
}

/* From nothing to the element's own opacity (the stars' .6, the shade's), so the end is the page as it is. */
@keyframes sp-fade {
  from {
    opacity: 0;
  }
}

@keyframes sp-show {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes sp-show-stars {
  from {
    opacity: 0;
  }

  to {
    opacity: 0.6;
  }
}

@keyframes sp-glow {
  from {
    --sp-glow: 0;
  }
}

@keyframes sp-show-glow {
  from {
    --sp-glow: 0;
  }

  to {
    --sp-glow: 1;
  }
}

@keyframes sp-out {
  to {
    opacity: 0;
  }
}

/* Switches a layer on when the dawn starts (forwards only, so it is off before): to --on, or fully. */
@keyframes sp-on {
  from,
  to {
    opacity: var(--on, 1);
  }
}

@keyframes sp-rise {
  from {
    transform: translateY(var(--rise));
  }
}

@keyframes sp-box {
  from {
    border-color: transparent;
    background-color: rgb(var(--space-2-rgb) / 0);
    box-shadow: 0 30px 80px rgb(var(--night-rgb) / 0);
  }
}

@keyframes sp-shade {
  from {
    opacity: 0.4;
  }
}

@keyframes sp-rule {
  from {
    transform: scaleX(0);
  }
}

/* t' 300-660 first light, 660-740 hold, 740-1340 daylight. */
@keyframes sp-umbra {
  0% {
    transform: translate(0, 0) scale(4);
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
  }

  34.6% {
    transform: translate(calc(var(--dvx) * var(--ud) * 0.1), calc(var(--dvy) * var(--ud) * 0.1)) scale(4);
    animation-timing-function: linear;
  }

  42.3% {
    transform: translate(calc(var(--dvx) * var(--ud) * 0.1), calc(var(--dvy) * var(--ud) * 0.1)) scale(4);
    animation-timing-function: cubic-bezier(0.55, 0, 0.25, 1);
  }

  100% {
    transform: translate(calc(var(--dvx) * var(--ud)), calc(var(--dvy) * var(--ud))) scale(4);
  }
}

@keyframes sp-umbra-short {
  from {
    transform: translate(0, 0) scale(4);
  }

  to {
    transform: translate(calc(var(--dvx) * var(--ud)), calc(var(--dvy) * var(--ud))) scale(4);
  }
}

/* ------------------------------------------------------------------ small and portrait screens: the planet edge across the top */

/* Must match SMALL_MEDIA in templates/hero-layout.mjs (and its copies in assets/js/strategy-planet3d.js and
   tools/planets3d/review.html). Landscape phones (wide and short) keep the wide layout below. */
@media (max-width: 860px) and (max-aspect-ratio: 3/2), (max-aspect-ratio: 4/5) {
  .sp-hero {
    --D: calc(var(--mk) * 100vw);
    --X: calc(var(--mx) * 100vw);
    --Y: calc(var(--my) * 100vw);
    --shade: 0.22;
    /* Where the text starts: as low as the first screen allows while it still holds the name, the tagline, the net
       result with its three figures, the price and Subscribe (the owner, 2026-10-09: sell on the phone), about 50 px
       to spare under Subscribe with the test banner, so the planet's edge keeps a band above the text (the text
       starts 140 px down the hero at 390 x 844, 112 px at 375 x 812, and never less than 84 px). Only the text
       moves: the disc (LAYOUT in hero-geometry.mjs) stays where the fly-over lands. */
    --text-top: clamp(84px, calc(100svh - 700px), 36vw);
    /* The arrival's dawn (see above): the light comes from the lower right of the disc, so the crescent and the rim
       run along the horizon arc and daylight sweeps toward the upper left. */
    --dvx: -0.866;
    --dvy: -0.5;
    --arc: 120deg;
    align-items: flex-start;
    min-height: 0;
  }

  body:has(> .preview-banner) .sp-hero {
    min-height: 0;
  }

  /* The planet's edge runs across the top: its halo sits under it and the nebula pair lower down. */
  .sp-hero__space {
    background:
      radial-gradient(circle calc(var(--D) * 0.5 + 260px) at var(--X) var(--Y), rgb(var(--globe-night-rgb) / var(--sp-glow, 1)) calc(var(--D) * 0.5), rgb(var(--tint, 255 255 255) / calc(0.26 * var(--sp-glow, 1))) calc(var(--D) * 0.5 + 60px), rgb(var(--tint, 255 255 255) / 0) calc(var(--D) * 0.5 + 260px)),
      radial-gradient(80% 40% at 90% 60%, rgb(var(--nebula-1) / calc(0.22 * var(--sp-glow, 1))), transparent 72%),
      radial-gradient(80% 40% at 10% 85%, rgb(var(--nebula-2) / calc(0.24 * var(--sp-glow, 1))), transparent 70%),
      var(--space);
  }

  .sp-hero__space::before {
    background-size: 100% 100%, 100% 100%, 100% 100%, 900px auto;
  }

  /* The nebula pair, then a little dark under the header and a fade into solid space just where the text starts,
     then the atmosphere. Here the limb runs right down to the text, so the atmosphere lies under the fade: on top of
     it, it put Back and the eyebrow under 7:1 on Earth. The fade never starts above the header's bottom, which has its
     own dark, and stays light until just above Back, so the planet shows in the band between them even where the text
     starts right under the header; at Back it is 0.86 (Back and the eyebrow at 7.4:1 or more on every look). */
  .sp-hero__space::after {
    background:
      radial-gradient(70% 30% at 95% 55%, rgb(var(--nebula-1) / 0.2), transparent 72%),
      radial-gradient(70% 30% at 5% 80%, rgb(var(--nebula-2) / 0.2), transparent 70%),
      linear-gradient(180deg, rgb(var(--planet-shade-rgb) / 0.62) 0, rgb(var(--planet-shade-rgb) / 0.22) var(--header-h), rgb(var(--planet-shade-rgb) / 0) calc(var(--header-h) + 40px)),
      linear-gradient(180deg, rgb(var(--planet-shade-rgb) / 0) 0, rgb(var(--planet-shade-rgb) / 0) max(var(--header-h), calc(var(--text-top) - 110px)), rgb(var(--planet-shade-rgb) / 0.3) max(calc(var(--text-top) - 24px), calc(var(--header-h) / 2 + var(--text-top) / 2)), rgb(var(--space-rgb) / 0.86) calc(var(--text-top) + 8px), var(--space) calc(var(--text-top) + 90px)),
      radial-gradient(circle calc(var(--D) * 0.5 + 160px) at var(--X) var(--Y), rgb(var(--tint, 255 255 255) / 0) calc(var(--D) * 0.5 - 2px), rgb(var(--tint, 255 255 255) / calc(0.24 * var(--sp-limb, 1))) calc(var(--D) * 0.5 + 6px), rgb(var(--tint, 255 255 255) / calc(0.08 * var(--sp-limb, 1))) calc(var(--D) * 0.5 + 50px), rgb(var(--tint, 255 255 255) / 0) calc(var(--D) * 0.5 + 160px));
  }

  .sp-hero__inner {
    display: block;
    padding-top: var(--text-top);
    padding-bottom: 48px;
  }

  .sp-hero__content {
    width: auto;
    max-width: 560px;
  }

  .sp-hero__back {
    margin-bottom: 2px;
  }

  .sp-hero__eyebrow {
    margin-bottom: 0.4rem;
  }

  .sp-hero__tagline {
    margin-bottom: 12px;
    font-size: 1rem;
  }

  .sp-hero__gets {
    gap: 4px;
    margin-bottom: 20px;
    font-size: 0.9375rem;
  }

  .sp-buy .sp-hero__gets {
    margin-bottom: 14px;
    padding-bottom: 12px;
  }

  /* In the box Subscribe and its hint come right after the price (and what you get, where it shows), so they stand in
     the first screen; "Before you subscribe", the two boxes and the calm lines follow under it. The order is the
     screen's only: the page's own order, read by a screen reader and by Tab, stays the one the law reads (what you
     should know, the boxes, then the button). The form lets its children into the box's column (display: contents),
     so the order can reach them; it still submits as a form. */
  .sp-buy {
    display: flex;
    flex-direction: column;
    padding: 18px 18px 18px;
  }

  .sp-buy__form {
    display: contents;
  }

  .sp-buy__price {
    order: 1;
  }

  .sp-buy .sp-hero__gets {
    order: 2;
  }

  .sp-buy__btn {
    order: 3;
  }

  .sp-buy__hint {
    order: 4;
    margin: 8px 0 14px;
  }

  .sp-buy__before {
    order: 5;
  }

  /* Under the button there is room: the links to the terms and the privacy page go under the rows again. */
  .sp-buy__terms {
    grid-column: 1 / -1;
    grid-row: 3;
    margin-top: 6px;
  }

  .sp-buy__consents {
    order: 6;
  }

  .sp-buy__facts {
    order: 7;
  }

  /* The landing brings the box's pieces in one after another (.sp-buy > *, above); the form's own pieces are in the
     box's column here, so they come in with Subscribe themselves. */
  html:where([data-motion="on"]).sp-land .sp-buy__form > * {
    --pop: 3;
    --rise: var(--l-rise);
    animation:
      sp-fade var(--l-copy) var(--ease-fade) calc(var(--pop) * var(--l-step)) both,
      sp-rise var(--l-copy) cubic-bezier(0.2, 0.7, 0.2, 1) calc(var(--pop) * var(--l-step)) both;
  }
}

/* Short phones: a little tighter so the buy button fits on the first screen. The short list of what you get is left
   out here (the next section lists it), so the text can start lower and the planet keeps its room. */
@media (max-width: 860px) and (max-aspect-ratio: 3/2) and (max-height: 780px) {
  .sp-hero {
    --text-top: clamp(84px, calc(100svh - 560px), 36vw);
  }

  .sp-hero__gets {
    display: none;
  }

  .sp-hero__title {
    font-size: 2.31rem;
  }

  .sp-hero__tagline {
    margin-bottom: 16px;
  }

  .sp-buy__price {
    margin-bottom: 10px;
  }
}

/* Landscape phones: the wide layout, a bit tighter, with a wider text column. */
@media (max-height: 500px) and (min-aspect-ratio: 3/2) {
  /* The hero is taller than the screen here, so the disc height is taken from the screen, not from the hero. */
  .sp-hero {
    --Y: calc(var(--y) * 100svh + 24px);
    min-height: 0;
  }

  body:has(> .preview-banner) .sp-hero {
    min-height: 0;
  }

  .sp-hero__inner {
    padding-top: calc(var(--header-h) + 8px);
    padding-bottom: 40px;
  }

  .sp-hero__content {
    width: min(470px, 50vw);
  }

  .sp-hero__title {
    font-size: 2.1rem;
  }
}

@media (max-width: 380px) {
  .sp-buy__price-amount {
    font-size: 1.47rem;
  }
}

/* ------------------------------------------------------------------ content sections (dark) */

.sp-section {
  padding: clamp(64px, 8.5vw, 112px) 0;
  background: var(--space);
  color: var(--on-dark);
  border-top: 1px solid var(--line-dark);
}

.sp-section--alt {
  background: var(--space-2);
}

.sp-section h2 {
  margin-bottom: 0.35em;
  font-weight: 400;
}

.sp-head {
  max-width: 640px;
  margin-bottom: clamp(28px, 4vw, 44px);
}

.sp-head p {
  margin: 0;
  font-size: 1.125rem;
}

/* Round thin-line icons used in the lists, in the planet's light colour. */
.sp-gets__item-icon,
.sp-fit__item-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  color: rgb(var(--tint-hi, var(--on-dark-rgb)));
  box-shadow: inset 0 0 0 1px rgb(var(--tint-hi, var(--on-dark-rgb)) / 0.45);
}

/* What you get (in Details) */
.sp-gets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sp-gets__item {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 26px 24px 28px;
  /* The planet's colour, faint, in the edge and the fill. */
  border: 1px solid rgb(var(--tint-hi, var(--on-dark-rgb)) / 0.2);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgb(var(--tint, 255 255 255) / 0.12), rgb(var(--tint, 255 255 255) / 0.03));
  font-size: 1.125rem;
  line-height: 1.45;
}

@media (max-width: 600px) {
  .sp-gets__item {
    flex-direction: row;
    align-items: flex-start;
    gap: 16px;
    padding: 20px;
  }

  .sp-gets__item > span:last-child {
    padding-top: 7px;
  }
}

/* At a glance: the strategy's facts as one row of small chips under the results' closing Subscribe (factsChips in
   templates/strategy.mjs), with no heading: the label small in the planet's lighter tone, the value after it. They
   wrap onto more lines where the row is short. */
.sp-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: clamp(20px, 3vw, 28px) 0 0;
}

.sp-chip {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 8px;
  max-width: 100%;
  padding: 7px 14px;
  border: 1px solid rgb(var(--tint-hi, var(--on-dark-rgb)) / 0.22);
  border-radius: 18px;
  background: rgb(var(--tint, 255 255 255) / 0.05);
  font-size: 0.875rem;
  line-height: 1.4;
}

.sp-chip dt {
  color: rgb(var(--tint-hi, var(--on-dark-rgb)));
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.sp-chip dd {
  margin: 0;
}

/* Details (detailsSection in templates/strategy.mjs): what you get, what you need and the questions in one calm band,
   three native <details>, closed, each a card with its name and one line. One a line on phones; in a row on wide
   screens, where the open one's content runs under all three (its width the row's, its left edge pulled back to the
   row's: --n cards and the gap between them) and the others close as it opens (name, strategy.js). Two open at once
   (a browser without name and without JavaScript) fall back to one a line. Everything prints open (below). */
.sp-details {
  padding: clamp(48px, 6vw, 80px) 0;
}

.sp-details__title {
  margin: 0 0 clamp(18px, 2.5vw, 24px);
  color: var(--on-dark-muted);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  line-height: 1.5;
  text-transform: uppercase;
}

.sp-details__row {
  --gap: 14px;
  display: grid;
  gap: var(--gap);
}

.sp-detail > summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px 20px;
  border: 1px solid rgb(var(--tint-hi, var(--on-dark-rgb)) / 0.2);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgb(var(--tint, 255 255 255) / 0.1), rgb(var(--tint, 255 255 255) / 0.02));
  list-style: none;
  cursor: pointer;
  transition: border-color 0.2s ease;
}

.sp-detail > summary::-webkit-details-marker {
  display: none;
}

.sp-detail[open] > summary {
  border-color: rgb(var(--tint-hi, var(--on-dark-rgb)) / 0.6);
}

.sp-detail__head {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.sp-detail__name {
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.4;
}

.sp-detail > summary:hover .sp-detail__name {
  text-decoration: underline;
  text-underline-offset: 4px;
}

.sp-detail__line {
  color: var(--on-dark-muted);
  font-size: 0.9375rem;
  line-height: 1.45;
}

/* "Tashmetu add-on" never breaks at its hyphen. */
.sp-detail__keep {
  white-space: nowrap;
}

.sp-detail__icon {
  flex: none;
  margin-top: 2px;
  color: var(--on-dark-muted);
  transition: transform 0.2s ease;
}

.sp-detail[open] .sp-detail__icon {
  transform: rotate(45deg);
}

.sp-detail__body {
  padding: clamp(24px, 3.5vw, 36px) 0 clamp(8px, 2vw, 20px);
}

.sp-detail__intro {
  margin: 0 0 18px;
  font-size: 1.0625rem;
}

.sp-detail__body .sp-steps {
  margin-top: clamp(32px, 4.5vw, 48px);
}

@media (min-width: 900px) {
  .sp-details__row {
    grid-template-columns: repeat(var(--n, 3), minmax(0, 1fr));
    align-items: start;
  }

  /* As tall as a name and three lines, so the open card's content starts level under all three, in a browser that
     cannot lay the three out as one grid (below, where the tallest sets the height). */
  .sp-detail > summary {
    min-height: 135px;
  }

  .sp-detail__body {
    width: calc(var(--n, 3) * 100% + (var(--n, 3) - 1) * var(--gap));
  }

  .sp-detail:nth-child(2) > .sp-detail__body {
    margin-left: calc(-100% - var(--gap));
  }

  .sp-detail:nth-child(3) > .sp-detail__body {
    margin-left: calc(-200% - 2 * var(--gap));
  }

  .sp-details__row:has(.sp-detail[open] ~ .sp-detail[open]) {
    grid-template-columns: minmax(0, 1fr);
  }

  .sp-details__row:has(.sp-detail[open] ~ .sp-detail[open]) .sp-detail__body {
    width: auto;
    margin-left: 0;
  }
}

@media (min-width: 900px) and (max-width: 1099px) {
  .sp-detail > summary {
    min-height: 138px;
  }
}

/* Where <details> can be a grid (::details-content), the three summaries share one grid row and the open one's
   content the next (each <details> spans both, its rows the row's: subgrid), so all three stand as tall as the
   tallest, whatever a strategy's name or a line makes of them, and the content starts level under all three. A fixed
   height could not: "the Gilgamesh add-on" takes a third line on every wide screen. Two open at once (no `name`, no
   JavaScript) fall back to one a line, each a block again. */
@supports selector(::details-content) {
  @media screen and (min-width: 900px) {
    .sp-details__row {
      grid-template-rows: auto auto;
      row-gap: 0;
    }

    .sp-detail {
      display: grid;
      grid-row: span 2;
      grid-template-rows: subgrid;
    }

    .sp-detail > summary {
      min-height: 0;
    }

    .sp-details__row:has(.sp-detail[open] ~ .sp-detail[open]) {
      grid-template-rows: none;
      row-gap: var(--gap);
    }

    .sp-details__row:has(.sp-detail[open] ~ .sp-detail[open]) .sp-detail {
      display: block;
      grid-row: auto;
    }
  }
}

/* On paper nothing is one click down: Details and its questions print open, one under the other (strategy.js opens
   them too, for a browser without ::details-content). */
@media print {
  .sp-details__row {
    display: block;
  }

  .sp-detail__body {
    width: auto;
    margin-left: 0;
  }

  .sp-detail::details-content,
  .sp-faq__item::details-content {
    content-visibility: visible;
    display: block;
  }

  .sp-detail > summary {
    min-height: 0;
  }

  .sp-detail__icon,
  .sp-faq__icon {
    display: none;
  }
}

/* What you need */
.sp-fit {
  margin: 0;
  padding: 0;
  list-style: none;
}

.sp-fit__item {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 20px 0;
  border-top: 1px solid var(--line-dark);
  font-size: 1.125rem;
  line-height: 1.5;
}

.sp-fit__item:last-child {
  border-bottom: 1px solid var(--line-dark);
}

.sp-fit__item > span:last-child {
  padding-top: 7px;
}

/* ------------------------------------------------------------------ results (templates/results.mjs)
   One curve over the section's width, under the label that says the figures are simulated (with its link to the
   terms); then trade by trade, and the plain figures one click down. In the planet's light tone, but for the gold of
   the best true numbers: the net result (the curve's end, the block's), the biggest win, the strongest month and the
   winning months (the owner, 2026-10-09: the eye goes to the best numbers first, then to Subscribe). */
.sp-results__chart {
  margin: 0;
}

.sp-results__chart figcaption {
  margin-top: 14px;
  color: var(--on-dark-muted);
  font-size: 0.9375rem;
  line-height: 1.45;
}

/* The chart: an SVG stretched over the plot (strokes that keep their width), the labels as HTML round it. */
/* Its right padding holds the curve's end value (.sp-chart__end). */
.sp-chart {
  position: relative;
  padding: 30px 6rem 34px 3.9rem;
  border: 1px solid rgb(var(--tint-hi, var(--on-dark-rgb)) / 0.2);
  border-radius: var(--radius);
  background: rgb(var(--night-rgb) / 0.35);
}

.sp-chart__plot {
  position: relative;
  height: clamp(200px, 40vw, 360px);
}

.sp-chart__plot svg {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.sp-chart__grid,
.sp-chart__line {
  fill: none;
  vector-effect: non-scaling-stroke;
}

.sp-chart__grid {
  stroke: rgb(var(--on-dark-rgb) / 0.09);
  stroke-width: 1;
}

.sp-chart__grid--zero {
  stroke: rgb(var(--on-dark-rgb) / 0.42);
}

.sp-chart__line {
  stroke: rgb(var(--tint-hi, var(--on-dark-rgb)));
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.sp-chart__y,
.sp-chart__x,
.sp-chart__unit {
  position: absolute;
  color: var(--on-dark-muted);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1;
  white-space: nowrap;
}

.sp-chart__y {
  right: calc(100% + 10px);
  transform: translateY(-50%);
}

.sp-chart__x {
  top: calc(100% + 14px);
  transform: translateX(-50%);
}

.sp-chart__x::before {
  content: "";
  position: absolute;
  top: -14px;
  left: 50%;
  height: 7px;
  border-left: 1px solid rgb(var(--on-dark-rgb) / 0.4);
}

.sp-chart__x--minor::before {
  height: 4px;
}

.sp-chart__unit {
  top: 10px;
  left: 16px;
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* The curve's end, a gold dot, and its value in gold beside it, right of the plot, where the curve never runs. */
.sp-chart__dot {
  position: absolute;
  left: 100%;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px rgb(var(--night-rgb) / 0.8);
  transform: translate(-50%, -50%);
}

.sp-chart__end {
  position: absolute;
  left: calc(100% + 12px);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  white-space: nowrap;
  transform: translateY(-50%);
}

/* The results coming into view (strategy-hero.js), once: until the chart is a quarter in the window the curve is
   clipped away, its end value and dot are out and the four cards and the five biggest trades wait 8 px low; then the
   curve draws itself from the left, the end comes in as it arrives and the cards and trades rise in. With motion calm
   they only fade. Never on paper. */
.sp-results-wait--on .sp-chart__line {
  clip-path: inset(-6px 100% -6px -6px);
}

.sp-results-wait :is(.sp-chart__end, .sp-chart__dot),
.sp-results-wait--calm .sp-chart__line,
.sp-results-wait :is(.sp-cards:not(.sp-cards--more) > .sp-card, .sp-top > li) {
  opacity: 0;
}

.sp-results-wait--on :is(.sp-cards:not(.sp-cards--more) > .sp-card, .sp-top > li) {
  transform: translateY(8px);
}

@media print {
  .sp-results-wait .sp-chart__line {
    clip-path: none;
  }

  .sp-results-wait :is(.sp-chart__end, .sp-chart__dot, .sp-cards:not(.sp-cards--more) > .sp-card, .sp-top > li, .sp-chart__line) {
    opacity: 1;
    transform: none;
  }

  .sp-results-wait .sp-chart__end {
    transform: translateY(-50%);
  }

  .sp-results-wait .sp-chart__dot {
    transform: translate(-50%, -50%);
  }
}

/* Phones: a taller chart (the box about 6:5 on a 390 px phone; it was about 5:4), the end value a little smaller. */
@media (max-width: 600px) {
  .sp-chart {
    padding: 28px 4.75rem 32px 3.1rem;
  }

  .sp-chart__plot {
    height: clamp(220px, 62vw, 320px);
  }

  .sp-chart__end {
    left: calc(100% + 9px);
    font-size: 0.75rem;
  }

  .sp-chart__y,
  .sp-chart__x {
    font-size: 0.6875rem;
  }

  .sp-chart__y {
    right: calc(100% + 7px);
  }

  .sp-chart__unit {
    left: 10px;
  }
}

/* The numbers (in the closed "All the numbers"): the net result large, in gold, then the rest one to a row. */
.sp-numbers {
  padding: 24px 24px 10px;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
  background: rgb(var(--night-rgb) / 0.35);
}

.sp-numbers__net {
  margin: 0 0 18px;
}

.sp-numbers__label,
.sp-numbers__value,
.sp-numbers__span {
  display: block;
}

.sp-numbers__label {
  color: rgb(var(--tint-hi, var(--on-dark-rgb)));
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  line-height: 1.5;
  text-transform: uppercase;
}

.sp-numbers__value {
  margin: 8px 0 6px;
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: clamp(2.125rem, 5vw, 2.625rem);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}

.sp-numbers__span {
  color: var(--on-dark-muted);
  font-size: 0.875rem;
  line-height: 1.4;
}

.sp-numbers__list {
  margin: 0;
}

.sp-numbers__list div {
  display: flex;
  gap: 16px;
  align-items: baseline;
  justify-content: space-between;
  padding: 12px 0;
  border-top: 1px solid var(--line-dark);
}

.sp-numbers__list dt {
  color: var(--on-dark-muted);
  font-size: 0.9375rem;
}

.sp-numbers__list dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.sp-numbers__when {
  display: block;
  margin-top: 3px;
  color: var(--on-dark-muted);
  font-family: var(--font-body);
  font-size: 0.75rem;
}

.sp-head .muted a {
  color: rgb(var(--tint-hi, var(--on-dark-rgb)));
  white-space: nowrap;
}

/* Trade by trade (tradeByTrade in templates/results.mjs): one line, eight cards with one big number each (three of
   them in gold), the five biggest trades, the plain figures one click down (the block of numbers beside a strip of
   every month), and the closing line with the gold Subscribe. Static, no script; the months' gains in the planet's
   light tone, losses in the muted cream. */
.sp-sell {
  margin-top: clamp(48px, 7vw, 80px);
}

.sp-sell__title {
  max-width: 640px;
  margin: 0 0 clamp(20px, 3vw, 28px);
  font-weight: 400;
}

.sp-cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (max-width: 999px) {
  .sp-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.sp-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 20px 20px 18px;
  border: 1px solid rgb(var(--tint-hi, var(--on-dark-rgb)) / 0.2);
  border-radius: var(--radius);
  background: linear-gradient(180deg, rgb(var(--tint, 255 255 255) / 0.1), rgb(var(--tint, 255 255 255) / 0.02));
}

.sp-card__label {
  color: rgb(var(--tint-hi, var(--on-dark-rgb)));
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  line-height: 1.45;
  text-transform: uppercase;
}

.sp-card__value {
  margin: 10px 0 6px;
  color: var(--on-dark);
  font-family: var(--font-mono);
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
  white-space: nowrap;
}

/* The three cards the gold marks: the biggest win, the strongest month, the winning months. */
.sp-card--gold .sp-card__value {
  color: var(--accent);
}

.sp-card__note {
  margin-top: auto;
  color: var(--on-dark-muted);
  font-size: 0.8125rem;
  line-height: 1.4;
}

@media (max-width: 420px) {
  .sp-card {
    padding: 16px 14px 14px;
  }

  .sp-card__label {
    font-size: 0.625rem;
    letter-spacing: 0.1em;
  }

  .sp-card__value {
    font-size: 1.3rem;
  }
}

.sp-sell__part {
  min-width: 0;
}

.sp-sell__top {
  max-width: 720px;
  margin-top: clamp(36px, 5vw, 56px);
}

/* "All the numbers, month by month": a native <details>, closed, its summary as the FAQ's questions are (a row with
   the plus). Open, the block of numbers beside the strip of every month on wide screens, under each other on phones.
   It prints open (below). */
.sp-more {
  margin-top: clamp(36px, 5vw, 56px);
  border-top: 1px solid var(--line-dark);
  border-bottom: 1px solid var(--line-dark);
}

.sp-more summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 64px;
  padding: 16px 0;
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.4;
  list-style: none;
  cursor: pointer;
}

.sp-more summary::-webkit-details-marker {
  display: none;
}

.sp-more summary:hover span {
  text-decoration: underline;
  text-underline-offset: 4px;
}

.sp-more__icon {
  flex: none;
  color: var(--on-dark-muted);
  transition: transform 0.2s ease;
}

.sp-more[open] .sp-more__icon {
  transform: rotate(45deg);
}

.sp-more__body {
  display: grid;
  gap: 36px;
  padding: 8px 0 32px;
}

/* The four cards that wait here (highlights() in templates/results.mjs) span the body above the numbers. */
.sp-more__body > .sp-cards {
  grid-column: 1 / -1;
}

/* Its bottom line is the closing line's top one. */
.sp-more + .sp-sell__close {
  border-top: 0;
}

@media (min-width: 1000px) {
  .sp-more__body {
    grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
    gap: 48px;
    align-items: start;
  }
}

/* On paper nothing is one click down: the details print open (strategy.js opens them too, for a browser without
   ::details-content). */
@media print {
  .sp-more::details-content {
    content-visibility: visible;
    display: block;
  }

  .sp-more__icon {
    display: none;
  }
}

.sp-sell__sub {
  margin: 0 0 16px;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.14em;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--on-dark-muted);
}

/* The five biggest trades: rank, date and side, money. */
.sp-top {
  margin: 0;
  padding: 0;
  list-style: none;
}

.sp-top li {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr) auto;
  gap: 12px;
  align-items: baseline;
  padding: 13px 0;
  border-top: 1px solid var(--line-dark);
}

.sp-top li:last-child {
  border-bottom: 1px solid var(--line-dark);
}

.sp-top__rank {
  color: rgb(var(--tint-hi, var(--on-dark-rgb)));
  font-family: var(--font-mono);
  font-size: 0.875rem;
}

.sp-top__date {
  font-size: 1rem;
}

.sp-top__side {
  margin-left: 0.3em;
  color: var(--on-dark-muted);
  font-size: 0.8125rem;
}

.sp-top__usd {
  font-family: var(--font-mono);
  font-size: 1.0625rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Every month: one column a month, the zero line at --zero from the top, gains up and losses down on one scale. */
.sp-months {
  padding: 18px 16px 30px;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
  background: rgb(var(--night-rgb) / 0.35);
}

.sp-months__row {
  position: relative;
  display: flex;
  gap: 2px;
  height: clamp(120px, 16vw, 168px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.sp-months__row::before {
  content: "";
  position: absolute;
  top: var(--zero);
  left: 0;
  right: 0;
  border-top: 1px solid rgb(var(--on-dark-rgb) / 0.42);
}

.sp-months__m {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
}

.sp-months__m:hover .sp-months__bar {
  filter: brightness(1.35);
}

.sp-months__bar {
  position: absolute;
  left: 0;
  right: 0;
  min-height: 1px;
  border-radius: 1px;
}

.sp-months__bar--up,
.sp-months__swatch--up {
  background: rgb(var(--tint-hi, var(--on-dark-rgb)));
}

.sp-months__bar--down,
.sp-months__swatch--down {
  background: rgb(var(--on-dark-rgb) / 0.38);
}

.sp-months__year {
  position: absolute;
  top: calc(100% + 10px);
  left: 0;
  color: var(--on-dark-muted);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  line-height: 1;
  white-space: nowrap;
}

.sp-months__year::before {
  content: "";
  position: absolute;
  top: -8px;
  left: 0;
  height: 5px;
  border-left: 1px solid rgb(var(--on-dark-rgb) / 0.4);
}

.sp-months__key {
  margin: 12px 0 0;
  color: var(--on-dark-muted);
  font-size: 0.8125rem;
}

.sp-months__swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  margin: 0 6px 0 0;
  border-radius: 2px;
  vertical-align: -1px;
}

.sp-months__swatch--down {
  margin-left: 10px;
}

/* The closing line: what the buyer gets, and the way to buy. */
.sp-sell__close {
  display: flex;
  flex-wrap: wrap;
  gap: 20px 32px;
  align-items: center;
  justify-content: space-between;
  margin-top: clamp(40px, 6vw, 64px);
  padding-top: clamp(28px, 4vw, 36px);
  border-top: 1px solid var(--line-dark);
}

.sp-sell__close p {
  max-width: 640px;
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.45;
}

/* Steps */
.sp-steps {
  display: grid;
  gap: 32px;
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 760px) {
  .sp-steps {
    grid-template-columns: repeat(var(--n, 3), minmax(0, 1fr));
  }
}

.sp-step {
  position: relative;
  padding-left: 76px;
}

@media (min-width: 760px) {
  .sp-step {
    padding-left: 0;
    padding-top: 76px;
  }
}

.sp-step__num {
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  /* A ring in the planet's light tone and a faint glow of its colour. */
  box-shadow: inset 0 0 0 1px rgb(var(--tint-hi, var(--on-dark-rgb)) / 0.55), 0 0 22px -6px rgb(var(--tint, 255 255 255) / 0.6);
  color: rgb(var(--tint-hi, var(--on-dark-rgb)));
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 400;
}

/* thin line that joins the numbers */
.sp-step:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 27.5px;
  top: 68px;
  bottom: -24px;
  width: 1px;
  background: var(--line-dark);
}

@media (min-width: 760px) {
  .sp-step:not(:last-child)::after {
    left: 72px;
    right: 16px;
    top: 28px;
    bottom: auto;
    width: auto;
    height: 1px;
  }
}

.sp-step__title {
  margin: 0 0 6px;
  padding-top: 14px;
  font-size: 1.1025rem;
  font-weight: 400;
}

@media (min-width: 760px) {
  .sp-step__title {
    padding-top: 0;
  }
}

.sp-step p {
  margin: 0;
  color: var(--on-dark-muted);
  font-size: 1.0625rem;
}

/* Reviews (only rendered when there are real ones) */
.sp-reviews {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}

.sp-review {
  margin: 0;
  padding: 26px 24px;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
  background: rgb(var(--on-dark-rgb) / 0.025);
}

.sp-review blockquote {
  margin: 0 0 16px;
  font-size: 1.125rem;
  line-height: 1.55;
}

.sp-review blockquote p {
  margin: 0;
}

.sp-review figcaption {
  display: flex;
  flex-direction: column;
  font-size: 0.9375rem;
}

.sp-review__name {
  font-weight: 600;
}

.sp-review__about {
  color: var(--on-dark-muted);
}

/* FAQ */
.sp-faq {
  border-top: 1px solid var(--line-dark);
}

.sp-faq__item {
  border-bottom: 1px solid var(--line-dark);
}

.sp-faq__item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 64px;
  padding: 16px 0;
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.4;
  list-style: none;
  cursor: pointer;
}

.sp-faq__item summary::-webkit-details-marker {
  display: none;
}

.sp-faq__item summary:hover span {
  text-decoration: underline;
  text-underline-offset: 4px;
}

.sp-faq__icon {
  flex: none;
  color: var(--on-dark-muted);
  transition: transform 0.2s ease;
}

.sp-faq__item[open] .sp-faq__icon {
  transform: rotate(45deg);
}

.sp-faq__answer {
  padding: 0 40px 22px 0;
  color: var(--on-dark-muted);
}

.sp-faq__answer a {
  color: var(--on-dark);
}

.sp-faq__answer p:last-child {
  margin: 0;
}

.sp-faq__more {
  margin: 28px 0 0;
}

.sp-faq__more a {
  color: var(--on-dark);
}

/* ------------------------------------------------------------------ final call to action */

.sp-cta {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(64px, 8vw, 104px) 0;
  /* The planet's glow behind the round planet (not behind the price: gold on Saturn's pale gold glow fell under
     7:1) and its nebula pair, on the page's space tone. */
  background:
    radial-gradient(34% 70% at 30% 50%, rgb(var(--tint, 255 255 255) / 0.2), transparent 70%),
    radial-gradient(50% 90% at 85% 100%, rgb(var(--nebula-2) / 0.22), transparent 70%),
    radial-gradient(45% 80% at 12% 0%, rgb(var(--nebula-1) / 0.16), transparent 70%),
    var(--space);
  border-top: 1px solid var(--line-dark);
}

/* The photo's stars, tinted like the hero's and screened onto the blue (its black never covers the blue). */
.sp-cta::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-color: #000; /* the wash multiplies to black, not grey, where the photo is not painted */
  background-image: var(--star-wash), url("../planets/starfield.webp");
  background-size: 100% 100%, 100% 100%, 100% 100%, 1400px auto;
  background-repeat: no-repeat, no-repeat, no-repeat, repeat;
  background-position: center;
  background-blend-mode: multiply, multiply, multiply, normal;
  mix-blend-mode: screen;
  opacity: 0.7;
}

.sp-cta__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(16px, 5vw, 64px);
}

/* Round planet, lit from the left with a dark night side on the right. --k makes the ringed photo (smaller disc) match. */
.sp-cta__planet {
  --size: clamp(170px, 22vw, 280px);
  position: relative;
  flex: none;
  width: var(--size);
  height: var(--size);
  margin: -32px 0;
}

.sp-cta__planet img {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--size) * var(--k, 1));
  height: calc(var(--size) * var(--k, 1));
  max-width: none;
  transform: translate(-50%, -50%);
  filter: brightness(0.86) var(--planet-filter) var(--planet-tone,) drop-shadow(0 0 50px rgb(var(--tint, 255 255 255) / 0.42));
}

.sp-cta__planet::after {
  content: "";
  position: absolute;
  inset: 20%;
  border-radius: 50%;
  background: linear-gradient(105deg, rgb(var(--night-rgb) / 0) 38%, rgb(var(--night-rgb) / 0.55) 72%, rgb(var(--night-rgb) / 0.9) 100%);
  pointer-events: none;
}

.sp-cta__text {
  min-width: 0;
}

.sp-cta__text .eyebrow {
  margin-bottom: 0.25rem;
}

.sp-cta__title {
  margin: 0 0 0.2em;
  font-size: clamp(1.68rem, 1.176rem + 2.016vw, 2.73rem);
  font-weight: 400;
}

.sp-cta__price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin: 0 0 24px;
}

.sp-cta__price-amount {
  font-family: var(--font-display);
  font-size: 1.26rem;
  font-weight: 400;
}

.sp-cta__price-note {
  color: var(--on-dark-muted);
  font-size: 0.9375rem;
}

.sp-cta__btn {
  min-height: 56px;
  min-width: 220px;
  font-size: 1.0625rem;
}

/* A shade brighter than muted text, like the lines under the buy box's button. */
.sp-cta__note {
  margin: 12px 0 0;
  color: rgb(var(--on-dark-rgb) / 0.78);
  font-size: 0.9375rem;
}

@media (max-width: 700px) {
  /* Stacked, the planet sits above the text: its glow goes with it, around its centre (64px padding, -16px margin
     and half of the 170px planet), and stops short of the eyebrow. */
  .sp-cta {
    background:
      radial-gradient(circle 160px at 50% calc(64px - 16px + 85px), rgb(var(--tint, 255 255 255) / 0.2), transparent 70%),
      radial-gradient(50% 90% at 85% 100%, rgb(var(--nebula-2) / 0.22), transparent 70%),
      radial-gradient(45% 80% at 12% 0%, rgb(var(--nebula-1) / 0.16), transparent 70%),
      var(--space);
  }

  .sp-cta__inner {
    flex-direction: column;
    text-align: center;
  }

  .sp-cta__planet {
    margin: -16px 0 -20px;
  }

  .sp-cta__price {
    justify-content: center;
  }

  .sp-cta__text {
    width: 100%;
  }

  .sp-cta__btn {
    width: 100%;
    max-width: 420px;
  }
}

/* ------------------------------------------------------------------ sticky buy bar */

/* On every screen size while the buy box's Subscribe is out of view (strategy.js): the planet, the name, the price and
   Subscribe, which leads back to the buy box. A glass bar, its content as wide as the page's. */
.sp-buybar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  padding: 10px max(var(--gutter), env(safe-area-inset-right, 0px)) calc(10px + env(safe-area-inset-bottom, 0px)) max(var(--gutter), env(safe-area-inset-left, 0px));
  background: rgb(var(--space-2-rgb) / 0.94);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
  /* The top edge catches the planet's light: a thin line and a glow upward. */
  box-shadow:
    inset 0 1px 0 rgb(var(--tint-hi, var(--on-dark-rgb)) / 0.4),
    0 -1px 26px -6px rgb(var(--tint, 255 255 255) / 0.4),
    0 -12px 32px rgb(var(--night-rgb) / 0.45);
  transform: translateY(110%);
  visibility: hidden;
  transition: transform 0.25s ease, visibility 0s linear 0.25s;
}

.sp-buybar.is-visible {
  transform: none;
  visibility: visible;
  transition: transform 0.25s ease;
}

/* Motion calm (html[data-motion], base.css): the bar is there or not, with no slide. */
:where(html[data-motion="calm"]) .sp-buybar,
:where(html[data-motion="calm"]) .sp-buybar.is-visible {
  transition: none;
}

.sp-buybar__inner {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: calc(var(--container) - 2 * var(--gutter));
  margin: 0 auto;
}

.sp-buybar__planet {
  flex: none;
  width: 52px;
  height: 52px;
  /* A photo scaled up in its box (--k above 1: Saturn, whose rings make its disc smaller) reaches past the box: the
     right margin gives some of that back, so the rings end short of the name and the price (by about 3px). */
  margin: -6px calc(19px * (var(--k, 1) - 1) - 8px) -6px -10px;
  filter: brightness(0.9) var(--planet-filter) var(--planet-tone,);
  transform: scale(var(--k, 1));
}

.sp-buybar__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  margin: 0;
  line-height: 1.25;
}

.sp-buybar__name {
  overflow: hidden;
  font-family: var(--font-display);
  font-size: 0.8925rem;
  font-weight: 400;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.sp-buybar__price {
  color: var(--on-dark-muted);
  font-size: 0.875rem;
}

.sp-buybar__price-amount {
  font-family: var(--font-display);
  font-size: 0.9rem;
}

/* "per month" stays in one piece. */
.sp-buybar__price-note {
  white-space: nowrap;
}

/* "Delivered straight after payment · Secure payment via Stripe": only where there is room, see below. */
.sp-buybar__trust {
  display: none;
}

.sp-buybar__btn {
  min-height: 44px;
  padding: 0 1.4em;
  white-space: nowrap;
}

/* Narrow phones: the button's sides give the price and its note a little more room, down to a 360px window, next to
   Saturn too. */
@media (max-width: 380px) {
  .sp-buybar__btn {
    padding: 0 0.9em;
  }
}

body.sp-has-buybar {
  padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
}

/* While the bar shows, the browser scrolls a focused link or question to above it, not under it (Tab in the
   questions would otherwise land behind the bar). */
html:has(> body.sp-has-buybar) {
  scroll-padding-bottom: calc(88px + env(safe-area-inset-bottom, 0px));
}

/* Forced colours drop the box shadows that edge the bar and outline the inactive buy button (base.css gives every
   button a border there), and the fills that draw the tick: the bar gets a top border, the button before the tick
   reads as inactive, and the ticked box is filled in system colours. */
@media (forced-colors: active) {
  .sp-buybar {
    border-top: 1px solid CanvasText;
  }

  .sp-buy__check:checked {
    background: CanvasText;
  }

  .sp-buy__check::after {
    background: Canvas;
  }

  .sp-buy__btn[aria-disabled="true"],
  .sp-buy:has(.sp-buy__check:not(:checked)) .sp-buy__btn[data-buy] {
    border-color: GrayText;
    color: GrayText;
  }
}

/* Wide screens: a little more air, and the two reassurances right before the button. */
@media (min-width: 861px) {
  .sp-buybar {
    padding-top: 12px;
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  }

  .sp-buybar__text {
    flex: none;
  }

  .sp-buybar__trust {
    display: flex;
    flex: 1;
    justify-content: flex-end;
    align-items: center;
    gap: 8px 18px;
    margin: 0 8px 0 0;
    color: rgb(var(--on-dark-rgb) / 0.78);
    font-size: 0.875rem;
  }

  .sp-buybar__trust span {
    display: inline-flex;
    align-items: center;
    gap: 7px;
  }

  .sp-buybar__trust svg {
    color: rgb(var(--on-dark-rgb) / 0.6);
  }

  .sp-buybar__btn {
    min-height: 48px;
    min-width: 168px;
  }
}

/* ------------------------------------------------------------------ terms of sale */

.terms-head {
  padding: calc(var(--header-h) + clamp(40px, 7vw, 88px)) 0 clamp(40px, 6vw, 72px);
  /* The photo's stars screened onto the blue, fading out downwards. */
  background:
    linear-gradient(180deg, rgb(var(--space-rgb) / 0.5), var(--space)),
    url("../planets/starfield.webp") center / 1400px auto repeat,
    var(--space);
  background-blend-mode: normal, screen;
}

.terms-head h1 {
  margin: 0 0 0.3em;
  font-weight: 400;
}

.terms-lead {
  max-width: 60ch;
  margin: 0;
  color: var(--on-dark-muted);
  font-size: 1.125rem;
}

.terms {
  padding: clamp(48px, 7vw, 88px) 0 clamp(64px, 9vw, 112px);
  background: var(--space);
  color: var(--on-dark);
  border-top: 1px solid var(--line-dark);
}

.terms-layout {
  display: grid;
  gap: 32px 64px;
  align-items: start;
}

@media (min-width: 1000px) {
  .terms-layout {
    grid-template-columns: minmax(0, 70ch) minmax(220px, 280px);
  }

  .terms-toc {
    position: sticky;
    top: 24px;
    grid-column: 2;
    grid-row: 1 / span 2;
  }

  .terms-draft,
  .terms-body {
    grid-column: 1;
  }
}

.terms-body {
  min-width: 0;
  max-width: 70ch;
  color: rgb(var(--on-dark-rgb) / 0.88);
}

.terms-body h2 {
  margin: 2.2em 0 0.5em;
  color: var(--on-dark);
  font-size: clamp(1.134rem, 1.008rem + 0.504vw, 1.365rem);
  font-weight: 400;
  scroll-margin-top: 24px;
}

.terms-body section:first-of-type h2 {
  margin-top: 0;
}

.terms-body h3 {
  margin: 1.6em 0 0.4em;
  color: var(--on-dark);
  font-size: 0.945rem;
  font-weight: 400;
}

.terms-body strong {
  color: var(--on-dark);
  font-weight: 600;
}

.terms-body p,
.terms-body li {
  max-width: 70ch;
}

.terms-body ul,
.terms-body ol {
  margin: 0 0 1em;
  padding-left: 1.3em;
}

.terms-body li {
  margin-bottom: 0.4em;
}

.terms-body a {
  color: var(--on-dark);
  text-underline-offset: 3px;
}

.terms-draft {
  max-width: 70ch;
  margin: 0;
  padding: 16px 20px;
  border: 1px solid var(--line-dark);
  border-left: 2px solid var(--on-dark-muted);
  border-radius: var(--radius-sm);
  background: var(--space-2);
  color: var(--on-dark);
  font-weight: 500;
}

.terms-draft p {
  margin: 0;
}

.terms-toc {
  padding: 20px 24px;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
  background: var(--space-2);
}

.terms-toc h2 {
  margin: 0 0 10px;
  color: var(--on-dark-muted);
  font-family: var(--font-display);
  font-size: 0.6825rem;
  font-weight: 400;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.terms-toc ol {
  margin: 0;
  padding: 0;
  list-style: none;
  columns: 2 200px;
  column-gap: 32px;
}

@media (min-width: 1000px) {
  .terms-toc ol {
    columns: auto;
  }
}

.terms-toc a {
  display: inline-block;
  padding: 3px 0;
  color: var(--on-dark);
  text-decoration: none;
}

.terms-toc a:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.terms-toc li {
  margin-bottom: 4px;
  break-inside: avoid;
}

.terms-box {
  margin: 0 0 1em;
  padding: 16px 20px;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius-sm);
  background: var(--space-2);
}

.terms-box p:last-child {
  margin: 0;
}

.terms-body .terms-contact {
  margin: 0 0 1em;
  padding: 16px 20px;
  list-style: none;
}

.terms-contact li {
  margin-bottom: 2px;
}

.terms-body code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  color: var(--on-dark);
}

/* ------------------------------------------------------------------ withdraw from contract (/withdraw/) */

/* The form on the terms' panel colour, its fields on the page's space tone, every label above its field. The send
   button is cream, not the accent: gold means "pay here". The browser draws the date picker and the list dark. */
.withdraw-form {
  display: grid;
  gap: 18px;
  max-width: 34rem;
  margin: 0 0 1.4em;
  padding: 22px 24px 24px;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
  background: var(--space-2);
  color-scheme: dark;
}

.withdraw-form__field {
  display: grid;
  gap: 6px;
}

.withdraw-form label {
  color: var(--on-dark);
  font-weight: 600;
}

.withdraw-form input,
.withdraw-form select,
.withdraw-form textarea {
  width: 100%;
  min-height: 48px;
  margin: 0;
  padding: 10px 14px;
  border: 1px solid rgb(var(--on-dark-rgb) / 0.32);
  border-radius: var(--radius-sm);
  background: var(--space);
  color: var(--on-dark);
  font: inherit;
}

.withdraw-form textarea {
  min-height: 112px;
  resize: vertical;
}

.withdraw-form input:focus-visible,
.withdraw-form select:focus-visible,
.withdraw-form textarea:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-color: var(--on-dark);
}

.withdraw-form__note,
.terms-body .withdraw-form__note {
  margin: 0;
  color: var(--on-dark-muted);
  font-size: 0.875rem;
}

/* The honeypot: no person sees or reaches it. */
.withdraw-form__trap {
  display: none;
}

.withdraw-form__send {
  justify-self: start;
  min-width: 240px;
  background: var(--on-dark);
  color: var(--space);
}

.withdraw-form__send:hover {
  background: rgb(var(--on-dark-rgb) / 0.86);
}

.withdraw-form__send:active {
  transform: translateY(1px);
}

@media (max-width: 480px) {
  .withdraw-form {
    padding: 18px 16px 20px;
  }

  .withdraw-form__send {
    justify-self: stretch;
    min-width: 0;
  }
}

.withdraw-received {
  color: var(--on-dark);
  font-size: 1.0625rem;
}

@media (forced-colors: active) {
  .withdraw-form input,
  .withdraw-form select,
  .withdraw-form textarea {
    border-color: CanvasText;
  }
}

/* The support button (base.css) over the buy bar while the bar is up: lifted by the bar's height, so the two never
   overlap on a phone. */
body.sp-has-buybar .support-btn {
  bottom: calc(76px + env(safe-area-inset-bottom, 0px));
}
