/* ─────────────────────────────────────────────────────────────────────────
   getvivarium.app — site styles.
   Built on tokens.css. Rules from the design system that hold here too:
   flat saturated fields, NO shadows (the inset ring is the one exception the
   system itself defines), nothing rounder than 12px, two font weights only.
   ───────────────────────────────────────────────────────────────────────── */

*,
*::before,
*::after { box-sizing: border-box; }

html { scroll-behavior: auto; }
[hidden] { display: none !important; }
.btn:disabled { cursor: not-allowed; opacity: 0.65; }
.plan[data-selected="true"] { outline: 3px solid var(--text-body); outline-offset: 5px; }
html.motion-paused *, html.motion-paused *::before, html.motion-paused *::after {
  animation-play-state: paused !important;
}
html.motion-paused [data-reveal], html.motion-paused [data-split],
html.motion-paused .slug, html.motion-paused .char {
  opacity: 1 !important; transform: none !important; transition: none !important;
}
details { border-bottom: 1px solid currentColor; padding: 16px 0; }
summary { cursor: pointer; font-weight: 600; }
summary:focus-visible, button:focus-visible { outline: 2px solid currentColor; outline-offset: 5px; }

body {
  margin: 0;
  background: var(--surface-app);
  color: var(--text-body);
  font-family: var(--font-sans);
  font-weight: var(--weight-regular);
  font-size: var(--size-body);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  margin: 0;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-title);
  line-height: var(--leading-tight);
}

p { margin: 0; }

a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in oklch, var(--accent) 45%, transparent);
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
a:hover { color: var(--paper-100); border-bottom-color: var(--paper-100); }

button { font-family: inherit; font-size: inherit; color: inherit; }

::selection { background: var(--accent); color: var(--ink-900); }
:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }

img, video { max-width: 100%; display: block; }

/* ── Type helpers ───────────────────────────────────────────────────────── */

.mono { font-family: var(--font-mono); letter-spacing: var(--tracking-mono); }

.caps {
  font-family: var(--font-mono);
  font-size: var(--size-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.display {
  font-size: clamp(48px, 7.2vw, 112px);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  font-weight: var(--weight-bold);
  text-wrap: balance;
}

.headline {
  font-size: clamp(38px, 4.9vw, 72px);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  font-weight: var(--weight-bold);
}

.lede { font-size: var(--size-body); line-height: var(--leading-body); color: var(--paper-200); }
.meta { font-size: var(--size-meta); line-height: var(--leading-body); color: var(--paper-300); }
.micro { font-size: var(--size-micro); color: var(--ink-600); }

/* ── Page frame ─────────────────────────────────────────────────────────── */

.wrap {
  position: relative;
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 clamp(20px, 3.9vw, 56px);
}

.section { position: relative; border-bottom: 1px solid var(--ink-700); }
.section--sunken { background: var(--surface-sunken); }
.section__body { padding-bottom: clamp(64px, 7vw, 96px); }

/* the visible modular grid — structure, never decoration */
.gridlines {
  position: absolute;
  inset: 0;
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 clamp(20px, 3.9vw, 56px);
  pointer-events: none;
}
.gridlines > div {
  height: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.gridlines span { border-left: 1px solid var(--ink-700); }
.gridlines span:last-child { border-right: 1px solid var(--ink-700); }
.gridlines--bright span { border-color: color-mix(in oklch, var(--paper-100) 12%, transparent); }

/* section index row: 0.1 ─────────────── Overview */
.slug {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 0;
  border-bottom: 1px solid var(--ink-700);
  color: var(--paper-300);
}
.slug--bright { border-bottom-color: color-mix(in oklch, var(--paper-100) 14%, transparent); }

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: clamp(24px, 3vw, 48px);
  padding: clamp(48px, 6vw, 96px) 0 clamp(28px, 3.4vw, 52px);
}
.section-head__title { flex: 1 1 520px; min-width: 0; }
.section-head__aside { flex: 0 1 300px; min-width: 240px; }

/* ── Header ─────────────────────────────────────────────────────────────── */

.masthead { position: relative; z-index: 30; }
.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 20px;
  padding: 18px 0;
  border-bottom: 1px solid var(--ink-700);
}
.brand { display: flex; align-items: center; gap: 12px; }
/* The mark itself. It carries its own squircle and its own dark field, so it
   needs no background, no radius and no padding from us. */
.brand__glyph {
  width: 30px; height: 30px;
  display: block;
  flex: none;
}
.brand__name { font-size: var(--size-section); font-weight: var(--weight-bold); letter-spacing: var(--tracking-title); }

.nav { display: flex; align-items: center; flex-wrap: wrap; gap: clamp(14px, 1.8vw, 26px); }
.nav a {
  font-family: var(--font-mono);
  font-size: var(--size-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--paper-300);
  border-bottom: none;
  position: relative;
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -4px;
  height: 1px;
  background: var(--paper-100);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav a:hover { color: var(--paper-100); }
.nav a:hover::after { transform: scaleX(1); }

/* ── Buttons (ported from components/core/Button.jsx) ───────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 40px;
  padding: 0 20px;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-weight: var(--weight-bold);
  font-size: var(--size-body);
  line-height: 1;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              transform var(--dur-instant) var(--ease-out);
}
.btn:active { transform: scale(var(--scale-press)); }
.btn--sm { height: 32px; padding: 0 14px; font-size: var(--size-meta); }

.btn--primary { background: var(--paper-100); color: var(--ink-900); }
.btn--primary:hover { background: var(--paper-200); }

.btn--secondary { background: transparent; color: var(--paper-100); border-color: var(--border-hairline); }
.btn--secondary:hover { background: var(--ink-700); }

.btn--field {
  background: color-mix(in oklch, currentColor 12%, transparent);
  color: currentColor;
  border-color: color-mix(in oklch, currentColor 34%, transparent);
}
.btn--field:hover { background: color-mix(in oklch, currentColor 22%, transparent); }

/* ── Badge (components/core/Badge.jsx) ──────────────────────────────────── */

.badge {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 10px;
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: var(--size-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  background: var(--ink-700);
  color: var(--paper-100);
}
.badge--active { background: var(--status-active); color: var(--ink-900); }
.badge--field { background: color-mix(in oklch, currentColor 16%, transparent); color: currentColor; }

/* ── Card (components/core/Card.jsx) ────────────────────────────────────── */

.card {
  display: block;
  position: relative;
  border-radius: var(--radius-card);
  padding: var(--pad-card);
  background: var(--field);
  color: var(--fg);
  transition: box-shadow var(--dur-ring) var(--ease-out);
}
.card[data-ring="true"] { box-shadow: inset 0 0 0 var(--ring-width) var(--contrast); }

[data-tone="iris"]     { --field: var(--iris-field);     --contrast: var(--iris-contrast);     --fg: var(--on-dark); }
[data-tone="cyan"] { --field: var(--cyan-field); --contrast: var(--cyan-contrast); --fg: var(--on-light); }
[data-tone="indigo"]     { --field: var(--indigo-field);     --contrast: var(--indigo-contrast);     --fg: var(--on-dark); }
[data-tone="magenta"]    { --field: var(--magenta-field);    --contrast: var(--magenta-contrast);    --fg: var(--on-light); }

/* ── Note callout — where the honest caveats live ───────────────────────── */

.note {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 18px 22px;
  border: 1px solid var(--ink-700);
  border-radius: var(--radius-md);
}
.note__mark {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  border-radius: var(--radius-sm);
  background: var(--indigo-contrast);
  color: var(--ink-900);
  display: grid; place-items: center;
  font-family: var(--font-mono);
  font-weight: var(--weight-bold);
  font-size: 15px;
  line-height: 1;
}
.note p { font-size: var(--size-meta); line-height: var(--leading-body); color: var(--paper-300); }
.note strong { color: var(--paper-100); font-weight: var(--weight-bold); }

/* ── Hero ───────────────────────────────────────────────────────────────── */

.hero { position: relative; overflow: hidden; }

.hero__field {
  position: absolute;
  inset: -90px;
  /* A whisper, not a barber pole — the earlier 8px ink-700/800 pitch moiréd
     across the whole hero and fought the headline. */
  background: repeating-linear-gradient(45deg, var(--ink-800) 0 16px, var(--ink-900) 16px 32px);
  animation: drift 42s linear infinite;
  will-change: transform;
}
@keyframes drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-45.25px, 45.25px, 0); }
}

/* the loop itself, when a file is present in assets/video/ */
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}
.hero__video.is-ready { opacity: 0.42; }
.hero__scrim {
  position: absolute;
  inset: 0;
  background: color-mix(in oklch, var(--ink-900) 62%, transparent);
}

.hero__grid {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: clamp(28px, 4vw, 64px);
  padding: clamp(56px, 7vw, 96px) 0 clamp(36px, 4vw, 56px);
}
.hero__lead { flex: 1 1 620px; min-width: 0; }
.hero__aside { flex: 0 1 320px; min-width: 240px; }

.actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(28px, 3vw, 44px); }

.specbar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px 24px;
  padding: 14px 0 16px;
  border-top: 1px solid color-mix(in oklch, var(--paper-100) 14%, transparent);
}
.specbar span { font-family: var(--font-mono); letter-spacing: var(--tracking-mono); font-size: var(--size-meta); color: var(--paper-300); }

/* ── Loop engine ────────────────────────────────────────────────────────── */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  border-top: 1px solid var(--ink-700);
}
.step {
  padding: 24px clamp(16px, 2vw, 28px) 26px;
  border-bottom: 1px solid var(--ink-700);
  border-left: 1px solid var(--ink-700);
}
.step:first-child { border-left: none; }
.step__slug {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: var(--space-5);
  color: var(--paper-300);
}

/* striped scene stand-in, from components/wallpaper/ScenePlaceholder */
.scene {
  position: relative;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--ink-800);
  height: 132px;
}
.scene::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    var(--scene-angle, 34deg),
    var(--scene-stripe, var(--ink-600)) 0 var(--scene-w, 6px),
    transparent var(--scene-w, 6px) calc(var(--scene-w, 6px) * 2)
  );
  opacity: 0.55;
}
.scene__label {
  position: absolute;
  left: 12px; bottom: 10px;
  font-family: var(--font-mono);
  font-size: var(--size-micro);
  letter-spacing: var(--tracking-mono);
  color: var(--paper-300);
}
.scene img, .scene video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* the loop-point track */
.track { position: relative; height: 132px; border-radius: var(--radius-md); background: var(--ink-800); overflow: hidden; }
.track__ticks { position: absolute; inset: 0; background: repeating-linear-gradient(90deg, var(--ink-700) 0 1px, transparent 1px 14px); }
.track__range {
  position: absolute;
  top: 0; bottom: 0;
  left: 17.17%; width: 32.33%;
  background: color-mix(in oklch, var(--iris-contrast) 20%, transparent);
  border-left: 2px solid var(--iris-contrast);
  border-right: 2px solid var(--iris-contrast);
}
.track__handle {
  position: absolute;
  top: 50%;
  width: 18px; height: 18px;
  margin: -9px 0 0 -9px;
  border-radius: var(--radius-sm);
  background: var(--paper-100);
}
.track__playhead {
  position: absolute;
  top: 10px; bottom: 10px;
  width: 2px;
  background: var(--paper-100);
  animation: scrub 7.76s linear infinite;
}
@keyframes scrub { from { left: 17.17%; } to { left: 49.5%; } }
.is-paused .track__playhead, .is-paused .hero__field { animation-play-state: paused; }

.row-between { display: flex; justify-content: space-between; gap: 10px; }

/* ── Surfaces ───────────────────────────────────────────────────────────── */

.cards { display: flex; flex-wrap: wrap; gap: var(--gap-card-row); }
.surface {
  flex: 1 1 288px;
  min-width: 264px;
  cursor: pointer;
  border: none;
  padding: 0;
  background: none;
  text-align: left;
  transition: transform var(--dur-base) var(--ease-spring);
}
.surface:hover { transform: translateY(var(--lift-hover)) scale(1.01); }
.surface__inner { display: flex; flex-direction: column; min-height: 378px; }
.surface__slug { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.surface h3 { font-size: var(--size-card-title); letter-spacing: var(--tracking-title); }
.surface p { margin-top: var(--space-3); font-size: var(--size-meta); line-height: var(--leading-body); opacity: var(--alpha-body); min-height: 36px; }
.surface .stat { margin-top: var(--space-3); font-size: 10px; opacity: var(--alpha-meta); }

/* fanned scene stack, as in templates/playlists-section */
.fan { flex: 1 1 auto; display: grid; place-items: center; padding: var(--space-6) 0 var(--space-8); }
.fan__inner { position: relative; width: 100%; max-width: 236px; height: 172px; }
.fan__inner > * { position: absolute; border-radius: var(--radius-sm); overflow: hidden; }
.fan__a { left: 0; top: 12px; width: 60%; height: 78%; transform: rotate(-7deg); transition: transform var(--dur-slow) var(--ease-spring); }
.fan__b { right: 0; top: 6px; width: 60%; height: 78%; transform: rotate(7deg); transition: transform var(--dur-slow) var(--ease-spring); }
.fan__c { left: 20%; right: 20%; top: 22px; bottom: 0; transition: transform var(--dur-slow) var(--ease-spring); }
/* A fan of three reads well as abstract stripes. With a real screenshot it
   reads as three unreadable postage stamps — so once a shot loads, the side
   layers drop and the frame squares up and fills the card. */
.fan__inner.has-shot .fan__a,
.fan__inner.has-shot .fan__b { display: none; }
.fan__inner.has-shot .fan__c { inset: 0; }
.fan__inner.has-shot .scene img { object-position: left top; }

/* Once every card carries a real image, the frame should be the card — a
   236px-wide stamp inside a saturated field reads as a swatch, not as the
   app. Widened and made taller, and the fan's padding comes off with it,
   so the screenshot is the thing you look at. */
.fan__inner.has-shot { max-width: none; height: 214px; }
.fan:has(.has-shot) { padding: var(--space-4) 0 var(--space-5); }
.surface:hover .fan__inner.has-shot .fan__c { transform: translateY(-4px) scale(1.02); }

.surface:hover .fan__a { transform: rotate(-11deg) translate(-6px, -4px); }
.surface:hover .fan__b { transform: rotate(11deg) translate(6px, -4px); }
.surface:hover .fan__c { transform: translateY(-4px); }
.fan .scene { height: 100%; }

/* ── Comparison table ───────────────────────────────────────────────────── */

.compare {
  display: grid;
  grid-template-columns: minmax(96px, 1.3fr) minmax(88px, 1fr) minmax(88px, 1fr);
  border-top: 1px solid var(--ink-700);
}
.compare > * { padding: 20px 12px; font-size: var(--size-meta); color: var(--paper-300); border-top: 1px solid var(--ink-700); }
.compare > .compare__head { padding: 14px 12px; border-top: none; }
.compare > :nth-child(3n + 2), .compare > :nth-child(3n + 3) { border-left: 1px solid var(--ink-700); }
.compare .us { font-size: var(--size-body); color: var(--paper-100); }
.compare .us--strong { font-weight: var(--weight-bold); color: var(--iris-contrast); }
.compare .price { font-size: var(--size-section); font-weight: var(--weight-bold); letter-spacing: var(--tracking-title); color: var(--iris-contrast); }
.compare > :nth-last-child(-n + 3) { border-bottom: 1px solid var(--ink-700); }

/* ── Pricing ────────────────────────────────────────────────────────────── */

.plans { display: flex; flex-wrap: wrap; gap: var(--gap-card-row); align-items: stretch; }
.plan { flex: 1 1 380px; min-width: 280px; display: flex; }
.plan > * { flex: 1 1 auto; display: flex; flex-direction: column; }
.plan--free > div {
  border: 1px solid var(--ink-700);
  border-radius: var(--radius-card);
  padding: var(--pad-card);
}
.plan h3 { margin-top: var(--space-8); font-size: clamp(34px, 3.4vw, 44px); letter-spacing: var(--tracking-display); }
.plan ul { list-style: none; margin: var(--space-8) 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.plan li { display: flex; gap: 12px; align-items: flex-start; font-size: var(--size-body); }
.plan li::before {
  content: "";
  flex: 0 0 auto;
  width: 10px; height: 10px;
  margin-top: 6px;
  border-radius: 3px;
  background: var(--bullet, var(--ink-600));
}
.plan--paid li { opacity: 0.9; }
.plan__foot { margin-top: auto; display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }

/* ── Requirements ───────────────────────────────────────────────────────── */

.specs { flex: 1 1 420px; min-width: 280px; border-top: 1px solid var(--ink-700); }
.specs__row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 0;
  border-bottom: 1px solid var(--ink-700);
}
.specs__row dt { font-size: var(--size-meta); color: var(--paper-300); }
.specs__row dd {
  margin: 0;
  font-family: var(--font-mono);
  letter-spacing: var(--tracking-mono);
  font-size: var(--size-meta);
  color: var(--paper-100);
}

/* ── Footer ─────────────────────────────────────────────────────────────── */

.footer__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: 32px;
  padding: clamp(40px, 4.5vw, 72px) 0 clamp(32px, 3.5vw, 48px);
}
.footer__col { display: flex; flex-direction: column; gap: 10px; }
.footer__col .caps { color: var(--ink-600); }
.footer__base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 0 0;
  border-top: 1px solid var(--ink-700);
}

/* ── Chrome: scroll progress, cursor ────────────────────────────────────── */

.progress {
  position: fixed;
  right: clamp(14px, 2vw, 26px);
  bottom: clamp(14px, 2vw, 26px);
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: var(--size-micro);
  letter-spacing: var(--tracking-caps);
  color: var(--paper-300);
  mix-blend-mode: difference;
  pointer-events: none;
}
.progress__bar { width: 64px; height: 2px; background: color-mix(in oklch, var(--paper-100) 24%, transparent); }
/* PERF: driven by transform: scaleX() from site.js, not width. width forces
   layout + paint on every scroll frame; a transform is composited. */
.progress__fill { height: 100%; width: 100%; background: var(--paper-100); transform-origin: left; transform: scaleX(0); }

.cursor {
  position: fixed;
  top: 0; left: 0;
  z-index: 60;
  width: 12px; height: 12px;
  border-radius: 999px;
  border: 1px solid var(--paper-100);
  pointer-events: none;
  /* PERF: this was `mix-blend-mode: difference`. A blended element cannot be
     promoted to its own compositor layer, so the rAF that moves this dot was
     repainting whatever sat under it — the hero video included — on every
     mouse frame. The page is dark end to end, where difference-against-dark
     is white anyway, so a plain white ring is the same picture for free.
     will-change earns its keep here: this is the one element that moves on
     literally every frame it is visible. */
  transform: translate3d(-50px, -50px, 0);
  will-change: transform;
  transition: width var(--dur-base) var(--ease-spring),
              height var(--dur-base) var(--ease-spring),
              background var(--dur-fast) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
  opacity: 0;
}
.cursor.is-live { opacity: 1; }
.cursor.is-hot { width: 44px; height: 44px; background: color-mix(in oklch, var(--paper-100) 14%, transparent); }
@media (hover: none), (pointer: coarse) { .cursor { display: none; } }

/* ── Reveal animations ──────────────────────────────────────────────────── */

/* split headline: each line is a mask, chars rise into it */
.split { display: block; }
/* the mask. padding + negative margin keeps descenders from being clipped
   while the line still hides the chars before they rise into it. */
.split .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
}
.split .word { display: inline-block; white-space: pre; }
.js .split .char {
  display: inline-block;
  transform: translateY(105%);
  transition: transform 900ms var(--ease-out);
  transition-delay: calc(var(--i, 0) * 14ms);
}
/* PERF: will-change used to sit on every .char unconditionally. A headline is
   ~50 chars and the page has several, so that was hundreds of layers the
   compositor held for the whole session to animate each one once. Scoped to
   the headlines that have not played yet; the layers are dropped on reveal. */
.js [data-split]:not(.is-revealed) .char { will-change: transform; }
.split .char--space { white-space: pre; }
.js .is-revealed .split .char { transform: translateY(0); }

.js [data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--delay, 0ms);
}
[data-reveal].is-revealed { opacity: 1; transform: none; }

.js [data-reveal="rule"] {
  opacity: 1;
  transform: none;
  position: relative;
}
.js [data-reveal="rule"]::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 1px;
  background: var(--ink-700);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 900ms var(--ease-out);
}
.js [data-reveal="rule"].is-revealed::after { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .hero__field, .track__playhead { animation: none; }
  .js .split .char { transform: none; transition: none; }
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  .js [data-reveal="rule"]::after { transform: scaleX(1); }
  .cursor { display: none; }
  * { scroll-behavior: auto !important; }
}

/* ── Narrow screens ─────────────────────────────────────────────────────── */

@media (max-width: 720px) {
  .gridlines > div { grid-template-columns: repeat(2, 1fr); }
  .compare { grid-template-columns: minmax(80px, 1.2fr) minmax(76px, 1fr) minmax(76px, 1fr); }
  .compare > * { padding: 14px 8px; }
  .nav { gap: 12px; }
  .nav .btn { display: none; }
}

/* ── Bleed band: the loop, edge to edge ─────────────────────────────────────
   Backdrop's one genuinely good idea — at some point you have to stop
   describing the wallpaper and show it. Hidden until a clip exists; JS
   unhides it on `canplay` so there is never an empty black band. */

.bleed {
  position: relative;
  height: clamp(360px, 62vh, 720px);
  overflow: hidden;
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--ink-700);
}
.bleed[hidden] { display: none; }
.bleed__video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.bleed__meta {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 14px clamp(20px, 3.9vw, 56px);
  color: var(--paper-100);
  mix-blend-mode: difference;
}

/* ── Device: a laptop whose lid opens as you scroll ────────────────────────
   Drawn, not photographed, and unbranded — flat planes on the hairline scale,
   no gradients, no shadow. The lid is a real 3D rotation about a hinge at its
   bottom edge, so the screen foreshortens as it swings up the way a lid
   actually does. `--open` is 0 (shut) to 1 (upright), driven by scroll. */

/* ── The machine ──────────────────────────────────────────────────────────
   A laptop drawn in CSS, no branding anywhere on it. The old version was two
   grey rectangles and read as a diagram; this one has the proportions of the
   real thing — thin uniform bezel, notch, tapered base with the lip cut out of
   the front edge — because the section's whole argument is "here is what your
   desk actually looks like".

   Depth is gradients only. No box-shadow anywhere: the design system forbids
   them, and aluminium reads as aluminium from a light gradient across it.

   Two scroll-driven variables:
     --open  0 → 1   the lid lifts
     --wake  0 → 1   the lock screen lifts away, revealing the desktop
   The wallpaper sits under both and never restarts, which is the feature.
--------------------------------------------------------------------------- */

.mac {
  position: relative;
  /* Capped by the viewport's HEIGHT as well as its width, because this is a
     wide object in a page you meet at the top of a screen. Sized only by
     width, a 16:10 machine on a 1920x1080 display is taller than the space
     under the headline and you never see the whole thing — which is exactly
     what shipped on 2026-07-31. 74vh keeps the base above the fold at every
     desktop shape.
     Perspective magnifies the near edge on top of this, so the real drawn
     width is ~12% more than whatever lands here. */
  max-width: min(1080px, 90vw, 62vh);
  margin: 0 auto; --open: 1; --wake: 1;
  /* The resting angle once the lid is fully up.
     It used to be 0deg, which is dead face-on: the perspective above it did
     nothing and the machine read as a flat rectangle with a picture in it.
     A few degrees of negative tilt puts the top edge nearer the eye than the
     hinge, which is what makes it read as a laptop you are standing in front
     of rather than a screenshot. */
  --pov: -12deg;
}

/* Shorter perspective and a lower eye than before. perspective-origin is where
   the viewer is standing; below the middle of the device means looking up at
   the screen, which is the angle that shows a wallpaper best — the panel faces
   you and the deck falls away underneath it. */
/* Perspective scales with the object: the tilt lifts the top edge by roughly
   sin(12deg) x the lid height, and the near-edge magnification is
   P / (P - that). A smaller machine needs a shorter P for the same angle to
   read at all. 900px holds the ~1.13 top-to-bottom ratio measured off the
   reference without the device outgrowing its grid module. */
.mac__stage { perspective: 900px; perspective-origin: 50% 78%; position: relative; }

/* ── Hue ───────────────────────────────────────────────────────────────────
   One control, everything it touches. `--hue` lives on :root, so the hero
   machine and the laptop in the setup photograph recolour together — scroll
   down after moving it and the desk shot already agrees. Only the wallpaper
   is filtered, never the menu bar or the widgets over it, which is exactly
   what the app does.
--------------------------------------------------------------------------- */

/* PERF: a filter on a <video> costs a full GPU pass per decoded frame and
   takes the element off the fast video-compositing path — permanently, even at
   hue-rotate(0deg), which is what the page sits at until someone drags the
   slider. So the filter only exists once the slider has left zero; site.js
   sets data-hue on <html> to switch it on. Identical at every non-zero value,
   free at the default one. */
:root[data-hue] .mac__wall,
:root[data-hue] .mac__fallback,
:root[data-hue] .setup__screen { filter: hue-rotate(var(--hue, 0deg)); }

.huebar {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) 0 0;
}
/* Armed only when JS is running — see the note in the markup. */
.huebar { display: none; }
.js .huebar { display: flex; }

.huebar__label { color: var(--paper-300); flex: none; }
.huebar__value { flex: none; min-width: 4.5ch; text-align: right; color: var(--paper-300); font-variant-numeric: tabular-nums; }

.huebar__input {
  -webkit-appearance: none;
  appearance: none;
  flex: 1 1 auto;
  height: 20px;
  background: transparent;
  cursor: ew-resize;
}
/* A hairline, like every other rule on the page. */
.huebar__input::-webkit-slider-runnable-track {
  height: 1px;
  background: var(--border-hairline);
}
.huebar__input::-moz-range-track {
  height: 1px;
  background: var(--border-hairline);
}
/* Square, because nothing here is rounder than it has to be. */
.huebar__input::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 10px;
  height: 18px;
  margin-top: -9px;
  border-radius: 2px;
  background: var(--paper-100);
  border: none;
}
.huebar__input::-moz-range-thumb {
  width: 10px;
  height: 18px;
  border-radius: 2px;
  background: var(--paper-100);
  border: none;
}
.huebar__input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 6px; }

/* ── The setup shot ────────────────────────────────────────────────────────
   A photograph of a real desk with the loop playing on the machine in it.

   The screen in a photograph is a quadrilateral — its vertical edges converge
   — so the video is not laid over it as a rectangle. `site/tools/screen-fit.py`
   solves the projective transform from the video's rect onto the screen's four
   corners and emits `--screen-matrix`; the video is then positioned by
   percentage so the fit holds at every rendered width.

   `--screen-*` are set inline on the section, because they belong to one
   specific photograph rather than to the design system.
--------------------------------------------------------------------------- */

.setup { position: relative; overflow: hidden; }

.setup__photo { display: block; width: 100%; height: auto; }

.setup__screen {
  position: absolute;
  left: var(--screen-left);
  top: var(--screen-top);
  width: var(--screen-width);
  height: var(--screen-height);
  transform: var(--screen-matrix);
  transform-origin: 0 0;
  object-fit: cover;
  /* The panel's own glass sits above the video, so the loop picks up the
     photograph's reflection instead of looking pasted on. */
  z-index: 0;
}

/* The fish.
   They were cut out of the photograph, the water behind them cloned over, and
   each one put back as its own sprite — so they can move. Positions and sizes
   are percentages of the photo, which keeps them registered to the tank at
   every width.

   Clipped to the water the camera can actually see: the polygon is the tank
   with a notch taken out for the laptop standing in front of it. Without that
   a fish swims over the machine and the whole illusion goes. */
.setup__tank {
  position: absolute;
  inset: 0;
  pointer-events: none;
  clip-path: polygon(
    21.8% 18.3%, 80.1% 18.3%, 80.1% 66.0%,
    61.7% 66.0%, 61.7% 41.4%, 38.9% 41.4%, 38.9% 66.0%, 21.8% 66.0%);
}

.tank__fish {
  position: absolute;
  height: auto;
  animation: fish-swim var(--dur, 20s) ease-in-out var(--delay, 0s) infinite;
  will-change: transform;
}

/* Out and back, turning at each end. The flip happens at the far point, where
   the fish is momentarily still, which is where a real one turns too. */
@keyframes fish-swim {
  0%,
  100% { transform: translate(0, 0) scaleX(1); }
  46%  { transform: translate(var(--swim), var(--bob)) scaleX(1); }
  50%  { transform: translate(var(--swim), var(--bob)) scaleX(-1); }
  96%  { transform: translate(0, 0) scaleX(-1); }
}

@media (prefers-reduced-motion: reduce) {
  .tank__fish { animation: none; }
}

.setup__glass {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  mix-blend-mode: screen;
  opacity: 0.5;
}

/* ── The room ──────────────────────────────────────────────────────────────
   A floor and a back wall, ruled at the page's own module and carried into
   depth. The machine stands on the floor rather than hovering over a gradient,
   which is the "nothing floats" rule taken literally.

   Deliberately still. The only thing that moves in this scene is the
   wallpaper, which is the thing being sold. Everything else is a drawing.
--------------------------------------------------------------------------- */

.room {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  pointer-events: none;
  z-index: 0;
}

/* The floor. Hinged at the machine's base and laid away from the viewer, so
   the grid converges on its own — no faked vanishing point. */
.room__floor {
  position: absolute;
  left: 50%;
  top: 100%;
  width: 320%;
  height: 1500px;
  transform: translateX(-50%) rotateX(90deg);
  transform-origin: 50% 0;
  background:
    repeating-linear-gradient(90deg, var(--border-hairline) 0 1px, transparent 1px 96px),
    repeating-linear-gradient(0deg,  var(--border-hairline) 0 1px, transparent 1px 96px);
  /* Fade into the page rather than stopping at an edge. A hard horizon reads
     as a mistake; this reads as distance. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 12%, transparent 68%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 12%, transparent 68%);
}

/* The wall, set back far enough that the machine reads as standing clear of
   it. Coarser module than the floor: distance, stated by the drawing. */
.room__wall {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 260%;
  height: 150%;
  transform: translate(-50%, -54%) translateZ(-660px);
  background:
    repeating-linear-gradient(90deg, var(--border-hairline) 0 1px, transparent 1px 160px),
    repeating-linear-gradient(0deg,  var(--border-hairline) 0 1px, transparent 1px 160px);
  -webkit-mask-image: radial-gradient(120% 100% at 50% 46%, #000 30%, transparent 82%);
  mask-image: radial-gradient(120% 100% at 50% 46%, #000 30%, transparent 82%);
}

/* Three bands of brand colour on the wall, snapped to its module and run at
   full saturation — the system says the tones carry onto the page at strength
   rather than muted into a wash. Narrow on purpose: they are marks on a wall,
   not lighting. */
.room__band {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 96px;                    /* the floor's module, not an arbitrary width */
  /* Nothing on this page is rounder than 12px, and a band is not a card. */
  border-radius: 0;
  /* Visible across the machine's upper half, where the wall is actually
     behind something, and gone well before the section's spec row. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 4%, #000 24%, #000 52%, transparent 76%);
  mask-image: linear-gradient(to bottom, transparent 4%, #000 24%, #000 52%, transparent 76%);
}
.room__band--iris    { left: 18%; background: var(--iris-field); }
.room__band--cyan    { left: 47%; background: var(--cyan-field); }
.room__band--magenta { left: 76%; background: var(--magenta-field); }

/* The machine sits in front of the room. */
.mac__lid { z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .room { display: none; }
}

.mac__lid {
  position: relative;
  transform-origin: 50% 100%;
  transform: rotateX(calc(var(--pov) + (1 - var(--open)) * -88deg));
  transform-style: preserve-3d;
  will-change: transform;
}

/* Bezel = the black glass front. The aluminium edge is a 1px lighter ring. */
.mac__bezel {
  position: relative;
  padding: 0.9%;
  border-radius: 20px;
  /* Aluminium, not black. Against a near-black page a dark body has no
     silhouette and the thing reads as a floating screen rather than a laptop. */
  background:
    linear-gradient(168deg,
      oklch(0.72 0.004 250) 0%,
      oklch(0.55 0.004 250) 18%,
      oklch(0.44 0.004 250) 46%,
      oklch(0.38 0.004 250) 78%,
      oklch(0.62 0.004 250) 100%);
  backface-visibility: hidden;
}
/* the machined highlight along the top edge */
.mac__bezel::before {
  content: "";
  position: absolute;
  top: 0; left: 6%; right: 6%;
  height: 1px;
  background: linear-gradient(90deg, transparent, oklch(0.92 0.003 250 / 0.7), transparent);
  border-radius: 999px;
  z-index: 6;
}
.mac__bezel::after {           /* screen glare, very restrained */
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background: linear-gradient(112deg, oklch(1 0 0 / 0.07) 0%, oklch(1 0 0 / 0) 26%);
  pointer-events: none;
  z-index: 6;
}

.mac__screen {
  position: relative;
  aspect-ratio: 1.54;          /* the real panel is ~1.54, not 16:10 */
  border-radius: 11px;
  overflow: hidden;
  background: #000;
  isolation: isolate;
}
.mac__wall, .mac__fallback {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
}
/* Visible from the start, not on `is-ready`.
   It carries a `poster`, so an unplayed <video> is a still image rather than
   a transparent hole — hiding it until the video decodes means anyone whose
   video is slow, metered, or blocked outright gets an empty rectangle where
   the product should be. That is what a Mac with content blockers showed on
   2026-08-01: the mp4 was never even requested, and the hero was a dark box.
   The poster now stands in, and the video replaces it in place when it
   arrives. */
.mac__wall { opacity: 1; transition: opacity var(--dur-slow) var(--ease-out); }
.mac__wall.is-ready { z-index: 1; }
.mac__fallback { border-radius: 0; }

/* The notch. Hangs off the top edge of the glass, not the bezel. */
.mac__notch {
  position: absolute;
  top: 0.62%; left: 50%;
  transform: translateX(-50%);
  width: 13.5%;
  height: 2.6%;
  min-height: 8px;
  background: #000;
  border-radius: 0 0 7px 7px;
  z-index: 5;
  display: grid;
  place-items: center;
}
.mac__cam {
  width: 4px; height: 4px;
  border-radius: 999px;
  background: oklch(0.30 0.02 250);
}

/* ── Desktop ─────────────────────────────────────────────────────────────── */
.mac__os {
  position: absolute; inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  opacity: calc(0.15 + 0.85 * var(--wake));
  transition: opacity 120ms linear;
}

.mac__menubar {
  height: 4.6%;
  min-height: 15px;
  display: flex;
  align-items: center;
  gap: 1.4%;
  padding: 0 1.6%;
  background: oklch(0.14 0.01 250 / 0.55);
  backdrop-filter: blur(8px);          /* PERF: was 14px — see note below */
  -webkit-backdrop-filter: blur(8px);
  font-size: clamp(5px, 0.95cqw, 11px);
  color: oklch(1 0 0 / 0.86);
  container-type: inline-size;
}
.mac { container-type: inline-size; }
.mac__menu { font-size: clamp(6px, 1.02cqw, 12px); letter-spacing: 0.01em; white-space: nowrap; }
.mac__menu--app { font-weight: var(--weight-bold); }
.mac__spacer { flex: 1; }
.mac__status { width: 1.1cqw; max-width: 13px; height: 0.72cqw; max-height: 9px; border-radius: 2px; background: oklch(1 0 0 / 0.72); }
.mac__status--wifi { clip-path: polygon(50% 100%, 0 26%, 12% 12%, 50% 62%, 88% 12%, 100% 26%); border-radius: 0; }
.mac__status--batt { border-radius: 2px; border: 1px solid oklch(1 0 0 / 0.72); background: linear-gradient(90deg, oklch(1 0 0 / 0.72) 62%, transparent 62%); }
.mac__clock { font-size: clamp(6px, 1.02cqw, 12px); font-variant-numeric: tabular-nums; }

/* Widgets, right-hand column the way macOS parks them. */
.mac__widgets {
  position: absolute;
  top: 8%; right: 2.6%;
  display: grid;
  gap: 2.2cqw;
  width: 19%;
}
.mac__widget {
  border-radius: 12px;
  padding: 6% 8%;
  display: grid;
  gap: 0.35em;
  background: oklch(0.16 0.012 250 / 0.52);
  backdrop-filter: blur(10px);         /* PERF: was 18px */
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid oklch(1 0 0 / 0.10);
  color: oklch(1 0 0 / 0.92);
}
.mac__w-big { font-size: clamp(11px, 2.5cqw, 30px); font-weight: var(--weight-bold); line-height: 1; font-variant-numeric: tabular-nums; }
.mac__w-sub, .mac__w-label { font-size: clamp(5px, 0.86cqw, 10px); color: oklch(1 0 0 / 0.6); }
.mac__w-row { font-size: clamp(5px, 0.9cqw, 11px); display: flex; align-items: center; gap: 0.5em; }
.mac__swatch { width: 0.9em; height: 0.9em; border-radius: 3px; background: linear-gradient(135deg, var(--cyan-field), var(--magenta-contrast)); flex: none; }
.mac__w-bar { height: 3px; border-radius: 999px; background: oklch(1 0 0 / 0.18); overflow: hidden; }
.mac__w-bar i { display: block; height: 100%; width: var(--p); background: oklch(1 0 0 / 0.8); }

/* Dock */
.mac__dock {
  margin-top: auto;
  align-self: center;
  margin-bottom: 1.4%;
  display: flex;
  align-items: center;
  gap: 1.1cqw;
  padding: 0.9cqw 1.2cqw;
  border-radius: 14px;
  background: oklch(0.18 0.012 250 / 0.46);
  backdrop-filter: blur(10px);         /* PERF: was 20px */
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid oklch(1 0 0 / 0.10);
}
.mac__tile {
  width: 3.1cqw; height: 3.1cqw;
  max-width: 40px; max-height: 40px;
  border-radius: 22%;
  background: linear-gradient(150deg, color-mix(in oklch, var(--t) 92%, white), var(--t));
}
.mac__tile--vv {
  background:
    radial-gradient(120% 120% at 30% 78%, oklch(0.78 0.16 218) 0%, oklch(0.55 0.22 268) 42%, oklch(0.60 0.27 320) 78%, oklch(0.32 0.14 300) 100%);
}
.mac__dock-sep { width: 1px; height: 2.6cqw; max-height: 34px; background: oklch(1 0 0 / 0.16); }

/* ── Lock screen ─────────────────────────────────────────────────────────── */
.mac__lock {
  position: absolute; inset: 0;
  z-index: 3;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 0.2em;
  color: #fff;
  /* PERF: this used to be `backdrop-filter: blur(calc(6px * (1 - var(--wake))))`.
     That is a full-panel blur, over a playing video, whose RADIUS changed on
     every scroll frame — a radius change cannot be composited, so the whole
     panel was re-blurred from scratch ~60 times a second for the entire lift.
     It was the most expensive thing on the page. The scrim now carries the
     frosting as a flat wash and the lift is opacity + transform only, both of
     which the compositor does for free. */
  background: oklch(0.10 0.01 260 / 0.40);
  opacity: calc(1 - var(--wake));
  transform: translateY(calc(var(--wake) * -6%)) scale(calc(1 + var(--wake) * 0.04));
  transform-origin: 50% 40%;
  pointer-events: none;
}
.mac__lock-time { font-size: clamp(20px, 7.2cqw, 96px); font-weight: var(--weight-bold); line-height: 0.95; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.mac__lock-date { font-size: clamp(6px, 1.3cqw, 16px); color: oklch(1 0 0 / 0.78); }
.mac__lock-user { margin-top: 6%; display: grid; justify-items: center; gap: 0.35em; }
.mac__avatar {
  width: 3.4cqw; height: 3.4cqw; max-width: 44px; max-height: 44px;
  border-radius: 999px;
  background: linear-gradient(140deg, var(--cyan-field), var(--indigo-field));
  border: 1px solid oklch(1 0 0 / 0.25);
}
.mac__lock-user b { font-size: clamp(6px, 1.15cqw, 14px); font-weight: var(--weight-bold); }
.mac__lock-user em { font-style: normal; font-size: clamp(5px, 0.86cqw, 10px); color: oklch(1 0 0 / 0.55); }

/* ── Hinge and base ──────────────────────────────────────────────────────── */
.mac__hinge {
  height: 0.7%;
  min-height: 5px;
  margin: 0 11.5%;
  border-radius: 0 0 4px 4px;
  background: linear-gradient(180deg, oklch(0.24 0.005 250), oklch(0.44 0.006 250));
}

/* The base is foreshortened, tapers to the front, and has the lip cut out.
   It was 44px at rotateX(78deg), which draws as nine pixels — a grey sliver
   rather than the bottom half of a laptop. Taller and laid back less far, so
   the deck is actually a surface you can see, with the keyboard well and
   trackpad on it. Still foreshortened hard, because the eye is low. */
.mac__base {
  position: relative;
  height: 92px;
  border-radius: 2px 2px 10px 10px;
  transform-origin: 50% 0;
  transform: rotateX(66deg) scaleY(calc(0.3 + 0.7 * var(--open)));
  background: linear-gradient(180deg,
    oklch(0.74 0.004 250) 0%,
    oklch(0.60 0.004 250) 22%,
    oklch(0.46 0.004 250) 60%,
    oklch(0.34 0.004 250) 100%);
  clip-path: polygon(1.2% 0, 98.8% 0, 96.5% 100%, 3.5% 100%);
}
/* The keyboard well — a recess, not keys. At this foreshortening individual
   keys turn to noise; the dark inset is what actually reads as a deck. */
.mac__base::before {
  content: "";
  position: absolute;
  left: 7%; right: 7%; top: 12%;
  height: 46%;
  border-radius: 3px;
  background: linear-gradient(180deg, oklch(0.19 0.004 250), oklch(0.26 0.004 250));
}

/* The trackpad, seated below it. */
.mac__base::after {
  content: "";
  position: absolute;
  left: 37%; right: 37%; top: 62%;
  height: 24%;
  border-radius: 3px;
  background: linear-gradient(180deg, oklch(0.42 0.004 250), oklch(0.35 0.004 250));
}

/* The finger cutout on the front edge. */
.mac__lip {
  position: absolute;
  left: 50%; bottom: 0;
  transform: translateX(-50%);
  width: 13%;
  height: 12%;
  border-radius: 60% 60% 0 0 / 100% 100% 0 0;
  background: oklch(0.22 0.004 250);
  z-index: 1;
}

/* Ground shadow as a gradient, not a box-shadow. */
.mac__shadow {
  height: 26px;
  margin: -4px auto 0;
  width: 78%;
  background: radial-gradient(50% 50% at 50% 0%, oklch(0 0 0 / 0.55) 0%, oklch(0 0 0 / 0) 70%);
  opacity: calc(0.35 + 0.65 * var(--open));
}

/* One plan instead of two. `.plans` is flex, not grid — a grid-template rule
   here silently does nothing, which is exactly what the first attempt did. */
.plans--single { justify-content: center; }
.plans--single .plan { flex: 0 1 640px; }

.device__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  padding: 22px 4px 0;
}

@media (prefers-reduced-motion: reduce) {
  .mac { --open: 1; --wake: 1; }
  .mac__lid, .mac__base { transform: none; }
}

/* ── Prose: terms and privacy ─────────────────────────────────────────────── */

.prose { max-width: 68ch; }
.prose h2 {
  margin: var(--space-10) 0 var(--space-4);
  font-size: var(--size-section);
  letter-spacing: var(--tracking-title);
}
.prose h2:first-child { margin-top: 0; }
.prose p { margin-bottom: var(--space-4); color: var(--paper-200); }
.prose p + h2 { margin-top: var(--space-12); }
.prose strong { color: var(--indigo-contrast); font-weight: var(--weight-bold); }
.prose code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  color: var(--paper-100);
  background: var(--ink-800);
  padding: 2px 6px;
  border-radius: var(--radius-sm);
}

/* ── Hero, rebuilt around the machine (2026-07-29) ──────────────────────────
   The Mac carries the pitch now, so the type above it gets out of the way:
   centred, narrower measure, and the download button large enough to be the
   obvious next move. Everything here is layout only — no new colours, no
   shadows, nothing outside the four tones. */

.hero__lead--centred {
  max-width: 46rem;
  margin: 0 auto var(--space-8);
  text-align: center;
}

.hero__lead--centred .display {
  /* Smaller than the section default on purpose. The machine is the pitch, and
     a headline at full display size pushes it entirely below the fold — which
     defeats the point of moving it up here. */
  font-size: clamp(2.1rem, 5.2vw, 4rem);
  line-height: 1.02;
  margin-bottom: var(--space-5);
}

.hero__sub {
  max-width: 34rem;
  margin: 0 auto var(--space-6);
}

.actions--centred {
  justify-content: center;
}

.hero__terms {
  margin-top: var(--space-5);
  opacity: 0.72;
}

/* The primary call to action. Bigger hit area and optical weight than a
   section button, because on this page it is the only thing we are asking
   anyone to do. */
.btn--xl {
  padding: 1.05rem 2.1rem;
  font-size: 1.0625rem;
}

/* The machine sits directly under the type in the hero rather than in its own
   band, so it needs to breathe without pushing the fold too far down. */
.hero .mac {
  /* The tilted lid is drawn taller than its layout box — perspective lifts the
     top edge toward the viewer, and that overhang is not in the flow.
     32px left 13px of clearance over the pricing line at 1470x835, which
     measures as "not overlapping" and reads as covering it. Scaled to the
     viewport's height, since that is what squeezes it. */
  margin-top: clamp(44px, 7vh, 96px);
}

@media (max-width: 40rem) {
  .hero__lead--centred { margin-bottom: var(--space-6); }
  .btn--xl { width: 100%; }
  .actions--centred { flex-direction: column; align-items: stretch; }
}

/* PERF: backdrop-filter over a playing video is the most expensive thing the
   page asks a GPU to do, and phones and small laptops are where it hurts. The
   chrome is a few millimetres tall at these widths — the blur is not legible
   as blur, only as heat — so it is dropped and the fills are opened up to
   carry the same separation. */
@media (max-width: 900px) {
  .mac__menubar, .mac__widget, .mac__dock {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .mac__menubar { background: oklch(0.14 0.01 250 / 0.78); }
  .mac__widget  { background: oklch(0.16 0.012 250 / 0.76); }
  .mac__dock    { background: oklch(0.18 0.012 250 / 0.70); }
}
