/* velo's landing page.
 *
 * The tokens are the player's own factory palette — the same seven colours
 * `themes/velo.toml` ships — so the page wears the product it describes.
 * Two deviations, deliberate: `--dim` is lifted above the palette's `dim`
 * (#767676 on #141c28 is 3.3:1 and fails AA for body text), and `--soft` is
 * the reading colour for prose set over the video and the fog, where the
 * backdrop is never one flat value.
 *
 * The hero is the room the terminal sits in — a looping hearth video — with
 * the player drawn as glass over it: `transparent_background = true` is what
 * the app does, so the room behind the page is what would be behind the
 * terminal. Under the hero the video dissolves into a fog drawn by fog.js
 * (three.js, vendored), and the rest of the page is read through it.
 *
 * No build step, no framework: everything the page loads is in this folder,
 * system fonts only.
 */

:root {
  --bg: #141c28;
  --line: #252939;
  --text: #f4f0e2;
  --soft: #c9cdd3;
  --dim: #9aa3ae;
  --accent: #f4baa3;
  --accent-ink: #141c28;
  --cool: #a6c8e2;
  --hair: rgba(244, 240, 226, 0.16);
  --glass: rgba(9, 11, 16, 0.42);
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

html {
  background: #07090d;
  color: var(--text);
  font-family: var(--sans);
  line-height: 1.6;
  scroll-behavior: smooth;
  scroll-padding-top: 2rem;
}

body { margin: 0; position: relative; overflow-x: hidden; }

a { color: var(--cool); }

a:focus-visible,
button:focus-visible,
input:focus-visible,
.app:focus-visible,
label:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

[hidden] { display: none !important; }

/* ---- the fog the page is read through ---- */

/* The base does not depend on WebGL: soft clouds of warm brown and slate over
   near-black. fog.js paints its canvas on top of this; a browser that cannot
   still gets fog, never a flat plate. */
.fog {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(60% 50% at 50% 0%, rgba(201, 138, 75, 0.34) 0%, rgba(201, 138, 75, 0) 70%),
    radial-gradient(50% 45% at 22% 62%, rgba(74, 53, 36, 0.6) 0%, rgba(74, 53, 36, 0) 72%),
    radial-gradient(45% 40% at 82% 78%, rgba(43, 58, 77, 0.5) 0%, rgba(43, 58, 77, 0) 70%),
    #07090d;
}

.fog canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.wrap {
  position: relative;
  z-index: 1;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 2rem;
}

/* ---- header ---- */

.top {
  position: absolute;
  inset: 0 0 auto;
  z-index: 2;
}

.top-inner {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding-top: 1.6rem;
  padding-bottom: 1.6rem;
}

.top-links {
  display: flex;
  gap: 1.6rem;
}

.top-links a {
  font-size: 0.85rem;
  text-decoration: none;
  color: var(--text);
}

.top-links a:hover { color: var(--accent); }

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

.hero {
  position: relative;
  z-index: 1;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding: 6rem 0 18vh;
}

/* The room. It is opaque down to the last third, then lets go: the mask takes
   the video and its scrims out together, and what is left is the fog. */
.hero-media {
  position: absolute;
  inset: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 58%, rgba(0, 0, 0, 0.55) 78%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0%, #000 58%, rgba(0, 0, 0, 0.55) 78%, transparent 100%);
}

.hero-media video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 40%;
}

/* Two scrims, both for reading: the left one puts the pitch on a dark wall,
   the top one keeps the brand legible over the bright plaster. */
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(7, 9, 13, 0.86) 0%, rgba(7, 9, 13, 0.6) 34%, rgba(7, 9, 13, 0) 62%),
    linear-gradient(180deg, rgba(7, 9, 13, 0.6) 0%, rgba(7, 9, 13, 0) 22%);
}

.hero-grid {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1.08fr;
  gap: 3rem;
  align-items: center;
}

.hero-grid > * { min-width: 0; }

/* The name, the way the interface writes it in its own corner. */
.lockup {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin: 0 0 1.6rem;
  font-family: var(--mono);
  font-size: 1.9rem;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--accent);
}

.lockup img { display: block; width: 60px; height: 60px; }

h1 {
  font-size: clamp(2.1rem, 3.6vw, 3.3rem);
  line-height: 1.08;
  letter-spacing: -0.025em;
  font-weight: 650;
  margin: 0 0 1.2rem;
  text-wrap: balance;
}

.lede {
  color: var(--soft);
  font-size: 1.08rem;
  max-width: 44ch;
  margin: 0 0 2.2rem;
}

/* ---- install ---- */

.picker-field {
  border: 0;
  padding: 0;
  margin: 0 0 0.7rem;
}

.picker-field legend {
  font-size: 0.82rem;
  color: var(--soft);
  padding: 0;
  margin-bottom: 0.5rem;
}

.picker {
  display: inline-flex;
  flex-wrap: wrap;
  border: 1px solid var(--hair);
  border-radius: 8px;
  overflow: hidden;
  background: var(--glass);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

.picker label {
  position: relative;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--soft);
  padding: 0.42rem 0.6rem;
  cursor: pointer;
  border-right: 1px solid var(--hair);
  white-space: nowrap;
}

/* Controls, not prose: a drag across them should not paint a selection. */
.picker,
.app,
.copy,
.cta {
  -webkit-user-select: none;
  user-select: none;
}

.picker label:last-child { border-right: 0; }
.picker label:hover { color: var(--text); }

.picker label:has(input:checked) {
  background: var(--accent);
  color: var(--accent-ink);
}

.picker input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.cmd {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  background: var(--glass);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: 0.75rem 0.8rem 0.75rem 1rem;
  font-family: var(--mono);
  font-size: 0.78rem;
}

/* On a wide screen the command box stops where the paragraph above it does. */
@media (min-width: 981px) {
  .cmd { width: 89%; }
}

.prompt { color: var(--accent); flex: none; line-height: 1.5; }

/* The variants of a swap share one grid cell: the cell is as tall as the
   tallest of them, and only the chosen one is visible. */
.swap { display: grid; }
.swap > * { grid-area: 1 / 1; visibility: hidden; }
.swap > .on { visibility: visible; }
.cmd .swap { flex: 1; min-width: 0; }

/* The whole command is always on screen: it wraps instead of scrolling, so
   what gets copied is what was read. */
.cmd code {
  color: var(--text);
  flex: 1;
  min-width: 0;
  /* Wrapped the way a terminal wraps a long line: at the edge, not at a word. */
  word-break: break-all;
  line-height: 1.5;
}

.copy {
  font-family: var(--mono);
  font-size: 0.72rem;
  background: transparent;
  border: 1px solid var(--hair);
  color: var(--soft);
  border-radius: 5px;
  padding: 0.28rem 0.6rem;
  cursor: pointer;
  flex: none;
}

.copy:hover { color: var(--text); border-color: var(--soft); }

.hint {
  font-size: 0.8rem;
  color: var(--soft);
  margin: 0.8rem 0 0;
  max-width: 50ch;
}

.cta {
  display: inline-block;
  background: var(--accent);
  color: var(--accent-ink);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
  padding: 0.62rem 1.1rem;
  border-radius: 6px;
}

.cta:hover { filter: brightness(1.06); }

.more-install {
  margin: 0.9rem 0 0;
  font-size: 0.8rem;
}

.more-install a { color: var(--soft); }
.more-install a:hover { color: var(--text); }

/* ---- the interface, drawn as it draws itself ---- */

.app {
  position: relative;
  padding: 1.1rem 1.25rem 0.9rem;
  border: 1px solid var(--hair);
  border-radius: 12px;
  /* Glass: a thin dark tint for contrast, and the room behind it out of focus. */
  background: var(--glass);
  -webkit-backdrop-filter: blur(22px) saturate(1.35);
  backdrop-filter: blur(22px) saturate(1.35);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.1),
    0 30px 80px -20px rgba(0, 0, 0, 0.7);
  font-family: var(--mono);
  font-size: 0.74rem;
  line-height: 1.55;
  color: var(--text);
}

.app button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  text-align: left;
}

.app .dim { color: var(--dim); }
.app button.dim:hover { color: var(--text); }

.app-nav {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.5rem;
}

.app-tabs { display: inline-flex; gap: 1.1rem; }
.app-tabs button { color: var(--dim); }
.app-tabs button:hover { color: var(--text); }
.app-tabs button.on { color: var(--text); font-weight: 600; }

.app-mark {
  color: var(--accent);
  letter-spacing: 0.32em;
}

.app-title {
  color: var(--accent);
  font-weight: 600;
  margin-bottom: 1.1rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-clock {
  display: flex;
  justify-content: space-between;
  margin-bottom: 0.55rem;
}

.app-state { color: var(--accent); margin-left: 1.5ch; }
.app-of { color: var(--dim); }

.app-spectrum {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 68px;
  margin: 0 0 0.5rem;
  /* Before the first play the bars are a still picture of a spectrum, dimmed. */
  opacity: 0.45;
}

.app.is-live .app-spectrum { opacity: 1; }

.app-spectrum i {
  flex: 1;
  height: calc(var(--h) * 1%);
  background: linear-gradient(180deg, #f8d2c0 0%, #f4baa3 55%, #d98f72 100%);
  transform-origin: bottom;
}

/* The two sliders are the interface's own lines: a hairline, a round knob. */
.app input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  height: 16px;
  margin: 0;
  cursor: pointer;
  --rail: rgba(154, 163, 174, 0.5);
  --done: var(--rail);
}

.app input[type="range"]::-webkit-slider-runnable-track {
  height: 2px;
  background: linear-gradient(90deg, var(--done) var(--p, 0%), var(--rail) var(--p, 0%));
}

.app input[type="range"]::-moz-range-track {
  height: 2px;
  background: linear-gradient(90deg, var(--done) var(--p, 0%), var(--rail) var(--p, 0%));
}

.app input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 9px;
  height: 9px;
  margin-top: -3.5px;
  border-radius: 50%;
  background: var(--text);
}

.app input[type="range"]::-moz-range-thumb {
  width: 9px;
  height: 9px;
  border: 0;
  border-radius: 50%;
  background: var(--text);
}

.app-seek {
  display: block;
  width: 100%;
  --done: var(--accent);
  margin-bottom: 0.5rem !important;
}

.app-transport {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid rgba(154, 163, 174, 0.2);
  margin-bottom: 0.8rem;
}

.app-buttons {
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
}

.app button.app-primary {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
  padding: 0.16rem 0.7rem;
  border-radius: 2px;
  min-width: 10ch;
  text-align: center;
}

.app button.app-primary:hover { filter: brightness(1.08); }

.app-volume {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--dim);
}

.app-volume input { width: 150px; }
.app-volume output { color: var(--text); min-width: 3ch; text-align: right; }

.app-header {
  font-weight: 600;
  margin-bottom: 0.2rem;
}

.app-rows {
  list-style: none;
  margin: 0 0 0.6rem;
  padding: 0;
}

.app button.app-row {
  display: grid;
  grid-template-columns: 3.4ch 1fr auto;
  gap: 1ch;
  align-items: baseline;
  position: relative;
  width: calc(100% + 0.6rem);
  margin: 0 -0.3rem;
  /* Every row keeps two cells for the marker, the way the interface does: the
     numbers and names never move when a row starts to play. */
  padding: 0.04rem 0.3rem 0.04rem calc(0.3rem + 2ch);
  border-radius: 1px;
}

.app button.app-row:hover { background: rgba(244, 240, 226, 0.07); }

.app-num {
  color: var(--dim);
  text-align: right;
  white-space: nowrap;
}

.app-name,
.app-fact {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-fact {
  color: var(--dim);
  max-width: 30ch;
  text-align: right;
}

.app button.app-row.selected {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

.app-row.selected .app-num,
.app-row.selected .app-fact { color: var(--accent-ink); }

#marker {
  position: absolute;
  left: 0.3rem;
  width: 2ch;
  text-align: left;
}

.app-footer {
  display: flex;
  /* The interface joins its hints with two spaces and drops one rather than
     wrap, so the row is one line wide: the gaps here are those two spaces at
     the size this strip is set in. */
  flex-wrap: wrap;
  gap: 0.2rem 2ch;
  padding-top: 0.7rem;
  border-top: 1px solid rgba(154, 163, 174, 0.2);
  color: var(--dim);
  font-size: 0.66rem;
}

.app-footer b {
  color: var(--cool);
  font-weight: 400;
}

/* The card every other key opens: the interface's own kind of overlay. */
.app-card {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(88%, 25rem);
  padding: 1.1rem 1.3rem 0.9rem;
  background: rgba(13, 17, 25, 0.96);
  border: 1px solid var(--accent);
  border-radius: 6px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6);
  font-family: var(--sans);
  font-size: 0.86rem;
  color: var(--soft);
}

.app-card p { margin: 0 0 0.8rem; }

.app-card-title {
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--accent);
}

.app-card-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
}

.app-card .app-card-close {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--dim);
}

.app-card-close b { color: var(--cool); font-weight: 400; }

/* ---- the rest of the page ---- */

.page { padding-top: 1rem; }

h2 {
  font-size: clamp(1.55rem, 2.5vw, 2.15rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 650;
  margin: 0 0 1.8rem;
  max-width: 22ch;
  text-wrap: balance;
}

.page p,
.page dd,
.page li { color: var(--soft); }

.page code {
  font-family: var(--mono);
  font-size: 0.88em;
  color: var(--text);
  background: rgba(244, 240, 226, 0.09);
  padding: 0.08em 0.36em;
  border-radius: 3px;
}

kbd {
  font-family: var(--mono);
  font-size: 0.84em;
  color: var(--cool);
  border: 1px solid rgba(166, 200, 226, 0.4);
  border-bottom-width: 2px;
  border-radius: 4px;
  padding: 0 0.4em;
  white-space: nowrap;
}

.section-lede {
  max-width: 62ch;
  margin: 0;
}

/* A band: prose on one side, the thing itself on the other. */
/* The picture column is the width of the player in the hero. */
.band {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 572px);
  gap: 4.5rem;
  align-items: center;
  padding: 5.5rem 0;
}

.band.flip { grid-template-columns: minmax(0, 572px) minmax(0, 1fr); }
.band.flip .band-copy { order: 2; }

.points {
  display: grid;
  gap: 1.15rem;
  margin: 0;
}

.points dt {
  font-weight: 600;
  color: var(--text);
  margin-bottom: 0.1rem;
}

.points dd {
  margin: 0;
  max-width: 54ch;
}

/* A terminal's worth of glass: commands, their output, a config file. */
.term {
  position: relative;
  margin: 0;
  padding: 1.2rem 1.4rem 1.3rem;
  border: 1px solid var(--hair);
  border-radius: 12px;
  background: var(--glass);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow: 0 30px 70px -30px rgba(0, 0, 0, 0.7);
}

.term figcaption {
  font-size: 0.8rem;
  color: var(--soft);
  margin-bottom: 0.9rem;
}

.term pre {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.8rem;
  line-height: 1.75;
  color: var(--text);
  overflow-x: auto;
}

.term .p { color: var(--accent); }
.term .c { color: var(--dim); }

.sw {
  display: inline-block;
  width: 0.72em;
  height: 0.72em;
  margin-right: 0.55em;
  border-radius: 2px;
  background: var(--c);
  outline: 1px solid rgba(244, 240, 226, 0.35);
}

/* Scenes: other screens of the interface, drawn in the same glass as the
   player in the hero and at its width, from captures of the real thing. They
   are pictures, not controls. */
.scene-fig { margin: 0; }

.scene-fig figcaption {
  margin-top: 0.8rem;
  font-size: 0.82rem;
  color: var(--soft);
}

.scene {
  font-size: 0.72rem;
  cursor: default;
  overflow: hidden;
}

.scene .app-tabs span { color: var(--dim); }
.scene .app-tabs span.on { color: var(--text); font-weight: 600; }

.s-title { font-weight: 600; }
.s-sub { color: var(--dim); margin-bottom: 0.8rem; }
.s-stopped { margin-left: 2ch; }

.scene .app-spectrum {
  opacity: 1;
  height: 44px;
  gap: 4px;
  margin-bottom: 0.4rem;
}

.s-progress {
  height: 2px;
  background: rgba(154, 163, 174, 0.3);
  margin-bottom: 0.6rem;
}

.s-progress span {
  display: block;
  height: 100%;
  background: var(--accent);
}

.s-transport {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.9rem;
  white-space: nowrap;
}

.s-transport > span {
  display: inline-flex;
  align-items: center;
  gap: 1ch;
}

.s-primary {
  background: var(--accent);
  color: var(--accent-ink);
  padding: 0 1ch;
}

.s-gap { margin-left: 2ch; }
.s-cool { color: var(--cool); }

.s-gauge {
  position: relative;
  width: 7ch;
  height: 2px;
  background: rgba(154, 163, 174, 0.5);
}

.s-gauge span {
  position: absolute;
  top: -3px;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  border-radius: 50%;
  background: var(--text);
}

.s-head {
  display: flex;
  gap: 2ch;
  padding-left: 3ch;
  margin-bottom: 0.1rem;
  white-space: nowrap;
}

.s-head b { font-weight: 600; }

.s-rows { margin-bottom: 0.7rem; }

.s-row {
  display: grid;
  grid-template-columns: 2ch 3ch minmax(0, 1fr) auto;
  gap: 1ch;
  margin: 0 -0.3rem;
  padding: 0.03rem 0.3rem;
}

.s-row .app-name { min-width: 0; }
.s-meta { color: var(--dim); margin-left: 2ch; }

.s-row.selected {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

.s-row.selected .app-num,
.s-row.selected .app-fact,
.s-row.selected .s-meta { color: var(--accent-ink); }

.s-space { height: 5.5rem; }

.s-status {
  color: var(--accent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 0.3rem;
}

/* The interface's own cards: a thin frame with its title set into the edge. */
.s-card {
  position: absolute;
  display: grid;
  padding: 0.7rem 1.4ch 0.5rem;
  background: rgb(13, 16, 23);
  border: 1px solid var(--dim);
  border-radius: 4px;
}

.s-card-title {
  position: absolute;
  top: -0.8em;
  left: 1ch;
  padding: 0 0.6ch;
  color: var(--accent);
  font-weight: 600;
  background: linear-gradient(180deg, transparent 45%, rgb(13, 16, 23) 45%);
}

/* Both cards sit in the middle of the screen, as the interface places them. */
.s-card-list,
.s-card-prompt {
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.s-card-list .on { color: var(--accent); }

/* ---- the themes, tried on the picture ----
 *
 * Each rule below is one of the themes built into the binary, with the seven
 * colours `src/ui/theme/builtins.rs` gives it, mapped onto the tokens the
 * picture already draws with: background → --glass, text → --text, dim →
 * --dim, accent → --accent, ink → --accent-ink, secondary → --cool, border →
 * --hair. `velo` has no rule: it is the page's own palette, and the picture
 * stays glass. `default terminal` has no chip: it is the reader's terminal,
 * which a web page cannot show. No script — the checked radio is the state. */

.themes { margin: 1.2rem 0 0; }

/* Twelve names do not fit one row, and a segmented bar that wraps reads as
   a broken table: here each theme is a chip of its own, so a second row is
   just more chips. Nothing clips, so the focus ring is drawn whole. */
.themes .picker {
  display: flex;
  gap: 0.4rem;
  border: 0;
  border-radius: 0;
  overflow: visible;
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.themes .picker label {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.68rem;
  padding: 0.3rem 0.6rem 0.3rem 0.45rem;
  border: 1px solid var(--hair);
  border-radius: 999px;
  background: var(--glass);
}

.themes .picker label:last-child { border-right: 1px solid var(--hair); }
.themes .picker label:focus-within { outline-offset: 2px; }

.themes .picker label:has(input:checked) {
  border-color: var(--accent);
}

/* The theme's own accent on its own background: the chip shows what the
   name means before it is chosen. */
.themes .picker label::before {
  content: "";
  flex: none;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--sw);
  border: 2px solid var(--sw-bg);
  box-shadow: 0 0 0 1px var(--hair);
}

/* A chosen theme paints its own background: nothing shows through it. */
.look:has(input[name="theme"]:not([value="velo"]):checked) .scene {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.7);
}

.look:has(input[name="theme"]:not([value="velo"]):checked) .scene .app-spectrum i {
  background: var(--accent);
}

.look:has(input[name="theme"]:not([value="velo"]):checked) .scene :is(.s-progress, .s-gauge) {
  background: var(--hair);
}

.look:has(input[name="theme"]:not([value="velo"]):checked) .scene .app-footer {
  border-top-color: var(--hair);
}

.look:has(input[name="theme"]:not([value="velo"]):checked) .scene .s-card {
  background: var(--glass);
}

.look:has(input[name="theme"]:not([value="velo"]):checked) .scene .s-card-title {
  background: linear-gradient(180deg, transparent 45%, var(--glass) 45%);
}

.look:has(input[value="catppuccin-latte"]:checked) .scene {
  --glass: #eff1f5; --text: #4c4f69; --dim: #9ca0b0; --accent: #8839ef;
  --accent-ink: #eff1f5; --cool: #1e66f5; --hair: #ccd0da;
}

.look:has(input[value="catppuccin-mocha"]:checked) .scene {
  --glass: #1e1e2e; --text: #cdd6f4; --dim: #7f849c; --accent: #cba6f7;
  --accent-ink: #1e1e2e; --cool: #89b4fa; --hair: #313244;
}

.look:has(input[value="dracula"]:checked) .scene {
  --glass: #282a36; --text: #f8f8f2; --dim: #6272a4; --accent: #bd93f9;
  --accent-ink: #282a36; --cool: #8be9fd; --hair: #44475a;
}

.look:has(input[value="gruvbox-dark"]:checked) .scene {
  --glass: #282828; --text: #ebdbb2; --dim: #928374; --accent: #fe8019;
  --accent-ink: #282828; --cool: #83a598; --hair: #3c3836;
}

.look:has(input[value="monokai"]:checked) .scene {
  --glass: #272822; --text: #f8f8f2; --dim: #75715e; --accent: #a6e22e;
  --accent-ink: #272822; --cool: #66d9ef; --hair: #49483e;
}

.look:has(input[value="nord"]:checked) .scene {
  --glass: #2e3440; --text: #eceff4; --dim: #7b88a1; --accent: #88c0d0;
  --accent-ink: #2e3440; --cool: #81a1c1; --hair: #434c5e;
}

.look:has(input[value="one-dark"]:checked) .scene {
  --glass: #282c34; --text: #abb2bf; --dim: #5c6370; --accent: #61afef;
  --accent-ink: #282c34; --cool: #c678dd; --hair: #3e4451;
}

.look:has(input[value="one-light"]:checked) .scene {
  --glass: #fafafa; --text: #383a42; --dim: #a0a1a7; --accent: #0184bc;
  --accent-ink: #fafafa; --cool: #a626a4; --hair: #d4d4d4;
}

.look:has(input[value="solarized-dark"]:checked) .scene {
  --glass: #002b36; --text: #839496; --dim: #586e75; --accent: #268bd2;
  --accent-ink: #fdf6e3; --cool: #2aa198; --hair: #073642;
}

.look:has(input[value="solarized-light"]:checked) .scene {
  --glass: #fdf6e3; --text: #657b83; --dim: #93a1a1; --accent: #268bd2;
  --accent-ink: #fdf6e3; --cool: #2aa198; --hair: #eee8d5;
}

.look:has(input[value="tokyo-night"]:checked) .scene {
  --glass: #1a1b26; --text: #c0caf5; --dim: #565f89; --accent: #7aa2f7;
  --accent-ink: #1a1b26; --cool: #bb9af7; --hair: #292e42;
}

.s-card-prompt {
  /* Raised so its title lands in the empty spectrum rows, clear of the transport. */
  top: calc(50% - 2.4rem);
  width: min(86%, 44ch);
  gap: 0.05rem;
}

.s-card-keys { margin-top: 0.7rem; }

.s-caret {
  display: inline-block;
  width: 1px;
  height: 1.1em;
  margin-left: 1px;
  vertical-align: text-bottom;
  background: var(--text);
}

/* ---- radio ---- */

.stats {
  display: flex;
  gap: 3rem;
  margin-bottom: 1.8rem;
}

.stat {
  margin: 0;
  max-width: 20ch;
}

.stat b {
  display: block;
  font-size: clamp(2.4rem, 4.4vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.04em;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  margin-bottom: 0.6rem;
}

.plain {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.85rem;
}

.live { color: var(--accent); font-family: var(--mono); font-size: 0.88em; }

/* ---- cliamp radio ---- */

/* It belongs to the radio band above it: no section of its own, so it is
   pulled up under that band instead of standing a full gap away. */
.cliamp { margin-top: -2.5rem; padding: 0 0 5.5rem; }

.cliamp-head {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: 4.5rem;
  align-items: start;
  margin-bottom: 1.4rem;
}

.cliamp h3 {
  margin: 0 0 0.8rem;
  font-size: 1.3rem;
  font-weight: 600;
}

/* The channels by name, in the interface's own type: what is there, without
   a count per channel that the service changes on its own. */
.channels-line {
  margin: 1rem 0 0;
  max-width: 62ch;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--soft);
}

/* A thank-you in the first person, set apart by the accent, not by a box. */
.thanks {
  margin: 0;
  padding-left: 1.4rem;
  border-left: 2px solid var(--accent);
}

.thanks p {
  margin: 0 0 0.6rem;
  font-size: 1.08rem;
  line-height: 1.5;
  color: var(--text);
}

.thanks footer a { color: inherit; }

.thanks footer {
  font-size: 0.82rem;
  color: var(--soft);
}

/* The thank-you is a remark on the text beside it, so it starts level with
   that text, under the heading, and an arrow in the gutter points back at
   what it is about. */
.cliamp .thanks {
  position: relative;
  margin-top: 2.7rem;
}

.cliamp .thanks::before {
  content: "←";
  position: absolute;
  left: -2.6rem;
  top: 0.05rem;
  font-family: var(--mono);
  font-size: 1.05rem;
  color: var(--accent);
}

/* Who is saying it, the way a shared document shows who else is writing:
   a name tag in the accent, with a face. Still, it signs the remark; while
   the remark is being typed it hangs from the caret and goes where it goes. */
.thanks footer .who {
  display: inline-block;
  margin-top: 0.3rem;
  text-decoration: none;
}

.who-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.16rem 0.6rem 0.16rem 0.2rem;
  border-radius: 3px 999px 999px 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--sans);
  font-size: 0.76rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

.who-tag img {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  object-fit: cover;
}

/* While it is being typed: what is not written yet keeps its room, so the
   block never changes height, and a caret stands where the next letter goes.
   The room under the last line is the tag's, when the caret reaches it. */
.thanks.typing { padding-bottom: 2.3rem; }
.thanks .unwritten { visibility: hidden; }

/* The caret is an empty inline: it takes no width and, unlike a box, it is
   no place to break a line, so a word it stands inside wraps as it would
   whole and the paragraph keeps its lines. The bar is its own layer: it
   blinks, the tag hanging from it does not. */
.thanks .caret { position: relative; }

.thanks .caret::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.12em;
  width: 2px;
  height: 1.1em;
  background: var(--accent);
}

.thanks .caret .who-tag {
  position: absolute;
  top: calc(1.45em + 2px);
  left: 0;
}

/* Past the middle of the line the tag hangs to the left, so it never leaves
   the column. */
.thanks .caret.flip .who-tag {
  left: auto;
  right: -2px;
  border-radius: 999px 3px 999px 999px;
}

@keyframes caret {
  0%, 55% { opacity: 1; }
  56%, 100% { opacity: 0; }
}

/* For the readers a screen cannot type for: the sentence, whole. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* On air: the interface's own live mark, in front of the channels. */
.on-air {
  position: relative;
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: 0.7rem;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 0.05em;
}

.on-air::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid var(--accent);
  opacity: 0;
}

@keyframes point {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(-0.45rem); }
}

@keyframes on-air {
  0% { transform: scale(1); opacity: 0.7; }
  70%, 100% { transform: scale(2.8); opacity: 0; }
}

.cliamp-note {
  margin: 1.2rem 0 0;
  font-size: 0.86rem;
  max-width: 70ch;
}

/* ---- keys ---- */

.keys { padding: 5.5rem 0; }
.keys h2 { margin-bottom: 1rem; }

.keymap {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: 2.5rem;
  margin: 2.2rem 0 0;
  border-top: 1px solid var(--hair);
}

.keymap div {
  display: grid;
  grid-template-columns: 4.6rem 1fr;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--hair);
  font-size: 0.86rem;
}

.keymap dt { white-space: nowrap; }
.keymap dd { margin: 0; }

/* ---- servers, privacy, what is missing ---- */

.notes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 3rem;
  padding: 4rem 0 5rem;
}

.notes h2 {
  font-size: 1.05rem;
  letter-spacing: 0;
  margin-bottom: 0.6rem;
}

.notes p {
  margin: 0;
  font-size: 0.92rem;
}

/* ---- who makes it ---- */

/* The same glass as every panel on the page, with the links set the way the
   interface sets its keys: the label in the cool colour, the value beside it. */
.maker {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 2.2rem;
  align-items: center;
  margin-top: 4rem;
  padding: 1.8rem 2rem;
  border: 1px solid var(--hair);
  border-radius: 12px;
  background: var(--glass);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
  box-shadow: 0 30px 70px -30px rgba(0, 0, 0, 0.7);
}

/* The portrait takes the page's light: no colour of its own, warmed a little,
   inside a ring of the accent. */
.maker img {
  display: block;
  width: 112px;
  height: 112px;
  border-radius: 50%;
  filter: grayscale(1) sepia(0.35) contrast(1.05) brightness(0.92);
  outline: 1px solid var(--accent);
  outline-offset: 4px;
}

.maker h2 {
  font-size: clamp(1.3rem, 2vw, 1.6rem);
  margin-bottom: 0.6rem;
  max-width: none;
}

.maker p {
  margin: 0;
  max-width: 56ch;
  font-size: 0.95rem;
}

.maker-links {
  list-style: none;
  margin: 0;
  padding: 0 0 0 2.2rem;
  border-left: 1px solid var(--hair);
  display: grid;
  gap: 0.55rem;
  font-family: var(--mono);
  font-size: 0.78rem;
}

.maker-links a {
  display: grid;
  grid-template-columns: 5ch auto;
  gap: 1ch;
  color: var(--text);
  text-decoration: none;
}

.maker-links b { color: var(--cool); font-weight: 400; }
.maker-links a:hover { color: var(--accent); }

/* ---- the last word ---- */

.start .term {
  margin-bottom: 1.2rem;
  padding-bottom: 3.4rem;
}

/* The command is always whole: it wraps the way a terminal wraps a long line. */
.start .term pre {
  white-space: pre-wrap;
  word-break: break-all;
}

.start .copy {
  position: absolute;
  bottom: 1.2rem;
  right: 1.1rem;
}

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

.bottom {
  display: flex;
  justify-content: space-between;
  gap: 1rem 2rem;
  flex-wrap: wrap;
  border-top: 1px solid var(--hair);
  margin-top: 3.2rem;
  padding: 1.5rem 0 3rem;
  font-size: 0.8rem;
  color: var(--soft);
}

.footer-links { display: inline-flex; gap: 1.4rem; }

/* ---- narrow screens ---- */

@media (max-width: 980px) {
  .wrap { padding: 0 1.25rem; }
  .hero { padding: 5.5rem 0 14vh; }
  .hero-grid { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
  .hero-media::after {
    background: linear-gradient(180deg, rgba(7, 9, 13, 0.82) 0%, rgba(7, 9, 13, 0.62) 45%, rgba(7, 9, 13, 0.2) 100%);
  }
  .lede { max-width: none; }
  .top-links { gap: 1.1rem; }

  .app { font-size: 0.68rem; }
  .app-fact { max-width: 12ch; }
  .app-volume input { width: 84px; }

  .band { grid-template-columns: minmax(0, 1fr); gap: 2.2rem; padding: 3.5rem 0; }
  .band.flip { grid-template-columns: minmax(0, 1fr); }
  .band.flip .band-copy { order: 0; }
  .scene { font-size: 0.62rem; }
  .s-meta { display: none; }
  .keys { padding: 3.5rem 0; }
  .stats { gap: 2rem; }
  .keymap { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 1.5rem; }
  .cliamp { margin-top: -1rem; padding: 0 0 3.5rem; }
  .cliamp-head { grid-template-columns: minmax(0, 1fr); gap: 1.8rem; }
  /* One column: the remark stands under the text, so the arrow points up. */
  .cliamp .thanks::before { content: "↑"; left: 1.4rem; top: -1.7rem; }
  .cliamp .thanks { margin-top: 1.4rem; }
  .notes { grid-template-columns: minmax(0, 1fr); gap: 2rem; padding: 3rem 0; }
  .maker { grid-template-columns: auto minmax(0, 1fr); gap: 1.4rem; padding: 1.4rem; }
  .maker img { width: 72px; height: 72px; }
  .maker-links { grid-column: 1 / -1; padding: 1.1rem 0 0; border-left: 0; border-top: 1px solid var(--hair); }
}

@media (max-width: 560px) {
  .keymap { grid-template-columns: 1fr; }
  .app-fact { display: none; }
  .scene .app-fact { display: inline; }
  .s-transport .s-gap.dim:not(:last-of-type),
  .s-transport .s-gap + .dim { display: none; }
  .app button.app-row { grid-template-columns: 3.4ch 1fr; }
}

/* The install block, pointed at from the player's card: an outline for a
   moment instead of a scroll, since on a wide window it is already in view. */
.install {
  outline: 2px solid transparent;
  outline-offset: 12px;
  border-radius: 6px;
}

.install.nudge { outline-color: var(--accent); }

@keyframes nudge {
  0%, 100% { outline-color: transparent; }
  15%, 70% { outline-color: var(--accent); }
}

/* ---- motion, only when the reader allows it ---- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

@media (prefers-reduced-motion: no-preference) {
  .cta { transition: filter 0.15s ease; }
  .install.nudge { animation: nudge 1.8s ease; }
  .cliamp .thanks::before { animation: point 2.4s ease-in-out infinite; }
  .on-air::after { animation: on-air 2.2s ease-out infinite; }
  .thanks .caret::before { animation: caret 1s steps(1) infinite; }
}
