/* SPDX-License-Identifier: CC-BY-SA-4.0 */
/* Setloom. Generated by publish.py in the study folder: tokens, icons, base, page. */

/* Setloom colour tokens: Bone and Acid.

   Bone and black with an acid-lime signal. Semantic tokens with a light and a
   dark set. The page follows the system setting unless the visitor chooses a
   mode, which is stored as data-theme on <html>.

   Acid lime is a fill colour. It is too light to be text on bone, so text that
   needs the signal colour uses --link, which is lime in dark mode and a deep
   olive in light mode. Every reading pair meets WCAG 2.2 (body 7:1, rest 4.5:1). */

:root {
  color-scheme: light;
  --bg: #ECEAE3;
  --surface: #E1DED5;
  --text: #111110;
  --soft: #3A3935;
  --muted: #62605A;
  --line: #CFCCC2;
  --staff: #A9A69C;
  --accent: #C6F135;
  --on-accent: #111110;
  --link: #3F5A00;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0D0E0C;
    --surface: #161714;
    --text: #E9E8E2;
    --soft: #B9B8B0;
    --muted: #8C8B84;
    --line: #262724;
    --staff: #3B3C37;
    --accent: #D2FF3D;
    --on-accent: #0D0E0C;
    --link: #D2FF3D;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0D0E0C;
  --surface: #161714;
  --text: #E9E8E2;
  --soft: #B9B8B0;
  --muted: #8C8B84;
  --line: #262724;
  --staff: #3B3C37;
  --accent: #D2FF3D;
  --on-accent: #0D0E0C;
  --link: #D2FF3D;
}

::selection { background: color-mix(in srgb, var(--accent) 55%, transparent); color: var(--text); }

/* Setloom icons. Generated by icons.py: edit there. */

.ic {
  --house: cubic-bezier(0.16, 0.84, 0.24, 1);
  display: inline-block;
  flex: none;
  vertical-align: middle;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: square;
  stroke-linejoin: miter;
}
.ic .sig { stroke: var(--link, currentColor); }
.ic .ink { fill: currentColor; stroke: none; }
.ic .acc { fill: var(--accent, currentColor); }
.ic .cut { fill: var(--bg, Canvas); }
.ic .faint { stroke: var(--staff, currentColor); }
.ic .thick { stroke-width: 3; stroke-linecap: butt; }

.ic .pop, .ic .grow { transform-box: fill-box; transform-origin: center; }
.ic .rise { transform-box: fill-box; transform-origin: 50% 100%; }
.ic .spin, .ic .swell, .ic .flip { transform-box: view-box; transform-origin: var(--ox, 12px) var(--oy, 12px); }

/* Armed by icons.js: every animation waits at its first frame until played. */
@media (prefers-reduced-motion: no-preference) {
  .ic.armed :is(.draw, .pop, .drop, .slide, .travel, .grow, .rise, .spin, .swell, .blink, .flip) {
    animation-duration: var(--d, 0.8s);
    animation-timing-function: var(--e, var(--house));
    animation-delay: var(--t, 0s);
    animation-fill-mode: both;
    animation-play-state: paused;
  }
  .ic.armed .draw { stroke-dasharray: 1; animation-name: ic-draw; }
  .ic.armed .pop { animation-name: ic-pop; }
  .ic.armed .drop { animation-name: ic-drop; }
  .ic.armed .slide { animation-name: ic-slide; }
  .ic.armed .travel { animation-name: ic-travel; }
  .ic.armed :is(.grow, .rise) { animation-name: ic-grow; }
  .ic.armed .spin { animation-name: ic-spin; }
  .ic.armed .swell { animation-name: ic-swell; }
  .ic.armed .blink { animation-name: ic-blink; }
  .ic.armed .flip { animation-name: ic-flip; }
}

/* A dash offset by its whole length still paints its square cap, so a line
   that has not started is also transparent. */
@keyframes ic-draw { 0% { stroke-dashoffset: 1; opacity: 0; } 1% { opacity: 1; } 100% { stroke-dashoffset: 0; } }
@keyframes ic-pop { from { opacity: 0; transform: scale(0.4); } }
@keyframes ic-drop { from { opacity: 0; transform: translateY(var(--dy, -4px)); } }
@keyframes ic-slide { from { opacity: 0; transform: translate(var(--dx, 0px), var(--dy, 0px)); } }
@keyframes ic-travel { from { transform: translate(var(--dx, 0px), var(--dy, 0px)); } }
@keyframes ic-grow { from { transform: scaleY(0); } }
@keyframes ic-spin { from { transform: rotate(var(--r0, -180deg)); } }
@keyframes ic-swell { from { opacity: 0; transform: scale(var(--s0, 1.3)); } }
@keyframes ic-blink { 0%, 24.9%, 50%, 74.9% { opacity: 1; } 25%, 49.9%, 75%, 99.9% { opacity: 0; } 100% { opacity: 1; } }
@keyframes ic-flip { from { transform: scaleX(1); } to { transform: scaleX(-1); } }

/* Setloom stage studies: shared ground for the hero, loop, background and
   footer directions. Tokens come from current/tokens.css (Bone and Acid),
   icons from icons/icons.css. Sizes stay on the standard scale. */

@font-face { font-family: "Outward Block"; src: url("fonts/outward-block.woff2") format("woff2"); font-display: swap; }

:root {
  --gutter: clamp(20px, 6vw, 96px);
  --max: 78rem;
  --shell: min(100vw - 2 * var(--gutter), var(--max));
  --house: cubic-bezier(0.16, 0.84, 0.24, 1);
  --rise: cubic-bezier(0.19, 0.8, 0.22, 1);
  --hero: "Outward Block", "Arial Narrow", sans-serif;
  --display: "Melodrama", "Helvetica Neue", Arial, sans-serif;
  --body: "Supreme", "Helvetica Neue", Arial, sans-serif;
  --mono: "Tabular", ui-monospace, Menlo, monospace;

  /* The wordmark on its staff. Outward Block: cap height 0.700em, x-height
     0.542em, "Setloom" 1.067em wide. Five lines span the cap height, so the
     lowercase tops sit on the second line. */
  --cap: 0.7em;
  --space: 0.175em;
  --wm-width: 1.067em;
  --rule: max(1px, 0.0028em);
}

* { box-sizing: border-box; margin: 0; font-synthesis: none; }
html { overflow-x: clip; }
body { background: var(--bg); color: var(--text); font: 400 16px/1.6 var(--body); -webkit-font-smoothing: antialiased; }
a { color: inherit; }
.shell { width: var(--shell); margin-inline: auto; }

/* ---------- masthead: brand, links and switch on one centre line ---------- */

.mast { position: absolute; inset: 0 0 auto; z-index: 10; }
.mast .shell { display: flex; align-items: center; justify-content: space-between; gap: 24px; height: 88px; }
.brand { font: 500 24px/1 var(--display); text-decoration: none; }
.mast nav { display: flex; align-items: center; gap: 32px; }
.mast nav a { display: inline-flex; align-items: center; gap: 8px; color: var(--muted); font-size: 16px; line-height: 1; text-decoration: none; transition: color 0.2s var(--house); }
.mast nav a:hover { color: var(--text); }
.mode-switch { display: grid; place-items: center; width: 40px; height: 40px; margin-right: -10px; padding: 0; color: var(--text); background: none; border: 0; cursor: pointer; }
@media (max-width: 64rem) { .mast nav a.section { display: none; } }

/* ---------- buttons ---------- */

.actions { display: flex; flex-wrap: wrap; gap: 12px 16px; }
.btn { display: inline-flex; align-items: center; gap: 12px; padding: 16px 20px; font-size: 16px; line-height: 1; color: var(--text); text-decoration: none; box-shadow: inset 0 0 0 1px var(--staff); transition: box-shadow 0.2s var(--house), background-color 0.2s var(--house); }
.btn:hover { box-shadow: inset 0 0 0 1px var(--text); }
.btn.solid { background: var(--accent); color: var(--on-accent); box-shadow: none; }
.btn.solid:hover { background: var(--text); color: var(--bg); }

/* ---------- hero frame shared by the three directions ---------- */

.hero { position: relative; height: 200vh; }
/* The stage keeps the masthead's 72px clear at the top, so nothing in the hero
   ever runs under the header. */
.stage { position: sticky; top: 0; height: 100vh; min-height: 640px; overflow: clip; display: grid; align-items: end; padding: 104px 0 12vh; }
.hero h1 { font-weight: 400; display: grid; gap: 40px; }
.wordmark { position: relative; display: block; width: var(--wm-width); font: 400 var(--wm) / 0.858 var(--hero); white-space: nowrap; }
.word { display: block; height: var(--cap); }
.line { max-width: 24ch; font: 400 20px/1.4 var(--body); color: var(--soft); text-wrap: pretty; }
.hero .actions { margin-top: 32px; }
/* Stacked, the name is sized by the width and by the height, so the line and
   buttons below it still fit on the first screen of a short window. */
.hero { --wm: min(calc(var(--shell) / 1.067), 58svh); }
@media (min-width: 48rem) { .line { font-size: 24px; } }
@media (min-width: 64rem) {
  .hero { --wm: min(calc(var(--shell) * 0.52), 78vh); }
  .hero .grid { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: clamp(40px, 5vw, 88px); align-items: end; }
  .hero h1 { display: contents; }
  .wordmark { grid-row: 1 / 3; }
  .line { grid-column: 2; grid-row: 1; align-self: end; }
  .hero .actions { grid-column: 2; grid-row: 2; }
}

/* The staff runs in from the window's left edge and ends just after the name
   on a final barline, so the name is one whole bar and the text beside it
   stands in clear space. */
:root { --bar-end: 0.06em; }
.staff { position: absolute; z-index: -1; top: 0; left: calc((var(--shell) - 100vw) / 2); width: calc((100vw - var(--shell)) / 2 + var(--wm-width) + var(--bar-end)); height: var(--cap); pointer-events: none; }
.staff::after { content: ""; position: absolute; top: 0; right: 0; width: calc(var(--rule) * 9); height: calc(var(--cap) + var(--rule) / 2); background: linear-gradient(to right, var(--staff) 0 var(--rule), transparent 0 calc(var(--rule) * 4), var(--staff) 0); }
.staff i { position: absolute; left: 0; right: 0; height: var(--rule); background: var(--staff); transform-origin: left; }
.staff i:nth-child(1) { top: calc(0 * var(--space) - var(--rule) / 2); }
.staff i:nth-child(2) { top: calc(1 * var(--space) - var(--rule) / 2); }
.staff i:nth-child(3) { top: calc(2 * var(--space) - var(--rule) / 2); }
.staff i:nth-child(4) { top: calc(3 * var(--space) - var(--rule) / 2); }
.staff i:nth-child(5) { top: calc(4 * var(--space) - var(--rule) / 2); }
.wordmark { isolation: isolate; }

/* The three inner staff lines cut through the letters, so the staff reads
   unbroken across the name. */
.engraved {
  background-color: var(--text);
  background-image: linear-gradient(to bottom,
    transparent calc(1 * var(--space) - var(--rule) / 2), var(--bg) 0 calc(1 * var(--space) + var(--rule) / 2),
    transparent 0 calc(2 * var(--space) - var(--rule) / 2), var(--bg) 0 calc(2 * var(--space) + var(--rule) / 2),
    transparent 0 calc(3 * var(--space) - var(--rule) / 2), var(--bg) 0 calc(3 * var(--space) + var(--rule) / 2),
    transparent 0);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ---------- the section after the hero, so there is somewhere to scroll ---------- */

.after { position: relative; z-index: 1; background: var(--bg); padding: 120px 0 160px; border-top: 1px solid var(--line); }
.after h2 { font: 500 48px/1.1 var(--display); max-width: 20ch; }
.after p { margin-top: 24px; max-width: 62ch; font-size: 18px; color: var(--soft); }
@media (min-width: 64rem) { .after h2 { font-size: 60px; } }


.cue { font: 400 12px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ---------- the page ---------- */
/* Setloom, the whole page. One idea runs through it: the page is a score and
   scrolling is its transport. Position is the playhead, speed is the tempo,
   direction is play or rewind.

   - Masthead: once it sticks it becomes the transport, with a bar and beat
     counter driven by scroll (CSS), the tempo and direction (script), and a
     progress rule along its foot.
   - Hero: the name engraved on five strings. Scroll plays it; speed plucks it;
     the letters arrive as a draft and are tuned in staff steps.
   - Premise: set like lyrics, lit word by word as the page passes.
   - Each section opens a new system of the score with a rehearsal mark.
   - The loop: the lights go down and the visitor is taken once round the ring.
   - Footer: the last bar, five strings ending on a final barline, Fine. */

@property --q { syntax: "<integer>"; inherits: true; initial-value: 0; }
@property --bar { syntax: "<integer>"; inherits: true; initial-value: 1; }
@property --step { syntax: "<integer>"; inherits: true; initial-value: 0; }

:root { --in-played: var(--accent); --out-played: var(--text); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --in-played: var(--bg); --out-played: var(--accent); } }
:root[data-theme="dark"] { --in-played: var(--bg); --out-played: var(--accent); }

/* The stage: lights down. The black set, whatever the page's mode, so the
   loop always plays in the dark. In dark mode the ground goes deeper still. */
:root.lights {
  color-scheme: dark;
  --bg: #0D0E0C; --surface: #161714; --text: #E9E8E2; --soft: #B9B8B0; --muted: #8C8B84;
  --line: #262724; --staff: #3B3C37; --accent: #D2FF3D; --on-accent: #0D0E0C; --link: #D2FF3D;
  --in-played: var(--bg); --out-played: var(--accent);
}
@media (prefers-color-scheme: dark) { :root.lights:not([data-theme="light"]) { --bg: #050605; --line: #1E1F1C; } }
:root.lights[data-theme="dark"] { --bg: #050605; --line: #1E1F1C; }
body, .mast, .sheet, .foot { transition: background-color 0.7s var(--house), color 0.7s var(--house); }

/* ---------- masthead and transport ---------- */

.mast { position: sticky; top: 0; z-index: 30; container: mast / scroll-state; background: transparent; }
.mast .shell { position: relative; height: 72px; }
/* The plate: a full-width strip of the ground, always under the masthead, so
   its words never sit on whatever scrolls beneath. */
.mast .shell::before { content: ""; position: absolute; z-index: -1; inset: 0 calc(50% - 50vw); background: var(--bg); transition: background-color 0.7s var(--house); }
.mast::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--text); transform-origin: left; transform: scaleX(0); }
.transport { display: none; align-items: center; gap: 20px; font: 400 14px/1 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
.transport b { font-weight: 400; color: var(--text); font-variant-numeric: tabular-nums; }
.transport .pos b::before { counter-reset: bar var(--bar) beat calc(mod(var(--q), 4) + 1); content: counter(bar, decimal-leading-zero) "." counter(beat); }
.transport .mode { display: inline-grid; place-items: center; width: 24px; height: 24px; color: var(--on-accent); background: var(--accent); box-shadow: 0 0 0 1px var(--text); font-size: 12px; letter-spacing: 0; }
.transport .mode::before { content: "▶"; }
.mast[data-dir="up"] .transport .mode::before { content: "◀◀"; font-size: 10px; letter-spacing: -0.1em; }
.mast[data-dir="hold"] .transport .mode::before { content: "❚❚"; font-size: 10px; letter-spacing: 0.05em; }
.transport .tempo b::before { counter-reset: bpm var(--bpm, 0); content: counter(bpm); }
.mast[data-dir="hold"] .transport .tempo b::before { content: "—"; }
@supports (animation-timeline: scroll()) {
  .mast { animation: transport-run linear both; animation-timeline: scroll(root); }
  @keyframes transport-run { from { --bar: 1; --q: 0; } to { --bar: 64; --q: 252; } }
  .mast::after { animation: transport-rule linear both; animation-timeline: scroll(root); }
  @keyframes transport-rule { to { transform: scaleX(1); } }
}
/* Stuck: the masthead is laid on a plate of the ground and shows the transport. */
@container mast scroll-state(stuck: top) {
  .transport { display: flex; }
}
@media (max-width: 64rem) { .transport .tempo { display: none; } }
@media (max-width: 48rem) {
  .mast nav { gap: 16px; }
  .mast nav a:not(.keep) { display: none; }
  /* On a phone the kept links show their icons only; the words stay for screen readers. */
  .mast nav a.keep { font-size: 0; gap: 0; }
  .transport { gap: 8px; }
  .transport .pos i { display: none; font-style: normal; }
}
.transport .pos i { font-style: normal; }

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

.hero { --amp: 0; --lead: calc((100vw - var(--shell)) / 2); margin-top: -72px; }
.string { position: absolute; left: 0; width: 100%; height: calc(var(--space) * 0.9); overflow: hidden; }
.string:nth-of-type(1) { top: calc(0 * var(--space) - var(--space) * 0.45); }
.string:nth-of-type(2) { top: calc(1 * var(--space) - var(--space) * 0.45); }
.string:nth-of-type(3) { top: calc(2 * var(--space) - var(--space) * 0.45); }
.string:nth-of-type(4) { top: calc(3 * var(--space) - var(--space) * 0.45); }
.string:nth-of-type(5) { top: calc(4 * var(--space) - var(--space) * 0.45); }
.string path {
  fill: none; stroke: var(--staff); stroke-width: 2px; vector-effect: non-scaling-stroke;
  transform-box: fill-box; transform-origin: center;
  transform: scaleY(max(0.001, calc(var(--amp) * var(--k) * 0.8)));
  animation: travel var(--period) linear infinite;
}
@keyframes travel { to { translate: calc(var(--wave) * -1) 0; } }
.played { position: absolute; z-index: -1; top: 0; left: calc(-1 * var(--lead)); width: calc(var(--lead) + var(--wm-width) + var(--bar-end)); height: var(--cap); pointer-events: none;
  clip-path: inset(-50% calc(100% - var(--lead)) -50% var(--lead)); }
.played .string path { stroke: var(--out-played); stroke-width: 3px; }
.playhead { position: absolute; z-index: 2; top: calc(var(--space) * -0.3); left: calc(var(--rule) * -2); width: calc(var(--rule) * 4); height: calc(var(--cap) + var(--space) * 0.6); background: var(--accent); box-shadow: 0 0 0 1px var(--text); }
.cue-line { position: absolute; left: calc(var(--rule) * 6); top: calc(var(--space) * -0.3); height: 0; white-space: nowrap; }
/* The cue is drawn from an attribute, so the h1's text is the name alone. */
.cue-line::before { content: attr(data-cue); position: absolute; top: 0; left: 0; font: 400 12px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--text); }
.word { display: flex; }
.word > span {
  display: block; background-color: var(--text);
  background-image: linear-gradient(to bottom, transparent calc(1 * var(--space) - var(--rule) / 2), var(--in-played) 0 calc(1 * var(--space) + var(--rule) / 2), transparent 0 calc(2 * var(--space) - var(--rule) / 2), var(--in-played) 0 calc(2 * var(--space) + var(--rule) / 2), transparent 0 calc(3 * var(--space) - var(--rule) / 2), var(--in-played) 0 calc(3 * var(--space) + var(--rule) / 2), transparent 0), linear-gradient(to bottom, transparent calc(1 * var(--space) - var(--rule) / 2), var(--bg) 0 calc(1 * var(--space) + var(--rule) / 2), transparent 0 calc(2 * var(--space) - var(--rule) / 2), var(--bg) 0 calc(2 * var(--space) + var(--rule) / 2), transparent 0 calc(3 * var(--space) - var(--rule) / 2), var(--bg) 0 calc(3 * var(--space) + var(--rule) / 2), transparent 0);
  background-size: 0% 100%, 100% 100%; background-repeat: no-repeat;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.hero .staff svg, .played svg { animation: rule 1.4s var(--rise) both; transform-origin: left; }
.hero .staff svg:nth-of-type(2), .played svg:nth-of-type(2) { animation-delay: 85ms; }
.hero .staff svg:nth-of-type(3), .played svg:nth-of-type(3) { animation-delay: 170ms; }
.hero .staff svg:nth-of-type(4), .played svg:nth-of-type(4) { animation-delay: 255ms; }
.hero .staff svg:nth-of-type(5), .played svg:nth-of-type(5) { animation-delay: 340ms; }
@keyframes rule { from { transform: scaleX(0); } }
.playhead, .cue-line { animation: appear 0.6s var(--house) 2.2s both; }
@keyframes appear { from { opacity: 0; transform: scaleY(0); } }
.hero .line, .hero .actions { animation: rise-in 0.95s var(--rise) both; }
.hero .line { animation-delay: 1.6s; }
.hero .actions { animation-delay: 1.685s; }
@keyframes rise-in { from { opacity: 0; transform: translateY(24px); } }
@supports (animation-timeline: scroll()) {
  .word > span {
    animation: draft 0.6s var(--house) both, tune 0.45s both, inked 0.45s both, hop linear both, sound linear both;
    animation-delay: calc(var(--i) * 85ms + 300ms), calc(1100ms + var(--k) * 110ms), calc(1100ms + var(--k) * 110ms), 0s, 0s;
    animation-timing-function: var(--house), steps(var(--n), end), steps(1, end), linear, linear;
    animation-timeline: auto, auto, auto, scroll(root), scroll(root);
    animation-range: normal, normal, normal, var(--a) var(--b), var(--a) var(--b);
  }
  @keyframes draft { from { opacity: 0; } }
  @keyframes tune { from { transform: translateY(calc(var(--o) * var(--space) / 2)); } to { transform: none; } }
  @keyframes inked { from { background-color: var(--staff); } to { background-color: var(--text); } }
  @keyframes hop { 0%, 100% { translate: 0 0; } 10%, 90% { translate: 0 calc(var(--space) / -2); } }
  @keyframes sound { to { background-size: 100% 100%, 100% 100%; } }
  .played { animation: play-strings linear both; animation-timeline: scroll(root); animation-range: 0 100vh; }
  @keyframes play-strings { to { clip-path: inset(-50% 0 -50% var(--lead)); } }
  .playhead { animation: appear 0.6s var(--house) 2.2s both, head linear both; animation-timeline: auto, scroll(root); animation-range: normal, 0 100vh; }
  @keyframes head { to { translate: calc(var(--wm-width) + var(--bar-end) - var(--rule) * 9) 0; } }
  .cue-line { animation: appear 0.6s var(--house) 2.2s both, cue-out linear both; animation-timeline: auto, scroll(root); animation-range: normal, 0 8vh; }
  @keyframes cue-out { to { opacity: 0; } }
}

/* ---------- sections: each opens a new system with a rehearsal mark ---------- */

.sheet { position: relative; z-index: 1; padding: 120px 0; background: var(--bg); }
.system { display: flex; align-items: center; gap: 16px; margin-bottom: 40px; }
.system b { display: grid; place-items: center; width: 32px; height: 32px; font: 400 14px/1 var(--mono); box-shadow: inset 0 0 0 1.5px var(--text); }
.system span { font: 400 14px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.system i { position: relative; flex: 1; height: 25px; }
.system i::before { content: ""; position: absolute; inset: 0; background: repeating-linear-gradient(to bottom, var(--staff) 0 1px, transparent 1px 6px); transform-origin: left; }
.system i::after { content: ""; position: absolute; left: 0; top: 0; width: 3px; height: 25px; background: var(--text); }
@supports (animation-timeline: view()) {
  .system i::before { animation: rule linear both; animation-timeline: view(); animation-range: entry 30% cover 35%; }
}
h2 { font: 500 36px/1.1 var(--display); max-width: 20ch; text-wrap: balance; }
.lede { margin-top: 24px; max-width: 62ch; font-size: 18px; color: var(--soft); text-wrap: pretty; }
@media (min-width: 48rem) { h2 { font-size: 48px; } }
@media (min-width: 64rem) { h2 { font-size: 60px; } }

/* premise: lyrics */
.premise { padding: 160px 0; }
.lyric { font: 500 36px/1.12 var(--display); max-width: 22ch; view-timeline: --lyric block; }
.lyric span { color: var(--staff); }
@supports (animation-timeline: view()) {
  .lyric span { animation: lit linear both; animation-timeline: --lyric; animation-range: cover calc(18% + var(--i) * 2.6%) cover calc(24% + var(--i) * 2.6%); }
  @keyframes lit { to { color: var(--text); } }
}
.premise .body { margin-top: 40px; max-width: 62ch; font-size: 18px; color: var(--soft); }
@media (min-width: 48rem) { .lyric { font-size: 48px; } }
@media (min-width: 64rem) { .lyric { font-size: 72px; } .premise .grid { display: grid; grid-template-columns: 8fr 4fr; gap: 64px; align-items: end; } .premise .body { margin-top: 0; } }

/* roles */
.roles { display: grid; gap: 48px; margin-top: 64px; }
.role { padding-top: 24px; border-top: 1px solid var(--staff); }
.role h3 { margin-top: 24px; font: 500 30px/1.2 var(--display); }
.role h3 small { display: block; margin-top: 8px; font: 400 16px/1.4 var(--body); color: var(--muted); }
.role p { margin-top: 16px; color: var(--soft); }
.role em { color: var(--text); }
@media (min-width: 52rem) { .roles { grid-template-columns: repeat(3, 1fr); } .role:nth-child(2) { margin-top: 48px; } .role:nth-child(3) { margin-top: 96px; } }

/* ---------- the loop: lights down, once round the ring ---------- */

.loop { padding-bottom: 0; }
.runway { height: calc(100vh + 6 * 60vh); view-timeline: --round block; }
.pin { position: sticky; top: 0; height: 100vh; display: grid; place-items: center; overflow: clip;
  animation: round steps(6, jump-none) both; animation-timeline: --round; animation-range: contain 4% contain 96%; }
@keyframes round { from { --step: 0; } to { --step: 5; } }
.ring { --size: min(70vh, 88vw, 640px); position: relative; width: var(--size); height: var(--size); margin-top: 48px; }
.ring > svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.track { fill: none; stroke: var(--staff); stroke-width: 0.25; }
.arc { fill: none; stroke: var(--accent); stroke-width: 0.5; stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--step) / 6); transform: rotate(-90deg); transform-origin: 50% 50%; transition: stroke-dashoffset 0.7s var(--house); }
.node { --a: calc(var(--i) * 60deg - 90deg); --on: clamp(0, var(--step) - var(--i) + 1, 1);
  position: absolute; left: 50%; top: 50%; width: 56px; height: 56px; margin: -28px 0 0 -28px; display: grid; place-items: center;
  transform: rotate(var(--a)) translateX(calc(var(--size) / 2)) rotate(calc(-1 * var(--a)));
  background: color-mix(in srgb, var(--accent) calc(var(--on) * 100%), var(--bg));
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--accent) calc(var(--on) * 100%), var(--staff)); transition: background-color 0.4s var(--house), box-shadow 0.4s var(--house); }
.node .ic { color: color-mix(in srgb, var(--on-accent) calc(var(--on) * 100%), var(--text)); }
.centre { position: absolute; inset: 16%; display: grid; place-items: center; margin: 0; padding: 0; list-style: none; text-align: center; }
.panel { grid-area: 1 / 1; display: grid; justify-items: center; gap: 16px;
  opacity: calc(clamp(0, var(--step) - var(--i) + 1, 1) * clamp(0, var(--i) + 1 - var(--step), 1)); transition: opacity 0.35s var(--house); }
.panel .count { font: 400 12px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.panel strong { font: 500 30px/1.1 var(--display); }
.panel > span:last-child { max-width: 24ch; font-size: 18px; color: var(--soft); text-wrap: balance; }
@media (min-width: 48rem) { .panel strong { font-size: 48px; } }
.cue-round { position: absolute; left: 50%; bottom: 24px; translate: -50% 0; white-space: nowrap; }
@media (max-width: 48rem) {
  .ring { --size: min(70vh, 80vw); }
  .centre { inset: 14%; }
  .panel { gap: 8px; }
  .panel > .ic { width: 48px; height: 48px; }
  .panel > span:last-child { max-width: 18ch; font-size: 16px; }
}
.verdict { padding: 64px 0 120px; color: var(--soft); }

/* ---------- tools ---------- */

.tools { display: grid; margin: 64px 0 0; }
.tools > div { display: grid; align-content: start; grid-template-columns: 24px minmax(0, 1fr); column-gap: 16px; padding: 24px 0; border-top: 1px solid var(--line); }
.tools .ic { grid-row: 1; align-self: center; }
.tools dt { grid-column: 2; }
.tools dd { grid-column: 2; }
.tools dt { font: 400 16px/1.5 var(--mono); color: var(--link); }
.tools dt code { font: inherit; }
.tools dd { margin: 8px 0 0; max-width: 46ch; color: var(--soft); }
@media (min-width: 52rem) { .tools { grid-template-columns: 1fr 1fr; column-gap: 80px; } }

/* ---------- quick start ---------- */

.start { display: grid; gap: 48px; align-items: start; }
.start > * { min-width: 0; }
@media (min-width: 64rem) { .start { grid-template-columns: 5fr 7fr; gap: 72px; } }
.codeblock { border: 1px solid var(--line); background: var(--surface); }
.codebar { display: flex; justify-content: space-between; align-items: center; padding: 10px 12px 10px 16px; border-bottom: 1px solid var(--line); color: var(--muted); font-size: 14px; }
.codebar > span, .copy { display: inline-flex; align-items: center; gap: 8px; }
.copy { font: inherit; font-size: 14px; color: var(--text); background: none; border: 1px solid var(--staff); padding: 8px 12px; cursor: pointer; }
.copy:hover { border-color: var(--text); }
.copy .i-check { display: none; }
.copy.done .i-copy { display: none; }
.copy.done .i-check { display: inline-block; }
pre { margin: 0; padding: 20px 16px 24px; overflow-x: auto; font: 400 16px/1.8 var(--mono); color: var(--soft); }
pre .c { color: var(--muted); }
pre .p { color: var(--link); }
.status { min-height: 1.6em; padding: 0 16px 12px; color: var(--muted); font-size: 14px; }

/* ---------- today ---------- */

.today h2 { font-size: 48px; max-width: 16ch; }
@media (min-width: 64rem) { .today h2 { font-size: 72px; } }
.today .actions { margin-top: 40px; }

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

.faq { margin: 56px 0 0; max-width: 72ch; }
.faq > div { padding: 24px 0; border-top: 1px solid var(--line); }
.faq dt { font: 500 24px/1.25 var(--display); }
.faq dd { margin: 12px 0 0; color: var(--soft); text-wrap: pretty; }
.faq a { color: var(--link); text-underline-offset: 0.2em; }

/* ---------- footer: the last bar ---------- */

.foot { position: relative; z-index: 1; padding: 120px 0 48px; background: var(--bg); --amp: 0; }
.coda { position: relative; height: 49px; }
.coda .strings { position: absolute; inset: 0 13px 0 0; }
.coda .string { height: 10px; }
.coda .string:nth-of-type(1) { top: -5px; } .coda .string:nth-of-type(2) { top: 7px; } .coda .string:nth-of-type(3) { top: 19px; } .coda .string:nth-of-type(4) { top: 31px; } .coda .string:nth-of-type(5) { top: 43px; }
.coda .string path { stroke-width: 1.5px; }
.coda .final { position: absolute; right: 0; top: 0; width: 13px; height: 49px; background: linear-gradient(to right, var(--text) 0 1.5px, transparent 0 5px, var(--text) 0); }
.coda .fine { position: absolute; right: 0; bottom: calc(100% + 12px); font: 400 italic 18px/1 var(--body); }
@supports (animation-timeline: view()) {
  .coda .strings { transform-origin: left; animation: rule linear both; animation-timeline: view(); animation-range: entry 10% cover 40%; }
  .coda .final, .coda .fine { animation: land linear both; animation-timeline: view(); animation-range: cover 35% cover 42%; }
  @keyframes land { from { opacity: 0; transform: translateY(-12px); } }
}
.foot-grid { display: grid; gap: 48px; margin-top: 56px; }
.foot-mark { font: 500 48px/1 var(--display); }
.foot nav { display: grid; gap: 32px; grid-template-columns: repeat(2, 1fr); }
.foot h3 { font: 400 12px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.foot ul { margin: 16px 0 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.foot li a { display: inline-flex; align-items: center; gap: 8px; text-decoration: none; }
.foot li a span { text-decoration: underline; text-decoration-color: var(--staff); text-underline-offset: 0.2em; }
.foot li a:hover span { text-decoration-color: var(--text); }
.fineprint { display: grid; gap: 16px; margin-top: 64px; padding-top: 24px; border-top: 1px solid var(--line); color: var(--muted); }
.fineprint a { color: var(--soft); text-underline-offset: 0.2em; }
@media (min-width: 48rem) { .foot-mark { font-size: 60px; } .foot nav { grid-template-columns: repeat(3, 1fr); } .fineprint { grid-template-columns: 1fr 1fr; gap: 48px; } }
@media (min-width: 64rem) { .foot-mark { font-size: 72px; } .foot-grid { grid-template-columns: 5fr 7fr; align-items: end; } }

/* ---------- hero line, outside the h1 so the h1 is the name alone ---------- */
@media (max-width: 63.99rem) { .hero .line { margin-top: 40px; } }

/* ---------- what it is: the answer beside the facts ---------- */
.split { display: grid; gap: 48px; }
@media (min-width: 64rem) { .split { grid-template-columns: 1fr 1fr; gap: 80px; align-items: start; } }
.facts { margin: 0; border-top: 1px solid var(--text); }
.facts > div { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.facts dt { padding-top: 4px; font: 400 12px/1.6 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.facts dd { margin: 0; }
.facts a { color: var(--link); text-underline-offset: 0.2em; overflow-wrap: anywhere; }

/* ---------- capabilities: the name, how, and on what ---------- */
.tools dt { font: 500 24px/1.2 var(--display); color: var(--text); }
.tools dd code { font-family: var(--mono); color: var(--link); }
.tools .tech { display: block; margin-top: 8px; font-family: var(--mono); color: var(--muted); }

/* ---------- the setlist ---------- */
.setlist { margin: 56px 0 0; padding: 0; list-style: none; border-top: 1px solid var(--text); }
.setlist a { display: grid; grid-template-columns: 48px minmax(0, 1fr) auto 20px; align-items: center; gap: 16px; padding: 24px 12px; border-bottom: 1px solid var(--line); text-decoration: none;
  background: linear-gradient(var(--accent), var(--accent)) no-repeat left / 0% 100%; transition: background-size 0.5s var(--house), color 0.3s var(--house); }
.setlist a:hover, .setlist a:focus-visible { background-size: 100% 100%; color: var(--on-accent); }
.setlist .no { font: 400 14px/1 var(--mono); color: var(--muted); }
.setlist .title { font: 500 30px/1.15 var(--display); }
.setlist .where { font: 400 12px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.setlist a:hover :is(.no, .where), .setlist a:focus-visible :is(.no, .where) { color: var(--on-accent); }
@media (min-width: 64rem) { .setlist .title { font-size: 36px; } }
@media (max-width: 48rem) { .setlist a { grid-template-columns: 32px minmax(0, 1fr) 20px; } .setlist .where { display: none; } .setlist .title { font-size: 24px; } }

/* ---------- need and install ---------- */
.start h2 { font-size: 36px; }
@media (min-width: 64rem) { .start { grid-template-columns: 1fr 1fr; } .start h2 { font-size: 48px; } }
.needs { margin: 32px 0 0; padding: 0; list-style: none; border-top: 1px solid var(--text); }
.needs li { padding: 12px 0; border-bottom: 1px solid var(--line); }
.start .codeblock { margin-top: 32px; }
.then { margin-top: 16px; color: var(--soft); }
.then a { color: var(--link); text-underline-offset: 0.2em; }

/* ---------- compared ---------- */
.compare { width: 100%; margin-top: 48px; border-collapse: collapse; }
.compare th, .compare td { padding: 16px 24px 16px 0; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
.compare thead :is(th, td) { padding-top: 0; font: 400 12px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); border-bottom: 1px solid var(--text); }
.compare thead th:nth-child(2) { color: var(--text); }
.compare tbody th { width: 22%; font: 500 20px/1.3 var(--display); }
.compare tbody td:nth-child(2) { color: var(--text); }
.compare tbody td:nth-child(3) { color: var(--muted); }


/* ---------- skip link ---------- */
.skip { position: absolute; z-index: 40; left: 16px; top: -64px; padding: 12px 16px; background: var(--text); color: var(--bg); text-decoration: none; }
.skip:focus { top: 16px; }
