/*
 * Quiet Instrument — the web side of the design system.
 *
 * Colour comes entirely from quiet-instrument-tokens.css, which is generated from
 * design/tokens.json alongside the Swift palette. Nothing here introduces a hex value.
 *
 * Fonts are self-hosted rather than fetched from Google or rsms.me. §05's footer claims
 * "nothing on this page phones home", and a webfont request is a request.
 */

@import url("/quiet-instrument-tokens.css");

/*
 * IBM Plex, self-hosted, woff2 first.
 *
 * The TTFs came from the macOS bundle, which needs TTF or OTF because CoreText cannot load
 * woff2 — Sources/LoudinkCore/Resources/Fonts must stay TTF and is not this. On the web the
 * same three faces cost 791 KB as TTF and 302 KB as woff2: Sans 525 -> 225, Mono Regular
 * 132 -> 38, Mono Medium 134 -> 39. A 489 KB saving on a page whose own CSS is 80 KB.
 *
 * The .ttf stays as a second src. woff2 is supported everywhere that matters, so the fallback
 * should never be fetched — a browser picks the first format it understands and does not
 * download the rest — but it costs nothing to leave the older format reachable.
 *
 * Converted losslessly with fontTools; no glyph was dropped. Subsetting to latin would save
 * more again, but the page uses ✓, ⏎ and ▲, which sit outside the standard latin range, so
 * that needs a glyph audit rather than a flag.
 */
@font-face {
  font-family: "IBM Plex Sans QI";
  src: url("/fonts/IBMPlexSans.woff2") format("woff2-variations"),
       url("/fonts/IBMPlexSans.ttf") format("truetype-variations");
  font-weight: 100 700;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono QI";
  src: url("/fonts/IBMPlexMono-Regular.woff2") format("woff2"),
       url("/fonts/IBMPlexMono-Regular.ttf") format("truetype");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono QI";
  src: url("/fonts/IBMPlexMono-Medium.woff2") format("woff2"),
       url("/fonts/IBMPlexMono-Medium.ttf") format("truetype");
  font-weight: 500;
  font-display: swap;
}

:root {
  --qi-sans: "IBM Plex Sans QI", system-ui, sans-serif;
  --qi-mono: "IBM Plex Mono QI", ui-monospace, monospace;

  /* §03 site grid */
  --qi-frame: 1160px;
  --qi-gutter: 40px;
  --qi-section-pad: 64px;
  --qi-copy: 680px;

  /* Sticky nav is 58px; anchors clear it with 20px of air. See html:has(.qi) below. */
  --qi-nav-height: 58px;

  /*
   * §02 names no hover, pressed or focus value, so every interaction state on this page is
   * composed from steps that already exist rather than from a new colour:
   *
   *   hover    one step up the surface ladder — bg → panel → raised → line → edge → edge-strong
   *   pressed  one step further up the same ladder (never an opacity multiplier)
   *   hairline edge-strong → label under the pointer
   *   focus    a 2px ring, 2px outside the box, so focus never reflows a row
   *   disabled mute, matching the four disabled treatments the macOS side already agrees on
   *
   * The three tints below are the same values as QuietInstrument.Tint.quietPrimaryFillHover /
   * …Pressed / …BorderHover in the Swift interaction layer: the accent carried at a higher
   * alpha, not a second accent.
   */
  --qi-quiet-primary-fill-hover: rgb(var(--qi-accent-rgb) / 0.18);
  --qi-quiet-primary-fill-pressed: rgb(var(--qi-accent-rgb) / 0.24);
  --qi-quiet-primary-border-hover: rgb(var(--qi-accent-rgb) / 0.55);
}

/*
 * Scoped to the page rather than set globally: this stylesheet is linked from the route, and
 * `:has` keeps both declarations off every other page on the site.
 *
 * scroll-padding-top: six links on this page target #pricing and the nav is sticky, so without
 * it every jump lands with the section's eyebrow and headline behind the bar.
 *
 * color-scheme: the palette is dark-only, and without this the UA renders the scrollbar and its
 * own chrome light against it.
 */
html:has(.qi) {
  scroll-padding-top: calc(var(--qi-nav-height) + 20px);
  color-scheme: dark;
  /*
   * The marketing site's styles.css puts a near-white on body, and .qi only paints its own box.
   * The box happens to be exactly the document height, so the white never shows — until macOS
   * rubber-bands past either end, and then the page flashes #f8f8f6. Painting the root as well
   * costs nothing and is the difference between a dark page and a dark page with a white seam.
   */
  background: var(--qi-bg);
}

html:has(.qi) body {
  background: var(--qi-bg);
}

/* ---------------------------------------------------------------- base */

.qi {
  background: var(--qi-bg);
  color: var(--qi-body);
  font-family: var(--qi-sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

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

.qi h1,
.qi h2,
.qi h3,
.qi p,
.qi ul,
.qi ol,
.qi figure {
  margin: 0;
  padding: 0;
}

.qi ul {
  list-style: none;
}

.qi a {
  color: inherit;
  text-decoration: none;
}

/*
 * One focus indicator for the whole page. §02 has no focus token; the macOS side draws its ring
 * in quiet-primary-border (accent at 40%), but composited on --qi-bg that lands at ~2.4:1, under
 * the 3:1 a focus indicator has to clear. A focus ring is transient and only ever one at a time,
 * so it does not spend the surface's accent action the way a filled control would — the ring is
 * drawn in full accent and keeps the app's 2px width and 2px offset.
 */
.qi a:focus-visible,
.qi button:focus-visible,
.qi input:focus-visible,
.qi [tabindex]:focus-visible {
  outline: 2px solid var(--qi-accent);
  outline-offset: 2px;
}

/* Screen-reader-only text: used for the comparison table's corner cell. */
.qi-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/*
 * The site's existing styles.css sets font-family on bare elements (h1, p, …). An element
 * selector beats inheritance from .qi, so the family has to be restated per element here or
 * the whole page silently renders in Manrope — which is exactly what happened first time.
 *
 * These are element-qualified (0,1,1), so every mono rule below is scoped `.qi .qi-*` (0,2,0)
 * to stay ahead of them.
 */
.qi h1,
.qi h2,
.qi h3,
.qi p,
.qi li,
.qi td,
.qi th,
.qi a,
.qi span,
.qi button,
.qi input {
  font-family: var(--qi-sans);
}

/* ---------------------------------------------------------------- §03 type */

.qi-display {
  font-size: clamp(40px, 5.2vw, 64px);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1.04;
  color: var(--qi-ink);
}

/*
 * Clamped rather than fixed so the three heading steps hold their order at every width:
 * display > cta > section title. At a fixed 34px this one outgrew the clamped display's floor.
 * max-width keeps the heading and the --qi-copy lead beneath it in one visual column instead of
 * running ~190px past its right edge.
 */
.qi-section-title {
  font-size: clamp(26px, 3vw, 34px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.14;
  color: var(--qi-ink);
  max-width: 880px;
}

.qi-status {
  font-size: 15px;
  font-weight: 600;
  color: var(--qi-ink);
}

.qi-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--qi-ink);
}

.qi-row {
  font-size: 13px;
  font-weight: 400;
}

.qi-caption {
  font-size: 11px;
  font-weight: 400;
  color: var(--qi-mute);
}

/* Mono small-caps group label. §03: 10 / 500 / .14em / uppercase. */
.qi .qi-group-label {
  font-family: var(--qi-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--qi-label);
}

/*
 * Anything counted, keyed, timed or literally spoken. §01.03.
 *
 * .qi-data is meta — a version string, a footer base line, a card's ordinal. §02 restricts
 * faint to exactly that. .qi-note is the same mono 11 step for the mono runs that carry a value
 * the reader has to act on (a quantity, a rule, a keyboard affordance, a refund window); those
 * are not meta and mute keeps them above 4.5:1.
 */
.qi .qi-data {
  font-family: var(--qi-mono);
  font-size: 11px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--qi-faint);
}

.qi .qi-note {
  font-family: var(--qi-mono);
  font-size: 11px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--qi-mute);
}

/*
 * §01.03 puts anything timed in mono, and every other timing on this page obeys it. The 2.1 s
 * median had been borrowing .qi-price-amount, which is a pricing style in sans.
 */
.qi .qi-figure {
  font-family: var(--qi-mono);
  font-size: 34px;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--qi-ink);
}

.qi-lead {
  font-size: 17px;
  line-height: 1.6;
  color: var(--qi-label);
  max-width: var(--qi-copy);
}

/* ---------------------------------------------------------------- layout */

.qi-frame {
  width: 100%;
  max-width: var(--qi-frame);
  margin-inline: auto;
  padding-inline: var(--qi-gutter);
}

/*
 * `padding-inline: 0` is not redundant. The marketing site's styles.css carries
 * `@media (max-width: 960px) { section { padding: 72px 20px } }` and a 620px twin. Setting only
 * `padding-block` here left the inline half of that shorthand in force, so below 960px every
 * <section> gained 20px of side padding while the <nav>, the <header> hero and the <footer> —
 * which are not `section` elements — did not.
 *
 * The result was a 20px horizontal jog: content sat at x=40 in the nav and hero, x=60 through
 * the middle of the page, then x=40 again in the footer. Every section was internally
 * consistent, which is why it read as "not quite right" rather than as a broken column.
 *
 * The gutter belongs to .qi-frame and to nothing else.
 */
.qi-section {
  padding-block: var(--qi-section-pad);
  padding-inline: 0;
}

/*
 * §05 value rhythm: alternate bg / bg-alt so no two adjacent sections match. Privacy and
 * pricing sit on panel with cards lifted to raised. Never introduce a light section — it
 * reads as a different site.
 */
/*
 * §05 asks for "alternate bg / bg-alt so no two adjacent sections match", with privacy and
 * pricing on panel. Measured on the rendered page, that rhythm does not survive contact with
 * a screen: bg is luminance 0.0066 and bg-alt is 0.0078, so every section on the page sat
 * between 0.0066 and 0.0090 — the whole document inside the bottom 1% of the luminance range,
 * and the alternation 0.0011 apart, which is below what the eye resolves on a dark display.
 * The rhythm existed in the stylesheet and not in the room.
 *
 * The fix stays inside §02: no new value, only a longer stride across steps the token set
 * already publishes.
 *
 *   alternating band   bg 0.0066 -> panel 0.0090     0.0023 apart, twice the old step
 *   feature band       bg 0.0066 -> raised 0.0134    0.0068 apart, six times the old step
 *
 * bg-alt is now unused by sections. It stays in the token set — it is generated from
 * design/tokens.json and the app may want it — but on this page it is a step too small to
 * mean anything.
 *
 * §05's other instruction still holds absolutely: no light section. The top of this ladder is
 * 0.0134, which is still deep in the dark. This makes the page legible as a sequence of
 * surfaces, not lighter.
 */
.qi-section--bg { background: var(--qi-bg); }
.qi-section--alt { background: var(--qi-panel); }
.qi-section--panel { background: var(--qi-raised); }

/*
 * Privacy and pricing are both panel and adjacent, so the alternation cannot carry the boundary.
 * A hairline does, and pricing keeps the section rhythm rather than zeroing its top padding —
 * six links on this page land on that heading.
 */
.qi-section--panel + .qi-section--panel {
  border-top: 1px solid var(--qi-line);
}

/*
 * The group label is the most repeated element on the page, and it had been given seven
 * different gaps to the content beneath it via inline margins. One rule owns the distance now,
 * so the eyebrow-to-headline relationship is the same in every section.
 */
.qi .qi-group-label + * {
  margin-top: 12px;
}

.qi-section-head {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin-bottom: 34px;
}

/* Explicit steps: the eyebrow binds tighter to its headline than the headline does to its lead. */
.qi .qi-section-head > * + * { margin-top: 14px; }
.qi .qi-section-head > .qi-group-label + * { margin-top: 8px; }

/* ---------------------------------------------------------------- nav */

.qi-nav {
  position: sticky;
  top: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--qi-bg) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--qi-line);
}

.qi-nav-inner {
  display: flex;
  align-items: center;
  gap: 24px;
  height: var(--qi-nav-height);
}

.qi-nav-links {
  display: flex;
  gap: 20px;
  margin-left: 12px;
}

/*
 * The nav bar is 58px but each link's box was only its 19px line, so on a touch screen the
 * target was a third of the bar it appears to fill. The link now claims the bar's full height
 * — the text does not move, because the padding is vertical and the bar was already taller
 * than the text.
 *
 * `align-items: center` on .qi-nav-inner would otherwise shrink these back to their content
 * height, so the stretch is explicit.
 */
.qi-nav-links a {
  display: flex;
  align-items: center;
  align-self: stretch;
  min-height: 44px;
  font-size: 13px;
  color: var(--qi-label);
  transition: color 0.12s ease-out;
}

.qi-nav-links a:hover {
  color: var(--qi-ink);
}

.qi-nav-spacer { flex: 1; }

/*
 * Below 900px the four links used to be removed outright, leaving the site with no navigation on
 * any laptop, tablet or phone while the 58px bar still carried a badge. Navigation survives and
 * the badge goes. Below 700px the links wrap to their own scrollable row rather than being
 * replaced by a disclosure, which would need script.
 *
 * The badge now reads "macOS 14+" rather than a version string, so dropping it is a slightly
 * worse trade than it was — it is a requirement, not meta. It still holds, because the same
 * requirement is stated in the CTA's spec row, which is visible at 375 and sits at the point
 * where the reader is deciding to download. Verified, not assumed.
 */
@media (max-width: 900px) {
  .qi-nav-inner { gap: 16px; }
  .qi-nav-links { gap: 14px; margin-left: 0; }
  .qi-nav-links a { font-size: 12px; }
  .qi-nav-inner > .qi-data { display: none; }
}

@media (max-width: 700px) {
  .qi-nav-inner {
    height: auto;
    flex-wrap: wrap;
    gap: 10px 12px;
    padding-block: 10px;
  }
  .qi-nav-links {
    order: 3;
    width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .qi-nav-links::-webkit-scrollbar { display: none; }
  .qi-nav-links a { white-space: nowrap; }
}

/* ---------------------------------------------------------------- mark */

.qi-mark {
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 20px;
}

/* §05: 4px bars, 5px gaps, heights 8/18/44/14/4 on a 52 grid, radius 2, flat fill. */
.qi-mark i {
  display: block;
  width: 4px;
  border-radius: 2px;
  background: var(--qi-accent);
}
.qi-mark i:nth-child(1) { height: 15.4%; }
.qi-mark i:nth-child(2) { height: 34.6%; }
.qi-mark i:nth-child(3) { height: 100%; }
.qi-mark i:nth-child(4) { height: 26.9%; }
.qi-mark i:nth-child(5) { height: 7.7%; }

/* §05 lockup: the gap is markWidth * 0.4, and the mark is 5×4px bars over 4×5px gaps = 40px. */
.qi-lockup {
  display: flex;
  align-items: flex-end;
  gap: 16px;
}

.qi .qi-wordmark {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.035em;
  color: var(--qi-ink);
}

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

/*
 * §01.02: one accent action per surface.
 *
 * Every state below is a step on an existing ladder, never an opacity multiplier:
 * secondary lifts raised → line → edge and its hairline edge-strong → label; quiet carries the
 * same accent at 12% → 18% → 24% with its border at 40% → 55%; accent, which is already a solid
 * fill and so has no surface step above it, mixes toward --qi-ink instead. Disabled drops to
 * raised / edge-strong / mute so it stops spending the accent while staying readable.
 */
.qi-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 38px;
  padding-inline: 18px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.12s ease-out, border-color 0.12s ease-out,
    color 0.12s ease-out, transform 0.06s ease-out;
}

.qi-btn:active {
  transform: translateY(1px);
}

/*
 * Qualified by `.qi` so the colour survives `.qi a { color: inherit }` at line 123.
 * That reset is (0,1,1) and a bare `.qi-btn--accent` is (0,1,0), so every button
 * rendered as an anchor — which is all three "Download for macOS" CTAs and the nav's
 * "Get LoudInk" — lost its own colour and inherited `ink`: light grey on the accent
 * fill at 1.29:1, i.e. the page's primary call to action was illegible. The `<button>`
 * plan CTAs were unaffected, which is why the same class read 9.18:1 twelve rows down.
 * Only the specificity changes here; every colour is the token it always named.
 */
.qi .qi-btn--accent {
  background: var(--qi-accent);
  color: var(--qi-on-accent);
}

.qi-btn--accent:hover {
  background: color-mix(in srgb, var(--qi-accent) 92%, var(--qi-ink));
}

.qi-btn--accent:active {
  background: color-mix(in srgb, var(--qi-accent) 84%, var(--qi-ink));
}

/* Same reason as `.qi .qi-btn--accent` above: the nav CTA is an anchor. */
.qi .qi-btn--quiet {
  background: var(--qi-quiet-primary-fill);
  border-color: var(--qi-quiet-primary-border);
  color: var(--qi-accent);
}

.qi-btn--quiet:hover {
  background: var(--qi-quiet-primary-fill-hover);
  border-color: var(--qi-quiet-primary-border-hover);
}

.qi-btn--quiet:active {
  background: var(--qi-quiet-primary-fill-pressed);
}

/* Same reason as `.qi .qi-btn--accent` above: these render as anchors too. */
.qi .qi-btn--secondary {
  background: var(--qi-raised);
  border-color: var(--qi-edge-strong);
  color: var(--qi-body);
}

.qi .qi-btn--secondary:hover {
  background: var(--qi-line);
  border-color: var(--qi-label);
  color: var(--qi-ink);
}

.qi-btn--secondary:active {
  background: var(--qi-edge);
}

.qi-btn:disabled,
.qi-btn[aria-disabled="true"] {
  background: var(--qi-raised);
  border-color: var(--qi-edge-strong);
  color: var(--qi-mute);
  cursor: default;
  transform: none;
}

.qi-btn--sm {
  height: 30px;
  padding-inline: 12px;
  font-size: 13px;
}

@media (prefers-reduced-motion: reduce) {
  .qi-btn,
  .qi-footer li a,
  .qi-nav-links a {
    transition: none;
  }
  .qi-btn:active { transform: none; }
}

/* ---------------------------------------------------------------- rows, chips, meters */

.qi-rule {
  height: 1px;
  background: var(--qi-line);
  border: 0;
}

/*
 * The OS requirement and the free allowance are qualification criteria, not meta, so this strip
 * sits at mute. The interpunct is the page's established divider — four facts separated only by
 * a flex gap read as one run-on line.
 */
/*
 * The family has to be restated on the children. .qi span (0,1,1) matches each child directly and
 * so beats the mono this container only passes down by inheritance — the same hazard the file
 * header describes. Without it the four facts render in Plex Sans and lose their tabular figures.
 */
.qi .qi-specs,
.qi .qi-specs > * {
  font-family: var(--qi-mono);
}

.qi .qi-specs {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
  font-size: 11px;
  color: var(--qi-mute);
}

.qi .qi-specs > * + *::before {
  content: "·";
  color: var(--qi-faint);
  margin-inline-end: 12px;
}

/*
 * `.qi-chip`, `.qi-chip--off` and `.qi-app-strip` used to live here. The "dictation works
 * everywhere" strip is now a component with its own stylesheet — site/public/qi-app-strip.css,
 * class prefix `qi-apps-` — because the chips carry brand marks and needed a size and a
 * typeface these rules did not have. Nothing else on the site used them, so they are gone
 * rather than left as a second, unreachable definition of the same object.
 */

/* §04 StageBar: mono label + value over a 5-8px track. */
.qi-stage {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.qi .qi-stage-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 11px;
}

/*
 * Restated on the children for the same reason as .qi-specs. These are the timings the whole
 * graphic argues about, so losing the mono also lost their tabular figures — 1461, 611 and 6 ms
 * were not aligning with one another down the column.
 */
.qi .qi-stage-head,
.qi .qi-stage-label,
.qi .qi-stage-value {
  font-family: var(--qi-mono);
}

.qi-stage-label { color: var(--qi-body); }
.qi-stage-value { color: var(--qi-ink); }

.qi-stage-track {
  height: 6px;
  border-radius: 3px;
  background: var(--qi-raised);
  overflow: hidden;
}

/*
 * min-width so a real but tiny value still reads as a bar. The typing stage is 6 / 2078 = 0.29%,
 * which rendered as an empty track — three bars, and only two of them visible.
 */
.qi-stage-fill {
  height: 100%;
  min-width: 3px;
  border-radius: 3px;
  background: var(--qi-accent);
}

/*
 * §05: the two absent rows sit below one dashed rule. The graphic exists to make a single
 * argument — three accent bars are all work — so the separator is part of the argument, not
 * decoration.
 *
 * Absent, not illegible: both halves have to be read for the argument to land, so they sit at
 * mute and the meaning is carried by form — the dashed rule above and a rule through the value.
 */
.qi-stage--absent .qi-stage-label,
.qi-stage--absent .qi-stage-value {
  color: var(--qi-mute);
}

.qi-stage--absent .qi-stage-value {
  text-decoration: line-through;
  text-decoration-color: var(--qi-faint);
}

.qi-absent-divider {
  height: 0;
  border: 0;
  border-top: 1px dashed var(--qi-edge);
  margin-block: 6px;
}

/* ---------------------------------------------------------------- cards */

.qi-card {
  background: var(--qi-panel);
  border: 1px solid var(--qi-edge);
  border-radius: 9px;
  padding: 20px;
}

/* §05: on the panel sections, cards lift to raised so they stay distinguishable. */
/*
 * The feature band moved up to `raised`, so a card at `raised` would now vanish into it. §05's
 * intent is that cards lift off their section — one step, whatever the section is standing on.
 */
.qi-section--panel .qi-card {
  background: var(--qi-line);
  border-color: var(--qi-edge-strong);
}

/* Same reason on the alternating band, which is now `panel`. */
.qi-section--alt .qi-card {
  background: var(--qi-raised);
  border-color: var(--qi-edge-strong);
}

/* Nothing inside a card was measure-capped, so a wide card produced ~120-character lines. */
.qi-card p,
.qi-phrase-does {
  max-width: 62ch;
}

/* The pricing plans, so three CTAs sit on one baseline however the feature lists wrap. */
.qi-plan {
  display: flex;
  flex-direction: column;
}

.qi-plan > .qi-btn {
  margin-top: auto;
  width: 100%;
}

.qi-grid {
  display: grid;
  gap: 18px;
}

.qi-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.qi-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/*
 * Both grids used to drop from four (and three) columns straight to one at 900px, so there was
 * no width between 640 and 900 at which the layout was comfortable: at 899px a phrase group ran
 * the full 820px measure, one pixel earlier it was 191px. Two-up stages fill the gap.
 */
@media (max-width: 1000px) {
  .qi-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  .qi-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/*
 * The speed graphic's stage column spans two of the three tracks. Once the grid is a single
 * column the span has to be released, or it invents an implicit second column and the figure
 * beside it collapses to a sliver.
 */
.qi-span-2 { grid-column: span 2; }

@media (max-width: 640px) {
  .qi-grid--3,
  .qi-grid--4 { grid-template-columns: 1fr; }
  .qi-span-2 { grid-column: auto; }
}

/* ---------------------------------------------------------------- phrase table */

.qi-phrases {
  display: flex;
  flex-direction: column;
}

.qi-phrase {
  display: grid;
  grid-template-columns: minmax(0, 260px) minmax(0, 1fr);
  gap: 16px;
  padding-block: 11px;
  border-top: 1px solid var(--qi-line);
}

.qi-phrase:last-child { border-bottom: 1px solid var(--qi-line); }

.qi .qi-phrase-say {
  font-family: var(--qi-mono);
  font-size: 12px;
  color: var(--qi-ink);
}

.qi-phrase-does {
  font-size: 13px;
  color: var(--qi-label);
}

/*
 * `.qi-phrase--step` used to live here, for the three rows of the approval card. That card is
 * now inside the computer-use rendering, which draws its own steps — see
 * _components/ComputerUseRendering.tsx and the `.qi-gh-step*` rules in qi-renderings.css.
 */

/*
 * A phrase row is two columns only when it has the width for them. Inside the 4-up grid each
 * cell is ~250px, so a 260px phrase column plus the effect overflows and the two collide —
 * stack them there instead.
 */
.qi-grid--4 .qi-phrase,
.qi-grid--3 .qi-phrase {
  grid-template-columns: 1fr;
  gap: 3px;
}

/* A phrase and its effect stack below 700px; two columns in a 335px track collide. */
@media (max-width: 700px) {
  .qi-phrase { grid-template-columns: 1fr; gap: 4px; }
}

/* ---------------------------------------------------------------- comparison */

/*
 * The one element on the page that can genuinely exceed a phone viewport, so it scrolls inside
 * its own container. The site's global styles.css sets html { overflow-x: hidden }, which would
 * otherwise clip the overflow silently and put it out of reach.
 */
.qi-scroll {
  overflow-x: auto;
}

.qi-compare {
  width: 100%;
  min-width: 420px;
  border-collapse: collapse;
  font-size: 13px;
}

.qi-compare th,
.qi-compare td {
  text-align: left;
  padding: 11px 12px;
  border-top: 1px solid var(--qi-line);
}

.qi .qi-compare caption {
  caption-side: top;
  text-align: left;
  padding-bottom: 12px;
}

.qi .qi-compare thead th {
  border-top: 0;
  font-family: var(--qi-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--qi-label);
}

/* The row label is a <th scope="row">; it stays visually a label, not a heading. */
.qi-compare tbody th:first-child {
  color: var(--qi-body);
  font-weight: 400;
}

/*
 * Amber, not grey. This column is the whole argument of the section — where your audio, your
 * text and the model go when the work happens somewhere else — and in mute it read as a
 * footnote beside the column it is supposed to be losing to.
 *
 * `attention` rather than `accent` on purpose. §02 defines attention as "needs you" and accent
 * as ready/live/primary; a row saying your audio is uploaded is something to notice, not
 * something to do, so this costs the surface nothing from its one accent action. Not `fault`
 * either: cloud dictation is not broken or destructive, it is just the trade this page is
 * arguing against.
 */
.qi-compare .qi-them { color: var(--qi-attention); }

/*
 * Five rows of static comparison text are neither an action nor a live signal, so they do not
 * take accent — the top ink step plus the weight change already wins the column, and the panel
 * keeps its accent budget for something that can be clicked.
 */
.qi-compare .qi-us { color: var(--qi-ink); font-weight: 600; }

/* ---------------------------------------------------------------- pricing */

.qi-price {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-block: 10px 4px;
}

.qi-price-amount {
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--qi-ink);
  font-variant-numeric: tabular-nums;
}

/*
 * The period is the other half of the price — the whole pricing model is a shared action
 * allowance and it lives only in this string. It is not meta. Against a 34px ink amount, body
 * still reads as subordinate.
 */
.qi .qi-price-period {
  font-family: var(--qi-mono);
  font-size: 12px;
  color: var(--qi-body);
}

.qi-plan-features {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-block: 16px;
  font-size: 13px;
  color: var(--qi-label);
}

/* §05: "most picked" is a mark, not a saturated badge. */
.qi .qi-plan-mark {
  font-family: var(--qi-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--qi-accent);
}

/*
 * The featured plan carried its whole distinction in a border, which on a raised card against a
 * raised band is a very quiet way to say "most people pick this". A wash of the accent at 6%
 * lifts it off its neighbours without becoming a second accent action — the same device §02
 * already sanctions for the quiet primary at 12%, at half the strength because this is a
 * surface rather than a control.
 */
/*
 * Scoped to the band it lives on. `.qi-section--panel .qi-card` sets the card fill at (0,2,0);
 * a bare `.qi-plan--featured` is (0,1,0) and loses, so the wash silently did nothing.
 */
.qi-section--panel .qi-plan--featured {
  border-color: var(--qi-quiet-primary-border);
  background:
    linear-gradient(rgb(var(--qi-accent-rgb) / 0.06), rgb(var(--qi-accent-rgb) / 0.06)),
    var(--qi-line);
}

/* ---------------------------------------------------------------- CTA */

/*
 * §05: the CTA returns to bg and earns its arrival with a 56px headline and 96px of air.
 */
/* Also a <section>, so it took the same leaked inline padding. See .qi-section. */
.qi-cta {
  background: var(--qi-bg);
  padding-block: 96px;
  padding-inline: 0;
  text-align: center;
}

/*
 * Clamped so it always resolves one step below the display. At a fixed 56px it overtook the h1
 * on any window under 1077px, and was 40% larger than it at the display's clamp floor.
 */
.qi-cta h2 {
  font-size: clamp(34px, 4.6vw, 56px);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1.05;
  color: var(--qi-ink);
  max-width: 880px;
  margin-inline: auto;
}

.qi-cta-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-block: 26px 20px;
}

.qi-cta .qi-specs,
.qi-specs--center { justify-content: center; }

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

/* On the same ladder as the sections above it — bg-alt left the footer stranded between two
 * steps, close enough to the CTA's bg to read as a rendering fault rather than a boundary. */
.qi-footer {
  background: var(--qi-panel);
  border-top: 1px solid var(--qi-line);
  /* 48, on the 32 / 48 / 64 / 96 scale. 44 was a value that agreed with nothing else. */
  padding-block: 48px;
}

.qi-footer-grid {
  display: grid;
  grid-template-columns: 2fr repeat(4, 1fr);
  gap: 28px;
}

/* The rule on .qi-group-label + * already owns this distance. */

.qi-footer li {
  margin-bottom: 5px;
  font-size: 13px;
  color: var(--qi-label);
}

/*
 * These sit in link-shaped columns under link-shaped headings, so they have to behave as links:
 * clickable, focusable, and answering the pointer. inline-block gives each one a real target
 * instead of a bare text run.
 */
.qi .qi-footer li a {
  display: inline-block;
  padding-block: 2px;
  color: var(--qi-label);
  transition: color 0.12s ease-out;
}

.qi .qi-footer li a:hover {
  color: var(--qi-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.qi-footer-base {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-top: 32px;
  padding-top: 18px;
  border-top: 1px solid var(--qi-line);
}

/* .qi-data sits on the row, not its spans; restated so the children keep the mono. */
.qi .qi-footer-base > * {
  font-family: var(--qi-mono);
}

@media (max-width: 900px) {
  .qi-footer-grid { grid-template-columns: 1fr 1fr; }
}

/* ---------------------------------------------------------------- receipt line */

/* §05: both product renderings carry a mono receipt line. Never a stock screenshot. */
.qi .qi-receipt {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--qi-mono);
  font-size: 11px;
  color: var(--qi-accent);
}

/*
 * A tick beside a static claim is neither an action nor a live signal, so it does not take
 * accent — three of them on one surface is what erodes the accent's meaning everywhere else.
 */
.qi .qi-receipt--quiet {
  color: var(--qi-body);
}

/*
 * `.qi-transcript-pill` used to live here. §05 asks for the transcript pill inside recreated
 * desktop chrome rather than on a plain card, so it is now `.qi-mail-pill` in
 * qi-renderings.css, floating over the browser window where the HUD actually is.
 */

/* ---------------------------------------------------------------- small viewports */

/*
 * Neither the gutter nor the section padding used to move at any width: on a 375px phone the
 * 40px gutters took 21% of the viewport. The nav wraps to two rows at this width, so the anchor
 * offset grows with it.
 */
@media (max-width: 700px) {
  :root {
    --qi-gutter: 20px;
    --qi-section-pad: 44px;
  }

  html:has(.qi) {
    scroll-padding-top: 116px;
  }

  .qi-cta {
    padding-block: 64px;
  }

  .qi-cta-actions,
  .qi-footer-base {
    gap: 10px;
  }

  .qi-footer-grid {
    gap: 22px;
  }
}

/* ---------------------------------------------------------------- real screenshots */

/*
 * §05 "the instrument" — Retina captures of the shipped app, framed in the same lighting
 * model as the two recreated plates: `panel` surface, `edge-strong` bound, the renderings'
 * deep plate shadow, plus a 1px inner top highlight so the glass reads as a surface rather
 * than a hole in the page. Colour stays inside §02 — the photographs carry their own.
 */
.qi .qi-shots {
  display: grid;
  grid-template-columns: 2.4fr 1fr;
  gap: 28px;
  align-items: center;
  margin-top: 40px;
}

.qi .qi-shot {
  margin: 0;
  min-width: 0;
}

.qi .qi-shot img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
  border: 1px solid var(--qi-edge-strong);
  background: var(--qi-panel);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 0.045),
    0 30px 70px -28px rgb(0 0 0 / 0.65);
}

/*
 * The panel capture stops mid-surface; fading the last 48px finishes the crop so it reads
 * as a deliberate excerpt, not a torn edge. The mask sits on the img, not the figure, so
 * the caption underneath keeps full ink.
 */
.qi .qi-shot--panel img {
  -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 48px), transparent);
  mask-image: linear-gradient(to bottom, black calc(100% - 48px), transparent);
  border-bottom: 0;
}

.qi .qi-shot .qi-caption {
  display: block;
  margin-top: 12px;
}

@media (max-width: 900px) {
  .qi .qi-shots {
    grid-template-columns: 1fr;
    gap: 40px;
  }

  /* Centered and narrower than the column: a 340pt panel stretched full-width would
     blur; its natural size is its honest size. */
  .qi .qi-shot--panel {
    max-width: 340px;
    margin-inline: auto;
  }
}
