/* qkvm.com and docs.qkvm.com.
   Clean, with much air: one typeface for the text (QKVM Sans) and a console typeface for what is
   typed or measured (QKVM Mono), one accent colour, and the colours of the program where they mean
   what they mean in it (green is online, amber has no signal, red is offline). The pictures are
   the program itself, taken from the demo. What moves, moves quietly, and for everybody. Pointed
   at, a thing changes its colour and nothing else. Light, dark, or as the device is set. Nothing
   is loaded from elsewhere: the typefaces are in fonts/, the pictures in shots/. */

@font-face { font-family: "QKVM Sans"; src: url("fonts/qkvm-sans-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "QKVM Sans"; src: url("fonts/qkvm-sans-700.woff2") format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "QKVM Sans"; src: url("fonts/qkvm-sans-900.woff2") format("woff2"); font-weight: 900; font-display: swap; }
@font-face { font-family: "QKVM Mono"; src: url("fonts/qkvm-mono-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "QKVM Mono"; src: url("fonts/qkvm-mono-600.woff2") format("woff2"); font-weight: 600; font-display: swap; }
@font-face { font-family: "QKVM Mono"; src: url("fonts/qkvm-mono-700.woff2") format("woff2"); font-weight: 700; font-display: swap; }

/* --- colours: light, and dark for a device set to dark or a reader who chose it --- */

:root {
  color-scheme: light;
  --bg: #ffffff;
  --bg-soft: #f5f6f8;
  --panel: #ffffff;
  --line: #e6e8ec;
  --line-strong: #d0d4db;
  --text: #1b1d21;
  --muted: #555b64;
  --faint: #868c96;
  --accent: #0b6bff;
  --accent-hover: #0a5ee0;
  --accent-text: #0a62e8;
  --accent-soft: rgba(11, 107, 255, .08);
  --ok: #17885a;
  --warn: #a86400;
  --bad: #c43838;
  --code-bg: #f3f5f8;
  --code-text: #17202b;
  --shadow: 0 1px 2px rgba(16, 28, 54, .05), 0 24px 48px -24px rgba(16, 42, 92, .28);
  --lift: 0 60px 90px -50px rgba(16, 42, 92, .45), 0 18px 36px -18px rgba(16, 42, 92, .25);
  --grid: rgba(15, 22, 32, .05);
  --glow: rgba(11, 107, 255, .10);
  --art: #a9ccff;
  --bezel: #0c0d10;
  --screen: #f1f3f7;
  --bezel-edge: #2b2e34;
  --light-only: block;
  --dark-only: none;
  --radius: 10px;
  --max: 1200px;
  --sans: "QKVM Sans", system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: "QKVM Mono", ui-monospace, "Cascadia Mono", "SF Mono", Consolas, Menlo, monospace;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #08090b;
    --bg-soft: #0e1014;
    --panel: #131519;
    --line: #1d2026;
    --line-strong: #2d3139;
    --text: #f3f4f6;
    --muted: #a3a9b3;
    --faint: #6b727d;
    --accent: #3d86ff;
    --accent-hover: #5c9bff;
    --accent-text: #7fb1ff;
    --accent-soft: rgba(77, 148, 255, .13);
    --ok: #3fcf8e;
    --warn: #f0b44a;
    --bad: #ff6b6b;
    --code-bg: #0f1217;
    --code-text: #dbe4f0;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 24px 48px -20px rgba(0, 0, 0, .7);
    --lift: 0 70px 120px -50px rgba(0, 0, 0, .9), 0 0 120px -30px rgba(77, 148, 255, .28);
    --grid: rgba(233, 237, 243, .045);
    --glow: rgba(77, 148, 255, .14);
    --art: #1e4f9e;
    --bezel: #16181c;
    --screen: #0a0f18;
    --bezel-edge: #3a3e46;
    --light-only: none;
    --dark-only: block;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #08090b;
  --bg-soft: #0e1014;
  --panel: #131519;
  --line: #1d2026;
  --line-strong: #2d3139;
  --text: #f3f4f6;
  --muted: #a3a9b3;
  --faint: #6b727d;
  --accent: #3d86ff;
  --accent-hover: #5c9bff;
  --accent-text: #7fb1ff;
  --accent-soft: rgba(77, 148, 255, .13);
  --ok: #3fcf8e;
  --warn: #f0b44a;
  --bad: #ff6b6b;
  --code-bg: #0f1217;
  --code-text: #dbe4f0;
  --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 24px 48px -20px rgba(0, 0, 0, .7);
  --lift: 0 70px 120px -50px rgba(0, 0, 0, .9), 0 0 120px -30px rgba(77, 148, 255, .28);
  --grid: rgba(233, 237, 243, .045);
  --glow: rgba(77, 148, 255, .14);
  --art: #1e4f9e;
  --bezel: #16181c;
  --screen: #0a0f18;
  --bezel-edge: #3a3e46;
  --light-only: none;
  --dark-only: block;
}

/* --- the page --- */

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 76px; -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--text); font: 400 16px/1.6 var(--sans); -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; overflow-x: hidden; }
img, svg { display: block; }
a { color: var(--accent-text); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
h1, h2, h3, p { margin: 0; }
code, pre, kbd { font-family: var(--mono); }
.wrap { width: min(var(--max), 100% - 48px); margin-inline: auto; }
.wrap.narrow { width: min(820px, 100% - 48px); }
.skip { position: absolute; left: -9999px; }
.skip:focus { left: 16px; top: 12px; z-index: 30; padding: 8px 14px; background: var(--accent); color: #fff; border-radius: 8px; }
svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
svg.fill { fill: currentColor; stroke: none; }

/* --- top bar --- */

.nav { position: sticky; top: 0; z-index: 20; border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--bg) 84%, transparent); backdrop-filter: saturate(1.6) blur(14px); -webkit-backdrop-filter: saturate(1.6) blur(14px); transition: box-shadow .3s ease; }
.nav.scrolled { box-shadow: 0 10px 30px -22px rgba(16, 28, 54, .5); }
.nav .wrap { display: flex; align-items: center; gap: 18px; height: 56px; transition: height .3s ease; }
/* Once the page has moved under it, the bar draws in a little. */
.nav.scrolled .wrap { height: 50px; }
.brand { display: inline-flex; align-items: center; gap: 9px; color: var(--text); font-size: 17px; font-weight: 900; letter-spacing: .03em; text-decoration: none; }
.nav nav { position: relative; display: flex; align-self: stretch; align-items: center; gap: 2px; margin-left: 18px; margin-right: auto; }
/* The link of the part of the page that is on show is marked, and the mark slides from one link to the
   next. (Made by the script, which says where it lies and how wide: --x, --w.) */
.nav nav .spot { position: absolute; left: 0; bottom: -1px; width: 1px; height: 2px; border-radius: 2px; background: var(--accent); opacity: 0; transform-origin: 0 50%; transform: translateX(var(--x, 0px)) scaleX(var(--w, 1)); transition: transform .45s cubic-bezier(.3, .7, .2, 1), opacity .3s ease; pointer-events: none; }
.nav nav .spot.on { opacity: 1; }
.nav nav a[aria-current="true"] { color: var(--accent-text); }
.nav nav a { display: inline-flex; align-items: center; gap: 5px; padding: 6px 11px; border-radius: 6px; color: var(--text); font-size: 15px; text-decoration: none; white-space: nowrap; transition: color .2s ease, background .2s ease; }
.nav nav a:hover { color: var(--accent-text); background: var(--accent-soft); }
/* A link that leads to another of the sites says so with a small mark (and in words, for whoever hears the page). */
.nav nav a .out { width: 12px; height: 12px; stroke-width: 2; color: var(--faint); transition: color .2s ease; }
.nav nav a:hover .out { color: currentColor; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.nav .wrap > .icon, .social a { display: grid; place-items: center; width: 34px; height: 34px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--muted); transition: color .2s ease, border-color .2s ease; }
.nav .wrap > .icon:hover, .social a:hover { border-color: var(--line-strong); color: var(--text); }
.nav .wrap > .icon, .nav .wrap > .btn { margin-left: -8px; }
.nav .wrap > .icon svg, .social svg { width: 17px; height: 17px; }
@media (max-width: 900px) { .nav nav .wide { display: none; } .nav nav { margin-left: 0; } }
@media (max-width: 640px) { .nav .btn.small { display: none; } }
@media (max-width: 520px) { .nav .wrap > a.icon, .nav nav .mid { display: none; } .nav .wrap { gap: 10px; } }

/* Light, dark, or as the device is set: one button, which shows the one that is chosen and goes on to the
   next when pressed. Shown once the script that works it has run. */
.theme { position: relative; padding: 0; cursor: pointer; font: inherit; }
.nav .wrap > .theme[hidden] { display: none; }
/* Its three pictures lie one over the other. The one that is chosen turns into place, the one before turns away. */
.theme svg { position: absolute; inset: 0; margin: auto; opacity: 0; transform: rotate(-120deg) scale(.3); transition: transform .55s cubic-bezier(.3, 1.35, .5, 1), opacity .25s ease; }
:root[data-theme-choice="system"] .theme .as-system, :root[data-theme-choice="light"] .theme .as-light, :root[data-theme-choice="dark"] .theme .as-dark { opacity: 1; transform: none; }
.theme:active { transform: scale(.92); }
/* And the page changes its colours from that button outwards, where the browser can show one state of a
   page turning into another; elsewhere every colour goes over into the next. (--from-x, --from-y, --reach:
   where the button is and how far the farthest corner, set by the script as it is pressed.) */
::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
::view-transition-new(root) { animation: spread .6s cubic-bezier(.45, 0, .2, 1) both; }
@keyframes spread { from { clip-path: circle(0 at var(--from-x, 50%) var(--from-y, 0)); } to { clip-path: circle(var(--reach, 150vmax) at var(--from-x, 50%) var(--from-y, 0)); } }
.theming, .theming *, .theming *::before, .theming *::after { transition: background-color .4s ease, color .4s ease, border-color .4s ease, fill .4s ease, stroke .4s ease, box-shadow .4s ease !important; }

/* --- buttons and links that lead on --- */

.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 46px; padding: 0 24px; border: 1px solid var(--line-strong); border-radius: 999px; background: var(--panel); color: var(--text); font: 700 15.5px var(--sans); text-decoration: none; white-space: nowrap; transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease, background .2s ease; }
/* Pointed at, a button changes its colour and nothing else: it does not rise, and casts no shadow. */
.btn:hover { border-color: var(--text); background: var(--bg-soft); }
.btn.primary { border-color: var(--accent); background: var(--accent); color: #fff; }
.btn.primary:hover { border-color: var(--accent-hover); background: var(--accent-hover); }
.btn:active { transform: scale(.98); }
.btn.small { height: 32px; padding: 0 15px; border-radius: 6px; font-size: 14px; }
.btn svg { width: 17px; height: 17px; stroke-width: 2; transition: transform .25s ease; }
.btn:hover svg { transform: translateX(3px); }
.more { display: inline-flex; align-items: center; gap: .4em; font-size: 15.5px; font-weight: 700; text-decoration: none; }
.more svg { width: 16px; height: 16px; stroke-width: 2.2; transition: transform .2s ease; }
.more:hover svg { transform: translateX(3px); }
.after.links { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px 32px; }
.cta { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px 14px; }

/* --- pills: a row of choices, one of which is shown --- */

.pills { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 12px; }
.pill { position: relative; display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 17px; border: 1px solid var(--line-strong); border-radius: 999px; background: color-mix(in srgb, var(--bg) 82%, transparent); color: var(--muted); font: 400 15px var(--sans); white-space: nowrap; cursor: pointer; transition: color .25s ease, border-color .25s ease, box-shadow .25s ease, background .25s ease; }
.pill:hover { border-color: var(--faint); color: var(--text); }
.pill svg { width: 15px; height: 15px; stroke-width: 1.8; }
.pill[aria-selected="true"] { border-color: var(--accent); color: var(--accent-text); box-shadow: 0 0 0 1px var(--accent); background: var(--bg); }
.pill em { padding: 1px 7px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-text); font-size: 11.5px; font-style: normal; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
/* While the pictures change by themselves, the chosen pill shows how long the one on show stays: its
   outline is drawn round it once in that time. (--lap is an angle, so that it can be counted up.) */
@property --lap { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.pills.auto .pill[aria-selected="true"] { border-color: var(--line-strong); box-shadow: none; }
.pills.auto .pill[aria-selected="true"]::after { content: ""; position: absolute; inset: -1px; padding: 2px; border-radius: inherit; background: conic-gradient(var(--accent) var(--lap), transparent 0); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); pointer-events: none; animation: lap var(--dwell, 7s) linear both; }
@keyframes lap { from { --lap: 0deg; } to { --lap: 360deg; } }

/* --- the first screen --- */

.hero { position: relative; padding: 44px 0 0; text-align: center; overflow: hidden; }
.hero h1 { font-size: clamp(30px, 4.3vw, 46px); font-weight: 700; line-height: 1.14; letter-spacing: -.012em; text-wrap: balance; }
/* Its words arrive one after the other, then what is under it. */
.hero h1 span { display: inline-block; animation: rise .8s cubic-bezier(.2, .7, .2, 1) both; }
.hero h1 span:nth-child(2) { animation-delay: .06s; }
.hero h1 span:nth-child(3) { animation-delay: .12s; }
.hero h1 span:nth-child(4) { animation-delay: .18s; }
.hero h1 span:nth-child(5) { animation-delay: .24s; }
.hero h1 span:nth-child(6) { animation-delay: .34s; }
.lede { max-width: 76ch; margin: 14px auto 0; color: var(--muted); font-size: clamp(16px, 1.5vw, 18px); line-height: 1.55; text-wrap: pretty; animation: rise .8s .36s cubic-bezier(.2, .7, .2, 1) both; }
.hero .pills { margin-top: 26px; animation: rise .8s .44s cubic-bezier(.2, .7, .2, 1) both; }
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* Behind the display: what the view on show is about, drawn as a plan on the floor, seen from above. One
   drawing for each view (the wall's tiles, a few lit; the one machine, large; the ticked ones and the one
   thing done to them; servers as they lie in a rack; the days, with what was read over them), and the one whose
   view is on show is the one to be seen. Drawn by the script (it is decoration: without it there is the
   light alone). */
.floor { position: relative; z-index: 0; width: min(1320px, 100%); height: clamp(120px, 19vw, 250px); margin: 26px auto clamp(-112px, -8.6vw, -52px); pointer-events: none;
         background: radial-gradient(48% 90% at 50% 100%, var(--glow), transparent 78%);
         -webkit-mask-image: radial-gradient(ellipse 58% 115% at 50% 100%, #000 42%, transparent 92%); mask-image: radial-gradient(ellipse 58% 115% at 50% 100%, #000 42%, transparent 92%); }
.floor svg { position: absolute; inset: 0; width: 100%; height: 100%; stroke: none; opacity: 0; transform: translateY(12px); transition: opacity .7s ease, transform .9s cubic-bezier(.2, .7, .2, 1); }
.floor svg.on { opacity: 1; transform: none; }
.floor .cell { fill: var(--accent-soft); stroke: var(--art); stroke-width: 1.4; stroke-linejoin: round; transition: fill .7s ease, stroke .7s ease; }
/* Now and then one more of them lights for a moment (the script chooses which). */
.floor .cell.on { fill: color-mix(in srgb, var(--accent) 24%, transparent); stroke: var(--accent); }
.floor .lit { fill: color-mix(in srgb, var(--accent) 22%, transparent); stroke: var(--accent); stroke-width: 1.6; stroke-linejoin: round; animation: lit 5.6s ease-in-out infinite; }
.floor .node { fill: var(--bg); stroke: var(--accent); stroke-width: 2; animation: lit 5.6s ease-in-out infinite; }
.floor .d1 { animation-delay: -.8s; } .floor .d2 { animation-delay: -1.9s; } .floor .d3 { animation-delay: -3.1s; } .floor .d4 { animation-delay: -4.2s; }
.floor .cell.far { opacity: .5; }
.floor .glass { fill: color-mix(in srgb, var(--accent) 9%, transparent); stroke: var(--accent); stroke-width: 1.1; stroke-linejoin: round; }
.floor .mark, .floor .tick, .floor .wire, .floor .vent, .floor .ring { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.floor .mark { stroke: var(--accent); stroke-width: 2.2; }
.floor .tick { stroke: var(--accent); stroke-width: 2.4; animation: lit 5.6s ease-in-out infinite; }
/* (What is done to the ticked ones runs along their lines to the one place it is done from.) */
.floor .wire { stroke: var(--accent); stroke-width: 1.1; stroke-dasharray: 3 7; opacity: .55; animation: flow 1.4s linear infinite; }
@keyframes flow { to { stroke-dashoffset: -20; } }
.floor .vent { stroke: var(--art); stroke-width: 1.3; }
.floor .ring { stroke: var(--art); stroke-width: 1.4; }
.floor .ring.near { stroke: var(--accent); opacity: .7; }
.floor .node.off { stroke: var(--art); animation: none; }
/* (What the wall read of a machine over the days runs across them, drawn anew each time its view comes.) */
.floor .trace { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.floor .trace.second { stroke: var(--art); stroke-width: 1.6; }
.floor svg.on .trace { animation: draw 2.4s .25s cubic-bezier(.4, 0, .2, 1) forwards; }
.floor svg.on .trace.second { animation-delay: .6s; }
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes lit { 0%, 100% { opacity: .28; } 45%, 60% { opacity: 1; } }

/* The program, as large as the page allows, in a display. Its pictures are the real page. */
.stage { position: relative; z-index: 1; width: min(1200px, 100% - 48px); margin: 0 auto; animation: arrive 1.1s .4s cubic-bezier(.2, .7, .2, 1) both; }
@keyframes arrive { from { opacity: 0; transform: translateY(34px) scale(.985); } to { opacity: 1; transform: none; } }
.display { position: relative; padding: clamp(5px, .9vw, 11px); border-radius: clamp(14px, 2.2vw, 26px); background: var(--bezel); box-shadow: inset 0 0 0 1.5px var(--bezel-edge), var(--lift); }
/* Light passes over its glass, once, as it has arrived. */
.display::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: linear-gradient(105deg, transparent 45.5%, rgba(255, 255, 255, .16) 50%, transparent 54.5%) no-repeat; background-size: 260% 100%; background-position: 160% 0; pointer-events: none; animation: sheen 1.5s 1.5s cubic-bezier(.3, .5, .3, 1) both; }
@keyframes sheen { from { background-position: 160% 0; } to { background-position: -60% 0; } }
/* (Behind its pictures the screen has the page's own shade: a view that leaves fades into that, and not into the dark.) */
.screen { position: relative; overflow: hidden; aspect-ratio: 1600 / 962; border-radius: clamp(8px, 1.3vw, 15px); background: var(--screen); isolation: isolate; }
/* (isolation: what lies over what inside a screen stays inside it. Without it the picture that comes up over
   the one before, which is one layer higher, also lay over the small window in front of the display.) */
/* The display is taken by the hand too: pulled to one side, it goes on to the next view or back to the
   one before. (Up and down stays the page's own: it is scrolled.) */
.display .screen { cursor: grab; touch-action: pan-y; }
.display .screen.pulled { cursor: grabbing; }
.display .screen img { -webkit-user-drag: none; user-select: none; }
/* One view gives way to another like a slide: the new one comes in from the side its pill is on, and the
   old one leaves by the other, more slowly and fading, as if it lay behind. */
.view { position: absolute; inset: 0; transition: transform .85s cubic-bezier(.62, .02, .18, 1), opacity .85s ease, translate .35s ease; }
.screen.pulled .view { transition: none; }
.view[hidden] { display: none; }
.view.out { opacity: 0; }
.view.enter-right { transform: translateX(100%); }
.view.enter-left { transform: translateX(-100%); }
.view.leave-left { transform: translateX(-32%); opacity: 0; }
.view.leave-right { transform: translateX(32%); opacity: 0; }
/* (isolation: the picture that comes up lies over the one before of the same view, and over nothing else.
   One layer higher in the whole screen, it left the one before under whatever else was in that screen.) */
.frames { position: absolute; inset: 0; isolation: isolate; }
.frames.light { display: var(--light-only); }
.frames.dark { display: var(--dark-only); }
/* The pictures of a view follow each other like a wall that refreshes. The new one comes up over the one
   before, which stays as it is until it is covered. (Both fading at once, the one out and the other in,
   let the screen behind them show through for a moment: the picture grew dark at every beat.) */
.frames img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 0 0; opacity: 0; }
.frames img:first-child, .frames img.was { opacity: 1; }
/* (Quickly: a wall puts the new picture in the old one's place. Half a second and more of two terminals shown
   through each other was most of the time between two beats.) */
.frames img.is { z-index: 1; opacity: 1; animation: come-up .32s ease both; }
.frames.cycling img:first-child:not(.is):not(.was) { opacity: 0; }
@keyframes come-up { from { opacity: 0; } }
/* A second, smaller window over its corner: one machine enlarged, or what is asked before an action. */
.float { position: absolute; z-index: 2; right: -7.6%; bottom: -3.4%; width: 41.6%; padding: 7px; border-radius: 16px; background: var(--bezel); box-shadow: inset 0 0 0 1.5px var(--bezel-edge), 0 40px 70px -30px rgba(6, 18, 44, .65); transition: opacity .5s ease, transform .6s cubic-bezier(.2, .7, .2, 1); will-change: transform; }
.float .screen { aspect-ratio: 1600 / 940; border-radius: 10px; background: #0a0f18; }
.float.away { opacity: 0; transform: translateY(14px) scale(.98); }
@media (max-width: 1340px) { .float { right: -12px; } }
@media (max-width: 860px) { .float { display: none; } }

.under { padding: 38px 0 64px; }
.says { max-width: 62ch; margin: 0 auto; color: var(--muted); font-size: 17px; text-wrap: balance; }
.says[hidden] { display: none; }
.under .cta { margin-top: 26px; }
.fine { margin-top: 18px; color: var(--faint); font-size: 13.5px; }
/* The version, which leads to its release notes. */
.fine .release { display: inline-flex; align-items: center; gap: 4px; color: var(--muted); font-weight: 700; text-decoration: none; transition: color .2s ease; }
.fine .release:hover { color: var(--accent-text); }
.fine .release svg { width: 11px; height: 11px; stroke-width: 2.2; }
.proof { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; gap: 10px 36px; padding: 46px 0 0; }
.proof p { color: var(--faint); font: 600 11.5px var(--mono); letter-spacing: .12em; text-transform: uppercase; }
.proof ul { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 34px; margin: 0; padding: 0; list-style: none; }
.proof li { color: var(--muted); font-size: 17px; font-weight: 700; }

/* --- the sections under it --- */

.band { padding: clamp(72px, 9vw, 112px) 0; text-align: center; }
.band.soft { background: var(--bg-soft); }
.band h2 { max-width: 24ch; margin-inline: auto; font-size: clamp(28px, 3.7vw, 42px); font-weight: 700; line-height: 1.14; letter-spacing: -.012em; text-wrap: balance; }
.intro { max-width: 62ch; margin: 16px auto 0; color: var(--muted); font-size: 17.5px; text-wrap: pretty; }
.band .pills { margin-top: 28px; }
.after { margin-top: 30px; }
.not-yet { max-width: 76ch; margin-inline: auto; color: var(--muted); font-size: 15px; line-height: 1.6; }
.not-yet b { color: var(--text); font-weight: 700; }

/* A large soft panel: words on one side, the program on the other, running off its edge. */
.panel { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: center; gap: clamp(28px, 4vw, 56px); margin-top: 44px; padding: clamp(32px, 4.6vw, 60px) 0 clamp(32px, 4.6vw, 60px) clamp(26px, 4.6vw, 64px); overflow: hidden; border-radius: 24px; background: var(--bg-soft); text-align: left; transition: opacity .5s ease; }
.band.soft .panel { background: var(--panel); }
.panel[hidden] { display: none; }
/* What a row of pills chooses between lies in one place, one over the other: the page keeps its height
   while one gives way to the next (side by side in the flow for that moment, it jumped). They move a
   little the same way the views above do. */
.deck { display: grid; }
.deck > * { grid-area: 1 / 1; min-width: 0; transition: transform .6s cubic-bezier(.3, .7, .2, 1), opacity .5s ease; }
.deck > .out { opacity: 0; }
.deck > .enter-right, .deck > .leave-right { transform: translateX(56px); opacity: 0; }
.deck > .enter-left, .deck > .leave-left { transform: translateX(-56px); opacity: 0; }
.panel h3 { font-size: clamp(24px, 2.6vw, 31px); font-weight: 700; line-height: 1.2; letter-spacing: -.01em; }
.panel p { margin-top: 14px; color: var(--muted); font-size: 17px; text-wrap: pretty; }
.ticks { display: grid; gap: 9px; margin: 22px 0 0; padding: 0; list-style: none; color: var(--muted); font-size: 15px; }
.ticks li { position: relative; padding-left: 20px; }
.ticks li::before { content: ""; position: absolute; left: 2px; top: .62em; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.ticks b { margin-right: 6px; color: var(--text); font-weight: 700; }
/* (--drift: it moves a little slower than the page, as something nearer does. Set by the script.) */
.shot { position: relative; aspect-ratio: 1600 / 962; overflow: hidden; border: 1px solid var(--line); border-right: 0; border-radius: 14px 0 0 14px; background: var(--screen); box-shadow: var(--shadow); translate: 0 var(--drift, 0px); }
@media (max-width: 900px) {
  .panel { grid-template-columns: 1fr; padding-right: clamp(26px, 4.6vw, 64px); }
  .shot { border-right: 1px solid var(--line); border-radius: 12px; }
}

/* What somebody gets: said large, then how. */
.answer { max-width: 820px; margin: 42px auto 0; }
.answer[hidden] { display: none; }
.answer h3 { color: var(--ok); font-size: clamp(24px, 3vw, 34px); font-weight: 700; line-height: 1.2; letter-spacing: -.01em; text-wrap: balance; }
.answer p { margin-top: 16px; color: var(--muted); font-size: 17.5px; text-wrap: pretty; }

.cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 48px; text-align: left; }
.cards article { padding: 26px; border-radius: 18px; background: var(--bg-soft); transition: background .3s ease; }
.band.soft .cards article { background: var(--panel); }
.cards article:hover { background: color-mix(in srgb, var(--bg-soft) 90%, var(--text)); }
.cards svg { width: 26px; height: 26px; color: var(--accent); }
/* Their pictures are drawn as they arrive: each line along its own length, which the script measures
   (--len; where it has not, the picture is simply there). */
.js .cards .reveal svg > * { stroke-dasharray: var(--len); stroke-dashoffset: var(--len); }
.js .cards .reveal.in svg > * { stroke-dashoffset: 0; transition: stroke-dashoffset 1.1s cubic-bezier(.4, 0, .2, 1); transition-delay: calc(var(--wait, 0s) + .3s); }
.cards h3 { margin-top: 18px; font-size: 17.5px; font-weight: 700; }
.cards p { margin-top: 8px; color: var(--muted); font-size: 15px; line-height: 1.6; }
@media (max-width: 1080px) { .cards { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .cards { grid-template-columns: 1fr; } }

/* What comes next, in the order it is being worked on. */
.road { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; max-width: 1000px; margin: 48px auto 0; padding: 0; list-style: none; text-align: left; }
.road li { padding: 24px 22px; border-radius: 18px; background: var(--panel); transition: background .3s ease; }
.road li:hover { background: color-mix(in srgb, var(--panel) 94%, var(--text)); }
.road h3 { margin-top: 16px; font-size: 17.5px; font-weight: 700; line-height: 1.3; }
.road p { margin-top: 8px; color: var(--muted); font-size: 14.5px; line-height: 1.55; }
.when { display: inline-block; padding: 3px 10px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-text); font: 600 11px var(--mono); letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; }
.when.now { position: relative; padding-left: 23px; background: var(--accent); color: #fff; }
/* What is there today has a light that beats, like a machine that is on. */
.when.now::before, .when.now::after { content: ""; position: absolute; left: 10px; top: 50%; width: 6px; height: 6px; margin-top: -3px; border-radius: 50%; background: #fff; }
.when.now::after { animation: beat 2.4s cubic-bezier(0, 0, .2, 1) infinite; }
@keyframes beat { 0% { transform: scale(1); opacity: .75; } 70%, 100% { transform: scale(3.2); opacity: 0; } }
@media (max-width: 760px) { .road { grid-template-columns: 1fr; } }

/* --- install --- */

.term { max-width: 760px; margin: 40px auto 0; text-align: left; }
.tabs { display: inline-flex; gap: 2px; padding: 2px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-soft); }
.tabs[hidden] { display: none; }
.tabs button { padding: 6px 14px; border: 0; border-radius: 6px; background: none; color: var(--muted); font: 700 14px var(--sans); cursor: pointer; }
.tabs button[aria-selected="true"] { background: var(--panel); color: var(--text); box-shadow: 0 0 0 1px var(--line-strong); }
pre { position: relative; margin: 12px 0 0; padding: 16px 18px; overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--code-bg); color: var(--code-text); font-size: 14px; line-height: 1.75; text-align: left; }
pre[hidden] { display: none; }
pre .cmd::before { content: "$ "; color: var(--faint); user-select: none; }
pre .note { color: var(--faint); transition: opacity .5s ease; }
/* The commands are typed once, as the terminal comes into view; what is said about them comes after. */
pre .cmd.typing::after { content: ""; display: inline-block; width: .55em; height: 1.1em; margin-left: 2px; vertical-align: text-bottom; background: var(--accent); animation: caret .9s steps(1) infinite; }
@keyframes caret { 50% { opacity: 0; } }
pre.being-typed .note { opacity: 0; }
pre .note::before { content: "# "; }
pre .copy { position: absolute; top: 9px; right: 9px; padding: 4px 10px; border: 1px solid var(--line-strong); border-radius: 6px; background: var(--panel); color: var(--muted); font: 700 12px var(--sans); cursor: pointer; }
pre .copy:hover { color: var(--text); border-color: var(--faint); }
:not(pre) > code { padding: 2px 6px; border: 1px solid var(--line); border-radius: 5px; background: var(--code-bg); font-size: .9em; }
.steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; max-width: 980px; margin: 40px auto 0; padding: 0; list-style: none; counter-reset: step; text-align: left; }
.steps li { padding: 0 22px 0 0; color: var(--muted); font-size: 15px; line-height: 1.55; counter-increment: step; }
.steps li::before { content: counter(step); display: grid; place-items: center; width: 28px; height: 28px; margin-bottom: 12px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-text); font: 700 13px var(--mono); }
.steps strong { display: block; color: var(--text); font-weight: 700; }
@media (max-width: 760px) { .steps { grid-template-columns: 1fr 1fr; gap: 24px 0; } }

.limits { margin: 34px 0 0; padding: 0 0 0 20px; color: var(--muted); font-size: 15.5px; line-height: 1.65; text-align: left; }
.limits li { margin: 10px 0; }

.closing .cta { margin-top: 30px; }

/* --- what comes into view: it arrives, once --- */

.js .reveal { opacity: 0; transform: translateY(20px); }
.js .reveal.in { opacity: 1; transform: none; transition: opacity .8s ease, transform .8s cubic-bezier(.2, .7, .2, 1); transition-delay: var(--wait, 0s); }

/* Where the script does not run, nothing can be chosen: the rows of pills go, and what they choose between
   is shown in full, one under the other. (The display keeps its first picture, the wall.) */
html:not(.js) .pills { display: none; }
html:not(.js) .deck { display: block; }
html:not(.js) .panel[hidden] { display: grid; }
html:not(.js) .answer[hidden] { display: block; }
/* There each answer says what it answers, which the pill said. */
.answer .asks { margin: 0 0 10px; color: var(--faint); font: 700 12px var(--mono); letter-spacing: .12em; text-transform: uppercase; }
.js .asks { display: none; }

/* --- the foot of the page, laid out as on the other sites of the house --- */

.foot { border-top: 1px solid var(--line); background: var(--bg-soft); color: var(--muted); font-size: 14.5px; }
.foot-top { display: grid; grid-template-columns: minmax(0, 2.2fr) repeat(4, minmax(0, 1fr)); gap: 40px 32px; padding: 56px 0 46px; }
.foot-brand p { max-width: 36ch; margin-top: 14px; line-height: 1.6; }
.foot-brand .social { display: flex; gap: 8px; margin-top: 18px; }
.foot nav { display: grid; align-content: start; gap: 11px; }
.foot h3 { margin-bottom: 5px; color: var(--text); font-size: 11.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.foot nav a { color: var(--muted); text-decoration: none; }
.foot nav a:hover { color: var(--text); }
.foot-legal { padding: 24px 0 30px; border-top: 1px solid var(--line); font-size: 12.5px; line-height: 1.6; }
.foot-legal > div { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 24px; margin-top: 18px; }
.foot-legal a { color: inherit; text-decoration: none; }
.foot-legal a:hover { color: var(--text); }
.foot-legal b { font-weight: 700; white-space: nowrap; }
.foot-legal ul { display: flex; flex-wrap: wrap; gap: 6px 20px; margin: 0; padding: 0; list-style: none; }
@media (max-width: 900px) { .foot-top { grid-template-columns: 1fr 1fr; padding: 44px 0 36px; } .foot-brand { grid-column: 1 / -1; } }

/* --- a page that is not there --- */

.lost { display: grid; place-items: center; min-height: 62vh; padding: 60px 0; text-align: center; }
.lost h1 { margin-top: 14px; font-size: clamp(30px, 4.4vw, 44px); font-weight: 700; letter-spacing: -.012em; }
.lost .lede { margin-top: 14px; animation: none; }
.lost .cta { margin-top: 28px; }
.kicker { color: var(--accent-text); font: 600 12.5px var(--mono); letter-spacing: .08em; text-transform: uppercase; }

