/* Docsroom marketing site — the drawing follows marketing/DESIGN.md.

   EVERY size, colour, measure, radius and duration is a token in :root below.
   Nothing further down this file, and nothing in a page, may write a raw font
   size, a hex colour or a width. `npm run check:site-design` fails the build
   if one appears. That is the whole point: change a token here and the change
   lands on all 76 pages at once.

   The ladder is the product's own — 30 · 24 · 17 · 16 · 15 · 14 · 12 — with
   two display sizes above it that a marketing page needs and an app does not.
   Emphasis is a weight, never an extra size. */

@font-face { font-family: 'Colfax'; font-weight: 400; font-style: normal; font-display: swap; src: url('/assets/fonts/ColfaxWebRegular.woff2') format('woff2'); }
@font-face { font-family: 'Colfax'; font-weight: 500; font-style: normal; font-display: swap; src: url('/assets/fonts/ColfaxWebMedium.woff2') format('woff2'); }
@font-face { font-family: 'Colfax'; font-weight: 700; font-style: normal; font-display: swap; src: url('/assets/fonts/ColfaxWebBold.woff2') format('woff2'); }

:root {
  /* ── Type ────────────────────────────────────────────────────────────────
     Two display sizes, then the product's ladder unchanged from 30 down. */
  --font: 'Colfax', 'Hanken Grotesk', 'Public Sans', -apple-system, 'Helvetica Neue', sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --t-display: clamp(38px, 5.6vw, 60px);   /* page h1 */
  --t-title: clamp(28px, 3.4vw, 38px);     /* section h2 */
  --t-price: 44px;                         /* a plan's figure */
  --t-head: 30px;                          /* the product ladder's top */
  --t-sub: 24px;                           /* article h2, caption h2 */
  --t-lead: 20px;                          /* lead paragraph, h3, wordmark */
  --t-body: 17px;                          /* body, button, row name */
  --t-ui: 16px;                            /* navigation */
  --t-sm: 15px;                            /* supporting text, field label */
  --t-chip: 14px;                          /* tag, code */
  --t-meta: 12px;                          /* row meta, table heading, hint */
  --t-micro: 10px;                         /* initials in a 22px avatar */
  /* Off the ladder on purpose: the 1200x630 social card is one fixed image at
     one fixed size, read as a thumbnail. Declared here so it is still one
     place, and used only by src/og.html. */
  --t-og-title: 58px; --t-og-lead: 22px; --t-og-brand: 26px; --t-og-demo: 16px;
  --w-regular: 400; --w-medium: 500; --w-bold: 700;
  --lh-title: 1.02; --lh-tight: 1.12; --lh-snug: 1.3;
  --lh-lead: 1.5; --lh-body: 1.6; --lh-meta: 1.4;
  --tr-display: -.03em; --tr-title: -.02em; --tr-tight: -.01em; --tr-none: 0;

  /* ── Colour ──────────────────────────────────────────────────────────────
     Two greys and one hairline, as the product. Violet is the accent and it
     is the product's own tile violet, so a screenshot sits in its own page.
     Black stays the one action; coral stays destructive. */
  --ground: #fbfafb; --paper: #ffffff; --sunken: #f3f1f3;
  --ground-veil: rgba(251, 250, 251, .86);   /* the sticky head, over the page */
  --line: #f3f1f3; --line-2: #e6e3e7;
  --ink: #000000; --ink-2: #000000; --muted: #666566; --on-dark: #ffffff;
  --on-dark-2: rgba(255, 255, 255, .72); --on-dark-line: rgba(255, 255, 255, .42);
  --on-dark-wash: rgba(255, 255, 255, .08);
  --violet: #8162a4;        /* 4.98:1 on white — links, marks, accents */
  --violet-ink: #6b4b8f;    /* 6.93:1 — a violet word on a violet tint */
  --violet-tint: #f3eef7; --violet-line: #e4dbec; --violet-deep: #4b3266;
  --violet-wash: #e9dff2;   /* the hero's ground, a shade past the tint */
  --coral: #e76c7a; --coral-tint: #fef2f4;
  /* Darkened 9 September: the old #2fa236 was 3.31:1 on white, which fails for
     the bold "Yes" in a comparison table, and 2.90 on the violet tint, which
     fails even for a tick read as a mark. This clears 5.41 and 4.74. */
  --green: #217a2a; --green-tint: #ecfdf7;
  --orange: #ef7c50; --orange-ink: #bd4e10; --orange-tint: #fff3ed;
  --mac-red: #ff5f57; --mac-amber: #febc2e; --mac-green: #28c840;

  /* ── Measure ─────────────────────────────────────────────────────────────
     Every page is this wide. Nothing sets its own. */
  --measure-page: 1120px;   /* the container */
  --measure-shot-tall: 642px;  /* a tall shot's own size: 640 of app + its frame */
  --measure-shot-wide: 1240px; /* a picture may be a little wider than the prose */
  --measure-demo: 480px;  /* the hero's example: its five choices are 474px on one line */
  --measure-shot-square: 440px; /* a drawn screen's WIDTH, the same everywhere.
                                   A 520 square until 10 Sep 2026, when Kish
                                   chose a fixed width with the height following
                                   the content ("c") over a smaller square: any
                                   square that fits the fullest picture stretches
                                   every other one. Illustrations share it. */
  --measure-prose: 720px;   /* an article's text column */
  --measure-head: 640px;    /* a section head */
  --measure-copy: 34em;     /* a paragraph inside a wider column */
  --measure-copy-tight: 30em; --measure-copy-wide: 44em;
  --measure-title: 14em; --measure-title-tight: 12em;
  --measure-form: 520px;    /* a form's fields */
  --measure-art-square: 360px;   /* a 1:1 illustration inside a prose column */
  --gutter: 24px;
  --section-y: 88px; --section-y-sm: 64px; --section-y-md: 80px; --section-y-lg: 96px;

  /* ── Shape and motion ────────────────────────────────────────────────── */
  --r-hair: 2px; --r-xs: 4px; --r-sm: 6px; --r: 8px; --r-card: 12px; --r-frame: 14px; --r-band: 20px; --r-phone: 36px; --r-screen: 28px; --r-pill: 999px;
  --dur-fast: .15s; --dur: .25s; --dur-slow: .7s;
  --ease: cubic-bezier(.2, .7, .2, 1);
  --lift: translateY(-2px);
  --shadow-lift: 0 10px 30px rgba(75, 50, 102, .10);
  --shadow-frame: 0 18px 50px rgba(75, 50, 102, .09);
}

*, *::before, *::after { box-sizing: border-box; }
html { font-synthesis: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body { margin: 0; font: var(--w-regular) var(--t-body)/var(--lh-body) var(--font); color: var(--ink); background: var(--ground); }
body.menu-open { overflow: hidden; }
img, svg { max-width: 100%; height: auto; }
/* Without this every figure on the site is inset by the browser's default
   40px each side, which quietly narrows every screenshot on 76 pages. */
figure { margin: 0; }
a { color: var(--violet); text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; border-radius: var(--r-sm); }
h1, h2, h3, h4 { margin: 0; font-weight: var(--w-bold); letter-spacing: var(--tr-title); line-height: var(--lh-tight); }

/* A control name inside running text — "choose Withdraw link", "tap Ask again".
   The pages mark 86 of these with <em>, and every one of them was rendering as
   plain body text: Colfax is licensed in three upright weights and no italic,
   and `font-synthesis: none` stops the browser faking an oblique, so the tag
   asked for a face that does not exist and got the regular one back. Naming a
   button without looking any different from the sentence around it is the same
   as not naming it. In Hairline emphasis is a weight, so that is what this is. */
em { font-style: normal; font-weight: var(--w-medium); }
h1 { font-size: var(--t-display); letter-spacing: var(--tr-display); line-height: var(--lh-title); }
h2 { font-size: var(--t-title); }
h3 { font-size: var(--t-lead); font-weight: var(--w-bold); letter-spacing: var(--tr-tight); line-height: var(--lh-snug); }
p { margin: 0; }
p + p { margin-top: 1em; }
.container { width: min(var(--measure-page), 100% - 2 * var(--gutter)); margin-inline: auto; }
.narrow { width: min(var(--measure-prose), 100%); }
.skip { position: absolute; left: 16px; top: -60px; padding: 10px 14px; background: var(--ink); color: var(--on-dark); border-radius: var(--r); z-index: 100; }
.skip:focus { top: 12px; }
.muted { color: var(--muted); }
.lead { font-size: var(--t-lead); line-height: var(--lh-lead); color: var(--ink-2); }
.small { font-size: var(--t-sm); }
.meta { font-size: var(--t-sm); color: var(--muted); }
/* An eyebrow over a heading: the site's small violet mark.

   It may be written as a <span> or a <p>. Five rules below style the body
   paragraph inside a section head, a split, a feature, a threes column and
   prose, and each of them out-specifies a single class — so each of them
   excludes .kicker rather than this rule fighting them. Write it either way. */
.kicker { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 14px; font-size: var(--t-meta); font-weight: var(--w-bold); letter-spacing: .08em; text-transform: uppercase; color: var(--violet-ink); }
.kicker::before { content: ''; width: 18px; height: 2px; border-radius: var(--r-hair); background: var(--violet); }

/* Buttons */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 44px; padding: 0 18px; border-radius: var(--r); border: 1px solid var(--sunken); background: var(--sunken); color: var(--ink); font: inherit; font-weight: var(--w-bold); text-decoration: none; cursor: pointer; white-space: nowrap; transition: background var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast); }
.btn:hover { background: var(--violet-tint); border-color: var(--violet-line); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn-primary, .btn-light { transition: background var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast), box-shadow var(--dur); }
.btn-primary:hover, .btn-light:hover { transform: var(--lift); box-shadow: var(--shadow-lift); }
.btn-primary:active, .btn-light:active { transform: translateY(1px); box-shadow: none; }
@media (prefers-reduced-motion: reduce) {
  .btn-primary:hover, .btn-light:hover, .pack:hover, .help-card:hover { transform: none; }
}
.btn-primary { background: var(--ink); border-color: var(--ink); color: var(--on-dark); }
.btn-primary:hover { background: var(--ink); border-color: var(--ink); }
.btn-quiet { border-color: transparent; background: transparent; }
.btn-quiet:hover { background: var(--sunken); }
.btn-lg { height: 52px; padding: 0 24px; font-size: var(--t-body); }
.btn-light { background: var(--paper); border-color: var(--on-dark); color: var(--ink); }
.btn-light:hover { background: var(--sunken); }
.btn-ghost-light { background: transparent; border-color: var(--on-dark-line); color: var(--on-dark); }
.btn-ghost-light:hover { background: var(--on-dark-wash); }

/* Header */
.site-head { position: sticky; top: 0; z-index: 50; background: var(--ground-veil); backdrop-filter: saturate(160%) blur(12px); -webkit-backdrop-filter: saturate(160%) blur(12px); border-bottom: 1px solid var(--line); }
.site-head-inner { height: 64px; display: flex; align-items: center; gap: 28px; }
.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); text-decoration: none; font-weight: var(--w-bold); font-size: var(--t-lead); letter-spacing: -.01em; }
.brand:hover { text-decoration: none; }
.brand-mark { color: var(--ink); flex: none; }
.site-nav { display: flex; align-items: center; gap: 2px; flex: 1; }
.site-nav > a { padding: 8px 12px; border-radius: var(--r); color: var(--ink-2); text-decoration: none; font-size: var(--t-ui); font-weight: var(--w-regular); }
.site-nav > a:hover { color: var(--ink); background: var(--sunken); }
.site-nav > a[aria-current] { color: var(--ink); font-weight: var(--w-medium); box-shadow: inset 0 -2px 0 var(--violet); border-radius: 0; }
.site-nav-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
.menu-toggle { display: none; margin-left: auto; width: 44px; height: 44px; border: 0; background: transparent; border-radius: var(--r); cursor: pointer; flex-direction: column; justify-content: center; align-items: center; gap: 5px; }
.menu-toggle span { display: block; width: 20px; height: 2px; background: var(--ink); border-radius: var(--r-hair); transition: transform var(--dur-fast), opacity var(--dur-fast); }
.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Sections */
section { padding: var(--section-y) 0; }
section + section { border-top: 1px solid var(--line); }
.page-head + section { padding-top: 0; }
.section-head { max-width: var(--measure-head); margin-bottom: 48px; }
.section-head p:not(.kicker) { margin-top: 16px; color: var(--ink-2); font-size: var(--t-lead); line-height: var(--lh-lead); }
.foot-note { margin-top: 20px; }
.section-head.center { margin-inline: auto; text-align: center; }
.rule { border: 0; border-top: 1px solid var(--line); margin: 0; }
/* A section that should read as a different room. Used sparingly: two on a
   long page, never two in a row. */
section.tinted { background: var(--violet-tint); }
section.tinted + section, section + section.tinted { border-top-color: var(--violet-line); }
section.tinted .shot, section.tinted .pack, section.tinted .help-card,
section.tinted .facts, section.tinted .plan { background: var(--paper); }
/* Every hairline on this site is --line, which is #f3f1f3 and therefore
   invisible on the tint. Rather than list the dozen rules that draw one,
   move the token: column rules, feature dividers, table cells, the log and
   the steps all read it. */
section.tinted { --line: var(--violet-line); }
/* A link's violet clears 4.98:1 on white but only about 4.6 on the tint, so
   the darker ink takes over inside a tinted section. */
section.tinted a { color: var(--violet-ink); }
/* Violet on the deep violet band is 2.17:1, so keyboard focus on the two
   buttons in the call to action was all but invisible. White is 10.78. */
.cta-band :focus-visible { outline-color: var(--on-dark); }
/* A card inside a tinted band keeps its ink title: the link rule above is
   (0,2,1) and .rel/.pack/.help-card set their colour at (0,1,0), so without
   this every card heading in a band turned violet. */
section.tinted .rel, section.tinted .pack, section.tinted .help-card { color: var(--ink); }
/* The section straight after a page head has no top padding, which is right
   for a screenshot and wrong for a coloured band starting flush against it. */
.page-head + section.tinted { padding-top: var(--section-y); }
/* Two runs of three, one under the other, need the gap the grid does not give
   them. */
.threes + .threes { margin-top: 32px; }

/* Hero */
.hero { position: relative; padding: var(--section-y-lg) 0 72px; isolation: isolate; }
.hero::before { content: ''; position: absolute; inset: -120px 0 auto; height: 620px; z-index: -1; pointer-events: none;
  background:
    radial-gradient(820px 460px at 76% 14%, var(--violet-wash), transparent 66%),
    radial-gradient(620px 400px at 4% 2%, var(--violet-tint), transparent 70%); }
.hero-grid { display: grid; grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr); gap: 64px; align-items: center; }
.hero h1 { margin-bottom: 22px; max-width: var(--measure-title-tight); }
.hero .lead { max-width: var(--measure-copy-tight); }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }
/* The tick sits on the first line. Centred, it drifted to the middle of a
   block that wraps to two lines at 1280 and three on a phone, so the one mark
   on the page that should be beside "The person you are asking" sat beside
   "password, and never sees". Same fault as the ticks in a list had. */
.hero-note { margin-top: 22px; color: var(--muted); font-size: var(--t-sm); display: flex; align-items: flex-start; gap: 10px; }
.hero-note svg { flex: none; margin-top: 3px; }
.hero-note svg { color: var(--green); flex: none; }

/* The hero example switcher: one quiet row of choices above the card. */
.demo-col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.demo-switch { display: flex; flex-wrap: wrap; gap: 6px; }
.demo-switch button { height: 30px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--paper); color: var(--muted); font: var(--w-medium) var(--t-chip) var(--font); cursor: pointer; white-space: nowrap; transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast); }
.demo-switch button:hover { color: var(--ink); border-color: var(--line-2); }
.demo-switch button[aria-selected="true"] { background: var(--ink); border-color: var(--ink); color: var(--on-dark); }
.demo-caption { font-size: var(--t-meta); color: var(--muted); }
/* The hero example stands on the same stage as every picture, and is as small
   as its choices allow: the five of them are 474px on one line. */
.demo-col { max-width: var(--measure-demo); }
@media (min-width: 901px) { .demo-col { margin-left: auto; } }
.ui-stage.demo-stage { width: 100%; }
.ui-stage > .demo { position: relative; z-index: 1; }
/* The card ends in its reminder band, whose clock sat 3px above the drawing's
   reach, so the hero's drawing sits 6px lower than a picture's. It then hangs
   about 39px under the card, and the caption, which sat 12px under the card,
   had the letter over "Five trades". */
.ui-stage.demo-stage .ui-motif-main { bottom: -42px; }
@media (max-width: 899px) { .ui-stage.demo-stage .ui-motif-main { bottom: -34px; } }
.ui-stage.demo-stage + .demo-caption { margin-top: 44px; }

/* The demonstration card in the hero */
.demo { background: var(--paper); border: 1px solid var(--line-2); border-radius: var(--r-frame); box-shadow: var(--shadow-frame); overflow: hidden; font-size: var(--t-sm); line-height: 1.45; }
.demo-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--line); }
.demo-head strong { font-size: var(--t-lead); font-weight: var(--w-medium); }
.demo-head small { display: block; color: var(--muted); font-size: var(--t-meta); margin-top: 2px; }
.demo-count { font-size: var(--t-meta); color: var(--muted); }
.demo-section { padding: 8px 18px; background: var(--ground); color: var(--muted); font-size: var(--t-meta); font-weight: var(--w-medium); border-bottom: 1px solid var(--line); }
.demo-row { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; gap: 14px; align-items: center; padding: 11px 18px; border-bottom: 1px solid var(--line); }
.demo-num { width: 28px; height: 28px; border-radius: var(--r); background: var(--sunken); color: var(--muted); font-size: var(--t-meta); font-weight: var(--w-medium); display: grid; place-items: center; }
.demo-row-title { font-weight: var(--w-medium); }
.demo-row-sub { color: var(--muted); font-size: var(--t-meta); }
.demo-status { position: relative; font-size: var(--t-meta); font-weight: var(--w-medium); color: var(--muted); white-space: nowrap; min-width: 112px; text-align: right; }
/* A status is the same filled tag the squares use, so the hero and the
   pictures below it agree about what "complete" looks like. */
.demo-status .from, .demo-status .to { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; border-radius: var(--r-sm); background: var(--sunken); color: var(--ink-2); }
.demo-status .to { position: absolute; right: 0; top: 0; opacity: 0; }
.demo-status .to.review { background: var(--sunken); color: var(--ink-2); }
.demo-status .to.complete { background: var(--sunken); color: var(--ink-2); }
.demo-status .to.answered { background: var(--sunken); color: var(--ink-2); }
.demo-reply { margin: 0 18px 12px 60px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--r); background: var(--ground); }
.demo-reply-head { display: flex; align-items: center; gap: 8px; font-size: var(--t-meta); color: var(--muted); margin-bottom: 4px; }
.demo-avatar { width: 22px; height: 22px; border-radius: 50%; background: var(--violet-tint); color: var(--violet-ink); font-size: var(--t-micro); font-weight: var(--w-medium); display: grid; place-items: center; }
.demo-files { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.demo-file { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px 5px 8px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); font-size: var(--t-meta); }
.demo-file svg { color: var(--muted); }
.demo-foot { display: flex; align-items: flex-start; gap: 10px; padding: 11px 18px; background: var(--ground); color: var(--muted); font-size: var(--t-meta); }
/* Same as the hero note: the clock belongs on the first line, not between the
   two the sentence wraps to on a phone. */
.demo-foot svg { flex: none; margin-top: 3px; }
.demo-foot svg { color: var(--muted); }

/* The sequence. Every timed element carries --t; the card's `play` class
   starts the clock, and removing/adding it replays from the top. */
.demo [data-t] { opacity: 0; }
/* `play` is on the body, not the card. Written as `.demo.play`, the reply and
   the footer never ran: they stayed at opacity 0 and left a 135px and a 43px
   hole in the hero for everyone with motion on. */
.demo-body.play :is(.demo-row, .demo-reply, .demo-foot) { animation: rise var(--dur-slow) var(--ease) both; animation-delay: var(--t); }
.demo-body.play .demo-status .from { animation: drop var(--dur) ease both; animation-delay: var(--t); }
.demo-body.play .demo-status .to { animation: rise var(--dur) var(--ease) both; animation-delay: var(--t); }
.demo-body.play .demo-reply .demo-file { animation: rise var(--dur) var(--ease) both; animation-delay: var(--t); }
.demo-body.play .demo-tick path { stroke-dasharray: 24; stroke-dashoffset: 24; animation: draw var(--dur) var(--ease) both; animation-delay: var(--t); }
.demo-body.still [data-t], .demo-body.still .demo-status .to { opacity: 1; animation: none; }
.demo-body.still .demo-status .from { display: none; }
/* The finished frame keeps what never changed. Row four is still awaiting a
   reply when the clock stops: its empty `to` hid its `from`, and on a phone,
   where a heavier rule shows every `to`, it drew as an empty grey stub. The
   tick on "Complete" stayed undrawn, because the drawing-on rule set its dash
   and nothing in the still frame took it back. */
.demo-body.still .demo-status .from:has(+ .to:empty) { display: inline-flex; }
.demo-body.play .demo-status .to:empty { display: none; }
.demo-body.still .demo-tick path { stroke-dasharray: none; stroke-dashoffset: 0; animation: none; }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes drop { to { opacity: 0; transform: translateY(-6px); } }
@keyframes draw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  /* The files in the reply carry `--t` but not `data-t`, so this reset missed
     them: a reader who asks for no motion got an empty reply bubble for two
     seconds and then a fade. Everything the sequence animates has to be listed
     here, or the still frame is not the finished picture. */
  .demo [data-t], .demo .demo-status .to, .demo .demo-file { opacity: 1 !important; animation: none !important; }
  .demo .demo-status .from { display: none; }
  .demo .demo-tick path { stroke-dasharray: none; animation: none !important; }
}
/* A request with nothing to say about it says nothing. Before the status was a
   filled tag an empty one was invisible; now it would paint a grey stub. */
.demo-status .to:empty { display: none; }

/* Drawn artwork, which is not a screenshot and must not be framed like one.
   No border and no window chrome: a screenshot is evidence, an illustration
   is a breath. `.art-square` caps a 1:1 image so it cannot fill a whole prose
   column and become a wall. */
.art { margin: 28px 0; }
.art img { display: block; width: 100%; border-radius: var(--r-card); }
.art-square img { width: min(var(--measure-art-square), 60%); margin-inline: auto; }
.art figcaption { margin-top: 10px; font-size: var(--t-sm); color: var(--muted); }

/* Screenshot frames: a line, never a shadow, and a quiet address bar so a
   picture of the product reads as the product and not as a poster. */
.shot { border: 1px solid var(--line); border-radius: var(--r-frame); overflow: hidden; background: var(--paper); box-shadow: var(--shadow-frame); }
/* A cropped detail is not a whole window, so its bar carries the lights
   without claiming an address. */
.shot.detail .shot-bar { justify-content: flex-start; }
.shot-bar { display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 14px; border-bottom: 1px solid var(--line); background: var(--ground); }
.shot-bar i { width: 11px; height: 11px; border-radius: 50%; background: var(--line-2); }
.shot-bar i:nth-of-type(1) { background: var(--mac-red); }
.shot-bar i:nth-of-type(2) { background: var(--mac-amber); }
.shot-bar i:nth-of-type(3) { background: var(--mac-green); }
.shot-bar span { margin-left: 8px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-meta); color: var(--muted); padding: 3px 10px; border-radius: var(--r-sm); background: var(--paper); border: 1px solid var(--line); }
.shot img { display: block; width: 100%; }
.shot-phone { width: 300px; border: 1px solid var(--line-2); border-radius: var(--r-phone); padding: 10px; background: var(--paper); }
.shot-phone > div { border-radius: var(--r-screen); overflow: hidden; border: 1px solid var(--line); }
.shot-phone img { display: block; width: 100%; }
.reveal { opacity: 0; transform: translateY(14px); transition: opacity var(--dur-slow) var(--ease) var(--reveal-delay, 0ms), transform var(--dur-slow) var(--ease) var(--reveal-delay, 0ms); }
.reveal.in { opacity: 1; transform: none; }
/* A screenshot is the thing the page is showing, so it arrives with a little
   more travel and a scale that settles rather than snapping. */
.shot.reveal { transform: translateY(22px) scale(.985); transform-origin: 50% 0; }
.shot.reveal.in { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal, .shot.reveal { opacity: 1; transform: none; transition: none; }
}

/* THE SCREEN, DRAWN. Not a screenshot and not a cartoon: the real type, the
   real colours and the real layout, built from the same tokens the product is,
   with everything the point does not need taken out.

   ONE LADDER, and it is the app's own. A title is 17 medium, a meta line is 15
   regular in muted ink, a chip is 14 medium. Nothing else. A finished row is
   NOT greyed out — it keeps the same weight and colour as the others and is
   marked by its tick, because greying one row and not the next is what reads
   as two different fonts in the same box.

   It is HTML, so it is text: it reflows rather than scaling, so it stays
   readable in a half-width column where a screenshot would halve. It never
   blurs, no clock drifts through it, and a screen reader gets the rows.

   Anything shown here has to be something the product actually does. */
/* ── THE STAGE A PICTURE STANDS ON ───────────────────────────────────────────
   Kish, 10 September 2026, looking at three drawings of the same picture: "c
   yes please do it for the whole website". C is 440 wide, as tall as what is
   in it, on a stage: one soft violet disc behind and two small violet
   drawings in front, which replaced a swirl and a dot the same afternoon (the
   drawings are in squares.js).

   The stage takes the frame's old place in every layout: its width, its
   margins, its grid cell. The decoration reaches OUTWARD, towards the page
   margin, so it never lands on the copy beside it; a picture on the left is
   the same drawing mirrored. The stage isolates, so the disc paints behind the
   frame and above the band's own background, and the drawings over the
   frame's edge. */
.ui-stage { position: relative; isolation: isolate; width: min(var(--measure-shot-square), 100%); margin-inline: auto; }
.ui { position: relative; z-index: 1; width: 100%; border: 1px solid var(--line-2); border-radius: var(--r-frame); background: var(--paper); box-shadow: var(--shadow-frame); overflow: hidden; }
.ui-stage::before { content: ''; position: absolute; z-index: 0; top: 0; right: -32px; height: min(300px, 100%); width: auto; aspect-ratio: 1; border-radius: 50%; background: color-mix(in srgb, var(--violet) 16%, transparent); pointer-events: none; }
/* The two drawings. The main one sits across the bottom corner and enters the
   frame by 12px at most, where the bottom padding is 22: the swirl before it
   entered by 24 and touched every frame that ends in a button. It hangs about
   35px below, which a help article's 56px under a picture allows for. The mark
   sits on the far edge, 11px in, where the side padding is 24. Paper-filled,
   so a drawing reads as an object laid over the corner, not a line through it. */
.ui-motif { position: absolute; z-index: 2; height: auto; overflow: visible; pointer-events: none; fill: var(--paper); stroke: var(--violet); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.ui-motif .l { fill: none; }
.ui-motif .t { fill: var(--violet-tint); }
.ui-motif .k { fill: var(--violet); stroke: none; }
.ui-motif .on { stroke: var(--paper); }
.ui-motif .dash { stroke-dasharray: 3 5; }
.ui-motif-main { left: -30px; bottom: -36px; width: 72px; }
.ui-motif-mark { right: -11px; bottom: 26px; width: 22px; }
/* On a violet band the disc needs more violet to be seen at all. */
section.tinted .ui-stage::before { background: color-mix(in srgb, var(--violet) 24%, transparent); }
.feature.flip .ui-stage::before, .art-band.flip .ui-stage::before { right: auto; left: -32px; }
.feature.flip .ui-motif-mark, .art-band.flip .ui-motif-mark { right: auto; left: -11px; }
.feature.flip .ui-motif-main, .art-band.flip .ui-motif-main { left: auto; right: -30px; }
.feature.flip .ui-motif-main.dir, .art-band.flip .ui-motif-main.dir { transform: scaleX(-1); }
/* Reaching outward means reaching past the viewport wherever the page margin
   is narrower than the reach, which would give the whole page a sideways
   scroll. Clipped along x only, on the band that holds a stage, so the disc
   can still rise above the frame; `clip` makes no scroll container, which is
   what keeps a sticky help rail sticking inside it. */
:is(section, .page-head):has(.ui-stage) { overflow-x: clip; }
/* The disc may rise above the frame only where the words sit BESIDE the
   picture. Everywhere else something sits directly above or below it: in a
   help article the paragraph before it, and in any band once it stacks under
   1100. A 300px disc on a short frame also hung out of the bottom into the
   next paragraph. Measured: 294 places across 76 pages at six widths, every
   one of them words, and not one of them at a two-column width. */
@media (min-width: 1100px) {
  :is(.page-head, .feature, .art-band, .step) .ui-stage::before { top: -34px; height: min(300px, calc(100% + 34px)); }
}
/* A picture of a phone is the phone. In a 440 frame it floated in an empty
   grey box with 120px of nothing either side; now the stage hugs the phone
   and the disc, swirl and dot decorate the phone itself. */
.ui-stage:has(> .ui-plain) { width: max-content; max-width: 100%; }
.ui.ui-plain { background: transparent; border: 0; box-shadow: none; padding: 0; overflow: visible; }
@media (max-width: 599px) {
  .ui-stage::before { top: 0; right: -14px; height: min(200px, 100%); }
  .feature.flip .ui-stage::before, .art-band.flip .ui-stage::before { right: auto; left: -14px; }
}
/* The smaller drawings up to 899, not only on a phone. From 600 to 899 the
   bands stack and a heading or a card follows a picture about 41px under it:
   the full-size drawing, hanging 35px, came within 6px of "What is backed up"
   and of the card grid on the features page. */
@media (max-width: 899px) {
  .ui-motif-mark { right: -8px; bottom: 18px; width: 18px; }
  .feature.flip .ui-motif-mark, .art-band.flip .ui-motif-mark { right: auto; left: -8px; }
  .ui-motif-main { left: -14px; bottom: -28px; width: 56px; } /* 9px in: 13px clear of 22px of padding, 15 of 24 */
  .feature.flip .ui-motif-main, .art-band.flip .ui-motif-main { left: auto; right: -14px; }
}
.ui-bar { display: flex; align-items: center; gap: 8px; height: 40px; padding: 0 16px; background: var(--ground); border-bottom: 1px solid var(--line); }
.ui-bar i { width: 11px; height: 11px; border-radius: 50%; background: var(--line-2); }
.ui-bar i:nth-of-type(1) { background: var(--mac-red); }
.ui-bar i:nth-of-type(2) { background: var(--mac-amber); }
.ui-bar i:nth-of-type(3) { background: var(--mac-green); }
/* Every part keeps its own height. Without `flex: none` a column flex box
   SHRINKS its children to fit a fixed height instead of overflowing, and it
   does it silently: the title measured 0px tall and rendered as blank space
   while `scrollHeight` still said everything fitted. Nothing can be trusted to
   report a clipped frame unless the parts refuse to be squashed first. */
.ui-body { padding: 20px 24px 22px; display: flex; flex-direction: column; }
.ui-body > * { flex: 0 0 auto; }
/* As tall as what is in it. The frame used to be forced square from 600px up
   with its rows stretched to fill the square, which measured 108px boxes
   holding 41px of content. Kish, 10 Sep 2026: "you have left so much gapping".
   The rows now sit at their own height, about 20px of air apiece, and "3 is
   more than enough" still holds: the same three rows, no longer pulled apart. */
.ui-rows { display: flex; flex-direction: column; }

/* Two lines, not one with an ellipsis. In the app a truncated title is fine —
   the whole thing is one click away. In a picture on a marketing page there is
   no click, and "What was the £402.50 to Corner Plant …" reads as a broken
   image rather than as a long title. */
.ui-head { font-size: var(--t-lead); font-weight: var(--w-medium); line-height: 1.25; margin-bottom: 2px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ui-sub { color: var(--muted); font-size: var(--t-meta); line-height: 1.45; }
/* A list that follows the sub-line directly needs the gap the progress bar
   would otherwise have supplied, or the first row's title sits on the meta
   line above it and the two read as one paragraph. */
.ui-sub + .ui-rows { margin-top: 16px; }
.ui-sub + .ui-note { margin-top: 14px; }

/* How far through it is. The one number a person actually wants. */
.ui-progress { margin: 14px 0 4px; }
.ui-track { height: 5px; border-radius: var(--r-pill); background: var(--sunken); overflow: hidden; }
.ui-fill { height: 100%; border-radius: var(--r-pill); background: var(--violet); }
.ui-legend { display: flex; justify-content: space-between; line-height: 1.3; font-size: var(--t-meta); color: var(--muted); margin-top: 8px; padding-bottom: 12px; }
.ui-legend b { color: var(--ink); font-weight: var(--w-medium); }

.ui-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 16px; align-items: center; min-height: 52px; padding: 11px 0; border-top: 1px solid var(--line); }
.ui-row:first-of-type { border-top: 0; padding-top: 0; }
.ui-what { font-size: var(--t-sm); font-weight: var(--w-medium); line-height: 1.35; }
.ui-who { color: var(--muted); font-size: var(--t-meta); line-height: 1.45; margin-top: 2px; }
.ui-marks { display: flex; align-items: center; gap: 8px; padding-top: 1px; }
.ui-chip { display: inline-block; padding: 4px 9px; border-radius: var(--r-sm); font-size: var(--t-meta); font-weight: var(--w-medium); white-space: nowrap; background: var(--sunken); color: var(--ink-2); }
.ui-chip.late { background: var(--coral); }
.ui-chip.done { background: var(--sunken); color: var(--ink-2); }
.ui-file { line-height: 1.45; display: inline-flex; align-items: center; gap: 4px; font-size: var(--t-meta); color: var(--muted); font-weight: var(--w-regular); }

/* The client's own view: the same ladder, a tick instead of a chip. */
.ui-note { border-radius: var(--r); background: var(--violet-tint); border: 1px solid var(--violet-line); padding: 10px 12px; margin-bottom: 13px; font-size: var(--t-chip); color: var(--ink); }
.ui-task { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; gap: 14px; align-items: start; padding: 12px 0; border-top: 1px solid var(--line); }
.ui-task:first-of-type { border-top: 0; padding-top: 0; }
.ui-task svg { display: block; margin-top: 2px; }
.ui-tick { color: var(--green); }
.ui-open { color: var(--line-2); }
.ui-do { display: inline-block; padding: 5px 12px; border-radius: var(--r-sm); font-size: var(--t-meta); font-weight: var(--w-medium); background: var(--ink); color: var(--on-dark); white-space: nowrap; }
.ui-do.sent { background: var(--sunken); color: var(--muted); }

/* Stacking a row's chip under its title makes the row taller. The frame grows
   with its rows, so nothing is cut off; the break stays at 600, where the frame
   reaches a phone's width and a chip beside a title no longer fits. */
@media (max-width: 599px) {
  .ui-body { padding: 20px 20px 24px; }
  .ui-row { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .ui-marks { justify-content: flex-start; }
}

/* ── THE MAIL PROGRAM (`shape: 'mailbox'` in squares.js) ──────────────────────
   The problem band's picture, and the one frame on the site that is NOT the
   product: an ordinary mail program, and no particular one. Kish, 11 September
   2026: "show a proper email app ... an email app of some kind that resonates
   with people". Every rule is under .ui-mail*, so no other frame picks one up,
   and every value is a site token: a mail program's greys, a black Compose as
   the one action, four soft tints for the round initials, no window lights.

   It keeps what every picture has: the stage, the 440 width, the height of its
   content, the disc and the two drawings. A folder column runs down the left;
   where the frame is under 400 wide (a phone) the folders fold into a row of
   tabs above the list and Compose into its pencil, so the list keeps the width
   it had. The bottom corner the drawing enters is the folder column's empty
   foot on a wide screen and the reading pane's 24px of padding on a phone. */
.ui.ui-mailapp { container: mailapp / inline-size; }
.ui-mailapp-grid { display: grid; grid-template-columns: 112px minmax(0, 1fr); grid-template-areas: "compose search" "folders main"; }
.ui-mail-compose, .ui-mail-search { display: flex; align-items: center; min-width: 0; padding-block: 11px; background: var(--ground); border-bottom: 1px solid var(--line-2); }
.ui-mail-compose { grid-area: compose; padding-inline: 10px 4px; }
.ui-mail-search { grid-area: search; padding-inline: 10px 16px; }
.ui-mail-compose > span { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 30px; padding: 0 12px 0 10px; border-radius: var(--r-pill); background: var(--ink); color: var(--on-dark); font-size: var(--t-meta); line-height: 1; white-space: nowrap; }
.ui-mail-compose b { font-weight: var(--w-medium); }
.ui-mail-search > span { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 12px; border-radius: var(--r-pill); background: var(--sunken); color: var(--muted); font-size: var(--t-meta); line-height: 1; white-space: nowrap; }
.ui-mail-glyph { display: block; flex: none; }
.ui-mail-folders { grid-area: folders; display: flex; flex-direction: column; gap: 2px; padding: 10px 8px; background: var(--ground); border-right: 1px solid var(--line-2); }
.ui-mail-folder { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: var(--r-sm); font-size: var(--t-meta); line-height: 1.3; color: var(--ink-2); }
.ui-mail-folder .ui-mail-glyph { color: var(--muted); }
.ui-mail-folder b { margin-left: auto; font-weight: var(--w-bold); }
.ui-mail-folder.on { background: var(--line-2); font-weight: var(--w-bold); }
.ui-mail-folder.on .ui-mail-glyph { color: var(--ink); }
.ui-mail-main { grid-area: main; min-width: 0; }
.ui-mail-list { border-bottom: 1px solid var(--line-2); }
.ui-mail-msg { position: relative; display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 10px; align-items: start; padding: 10px 16px 11px 18px; border-top: 1px solid var(--line); }
.ui-mail-msg:first-child { border-top: 0; }
.ui-mail-msg.open { background: var(--sunken); }
/* The unread dot sits in the row's left margin, level with the sender. */
.ui-mail-msg.unread::before { content: ''; position: absolute; left: 6px; top: 16px; width: 7px; height: 7px; border-radius: 50%; background: var(--ink); }
.ui-mail-avatar { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; font-size: var(--t-micro); font-weight: var(--w-bold); line-height: 1; background: var(--violet-tint); color: var(--violet-ink); }
.ui-mail-avatar[data-tone="1"] { background: var(--green-tint); color: var(--green); }
.ui-mail-avatar[data-tone="2"] { background: var(--orange-tint); color: var(--orange-ink); }
.ui-mail-avatar[data-tone="3"] { background: var(--coral-tint); color: var(--ink-2); } /* not grey: the open row is grey */
.ui-mail-msg-main { min-width: 0; }
.ui-mail-top { display: flex; align-items: baseline; gap: 8px; }
.ui-mail-from { min-width: 0; font-size: var(--t-chip); font-weight: var(--w-medium); line-height: 1.3; overflow-wrap: anywhere; }
.ui-mail-count { color: var(--muted); font-weight: var(--w-regular); }
.ui-mail-when { flex: none; margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-meta); line-height: 1.3; color: var(--muted); white-space: nowrap; }
/* `p + p` gives a following paragraph 1em; a mail row's lines sit close. */
.ui-mail-subject { margin-top: 1px; font-size: var(--t-chip); line-height: 1.35; color: var(--ink-2); overflow-wrap: anywhere; }
.ui-mail-msg.unread :is(.ui-mail-from, .ui-mail-subject) { font-weight: var(--w-bold); }
.ui-mail-preview { margin-top: 1px; font-size: var(--t-meta); line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
.ui-mail-read { padding: 16px 20px 24px 18px; }
.ui-mail-read-subject { font-size: var(--t-body); font-weight: var(--w-bold); line-height: 1.3; letter-spacing: var(--tr-tight); overflow-wrap: anywhere; }
.ui-mail-read-head { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 10px; align-items: center; margin-top: 12px; }
.ui-mail-read-head .ui-mail-when .ui-mail-glyph { color: var(--ink-2); }
.ui-mail-to { margin-top: 1px; font-size: var(--t-meta); line-height: 1.35; color: var(--muted); }
.ui-mail-body { margin-top: 12px; font-size: var(--t-chip); line-height: 1.5; color: var(--ink); }
.ui-mail-attach { display: flex; align-items: center; gap: 6px; width: fit-content; max-width: 100%; margin-top: 12px; padding: 7px 11px 7px 9px; border: 1px solid var(--line-2); border-radius: var(--r-sm); font-size: var(--t-meta); line-height: 1.3; color: var(--ink-2); }
.ui-mail-attach span { min-width: 0; overflow-wrap: anywhere; }
.ui-mail-attach .ui-mail-glyph, .ui-mail-msg .ui-mail-when .ui-mail-glyph { color: var(--muted); }
.ui-mail-quote { margin: 14px 0 0; padding-left: 11px; border-left: 2px solid var(--line-2); font-size: var(--t-meta); line-height: 1.45; color: var(--muted); }
.ui-mail-quote p + p { margin-top: 1px; }
@container mailapp (max-width: 400px) {
  .ui-mailapp-grid { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "search compose" "folders folders" "main main"; }
  .ui-mail-search { padding-inline: 14px 6px; }
  .ui-mail-compose { padding-inline: 6px 14px; }
  .ui-mail-compose > span { width: 30px; padding: 0; }
  .ui-mail-compose b { display: none; }
  .ui-mail-folders { flex-direction: row; flex-wrap: wrap; gap: 4px; padding: 8px 12px; border-right: 0; border-bottom: 1px solid var(--line-2); }
  .ui-mail-folder { gap: 5px; padding: 5px 9px; }
  .ui-mail-folder .ui-mail-glyph { display: none; }
  .ui-mail-folder b { margin-left: 2px; }
  .ui-mail-read { padding: 16px 18px 24px; }
}

/* AN ILLUSTRATION BESIDE AN ARGUMENT. The site was a run of screenshots and
   nothing else, which reads as a specification rather than a case: left image,
   right image, left image, right image. A drawing does something a screenshot
   cannot — it shows the reader their own week before it shows them a product.
   Wider than the prose because a picture may be, quieter than a screenshot
   because it is not evidence, and it carries no frame: it is not a window. */
.art-band { padding: 88px 0; }
.art-band .container { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: 64px; align-items: center; }
.art-band.flip .art-copy { order: 2; }
/* An illustration is a picture in the same rhythm as the drawn squares, so it
   is the same width and meets the same edge. At `width: 100%` of its grid
   column it came out 576 in one band and 480 in the next, which put three
   picture widths on the home page against the squares' settled 520. */
.art-band img { display: block; width: min(var(--measure-shot-square), 100%); height: auto; margin-inline: auto; }
.art-band h2 { font-size: var(--t-title); margin-bottom: 18px; }
/* SCOPED TO THE COPY COLUMN, not to everything under the band. Written as
   `.art-band p` it was two classes and an element against a component's one
   class, so it reached inside the drawn screen and repainted it: every muted
   meta line, every violet file line and the phone's own button label came out
   black — the button black on black, invisible. The rule is about the prose
   BESIDE the picture, so that is what it now says. Same for `.step` and
   `.feature` below. */
.art-band .art-copy p { color: var(--ink-2); max-width: var(--measure-copy-tight); }
.art-band p + p { margin-top: 14px; }
/* ONE SIZE IN A BLOCK OF COPY. Kish: "even this font has two sizes, please
   just keep one size" — and the one he pointed at as right was the lede. A lede
   at 20 over paragraphs at 17 is ordinary typography, but in a two-column band
   beside a picture it reads as two decisions rather than one voice. */
.art-lede { color: var(--ink); }
.art-band .art-copy p { font-size: var(--t-lead); line-height: 1.55; }
/* One size in the block — but 20px on a 390px screen is 28 characters a line,
   which makes three paragraphs into a column of stubs and the page into
   sixteen screens. Still one size at any width a reader is actually at; the
   size is what the width can carry. */
@media (max-width: 760px) {
  .art-band .art-copy p { font-size: var(--t-body); line-height: 1.6; }
}
@media (max-width: 860px) {
  .art-band { padding: 56px 0; }
  .art-band .container { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .art-band.flip .art-copy { order: 0; }
}

/* Banded screenshot */
.band-shot { padding-top: 0; }
.band-shot .caption { display: flex; justify-content: space-between; align-items: baseline; gap: 24px; margin-bottom: 20px; }
.band-shot .caption h2 { font-size: var(--t-sub); }
.band-shot .caption p { color: var(--muted); font-size: var(--t-sm); }

/* Three columns separated by rules */
.threes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.threes > div { padding: 8px 40px 8px 0; }
.threes > div + div { border-left: 1px solid var(--line); padding-left: 40px; }
.threes :is(h2, h3) { font-size: var(--t-lead); margin-bottom: 12px; }
.threes p:not(.kicker) { color: var(--ink-2); }
.threes .answer { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line); color: var(--ink); }
.threes .answer strong { font-weight: var(--w-bold); color: var(--violet-ink); }

/* Feature rows */
.feature { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 56px; align-items: center; padding: 64px 0; }
.feature + .feature { border-top: 1px solid var(--line); }
/* A WIDE SHOT DOES NOT GO IN A COLUMN. The picture slot is 7 of 12 across a
   1120 container less the gap: 621px. A `tall` shot is 640 CSS pixels of app,
   so it lands at 0.97 and reads at its own size. A `wide` one is 1200, so it
   lands at 0.52 — half size, and every label in it is 7px. Two pictures in the
   same slot on the same page, one readable and one not, which is the thing
   this whole redesign was asked to fix.

   So a row holding a wide shot stacks instead: the copy keeps its reading
   measure, the picture takes the whole container and lands at 0.93. The hook
   is the intrinsic width, which `site-shot-sizes` writes from the file itself,
   so this follows the picture rather than a class somebody has to remember. */
.feature:has(img[width="2400"]) { grid-template-columns: minmax(0, 1fr); gap: 32px; align-items: start; }
/* And it may be wider than the prose. A wide shot holds 1200 CSS pixels of
   app, so inside a 1120 reading measure it can never be more than 0.93 and a
   14px label lands at 13. Prose wants 1120; a picture does not have to. Given
   the window it takes 1400 and the same label lands at 16 — bigger than the
   app draws it, which is the only size that answers "at least make it
   readable". It shrinks with the window like everything else. */
.feature:has(img[width="2400"]) > figure,
.container > figure.shot:has(img[width="2400"]) {
  width: min(var(--measure-shot-wide), calc(100vw - 2 * var(--gutter)));
  margin-inline: calc((100% - min(var(--measure-shot-wide), 100vw - 2 * var(--gutter))) / 2);
}
.feature:has(img[width="2400"]) .feature-copy { order: 0; }
.feature:has(img[width="2400"]) figure { order: 1; }
/* AND A TALL SHOT IS NEVER BLOWN UP. It is 640 CSS pixels of app; across the
   1120 container that is 1.75x and soft, which is the same fault as the wide
   one in the other direction. Capped at its own size and centred, so every
   picture on the site now lands between 0.93 and 0.97 of the size the app
   actually draws — near enough life size that a label reads. */
.shot:has(img[width="1280"]) { max-width: var(--measure-shot-tall); margin-inline: auto; }
.feature.flip .feature-copy { order: 2; }
/* A flipped feature moves the copy to the second cell, so the picture takes
   the FIRST — which is the 5fr one, 443px, and a frame that was 520 everywhere
   else (its width until 10 Sep 2026) came out 443 here. The columns swap with the order so the picture keeps
   the wide side whichever side it is drawn on.

   Confined to the width where the bands ARE two columns. Left unconditional it
   outranked the stacking rule below it — three classes against two — so a
   flipped band stayed side by side all the way down and the frame came out
   129px wide on a phone. Specificity is not a lever you can pull once and
   forget: the rule that must lose has to be unable to match. */
@media (min-width: 1100px) {
  .feature.flip:has(.ui) { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  /* Same trap in the art bands: flipping moves the copy to the second cell, so
     the picture takes the FIRST — the narrower one — and a full-width frame would
     not fit it. The columns swap with the order. */
  .art-band.flip .container { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }

  /* The square meets the container edge, on whichever side it sits. `.ui`
     centres itself with `margin-inline: auto`, and a centred 520 square lands
     at a different inset under every column ratio: 30px in under the page
     head, 50px in the bands below it. Scrolling a page, that reads as the
     picture sliding sideways while the words stay still. Meeting the edge also
     lines each square up with the h1 opposite it and the cards underneath. */
  .page-head:has(.ui) .ui-stage,
  .feature:has(.ui) > .ui-stage,
  .art-band:has(.ui) .ui-stage,
  .art-band figure { margin-inline: auto 0; }
  .feature.flip:has(.ui) > .ui-stage,
  .art-band.flip:has(.ui) .ui-stage,
  .art-band.flip figure { margin-inline: 0 auto; }
  /* The figure holds the picture column's slack; the image inside it is the
     picture, so it must not take a second helping of `auto`. */
  .art-band figure { width: min(var(--measure-shot-square), 100%); }
  .art-band figure img { margin-inline: 0; }
}
.feature h2 { font-size: var(--t-head); margin-bottom: 16px; }
.feature .feature-copy p:not(.kicker) { color: var(--ink-2); max-width: var(--measure-copy-tight); }
.ticks { list-style: none; margin: 22px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
/* The tick hangs in the margin and the words stay one run of text. As a flex
   row the li made a flex item of every inline child, so "Reach is <strong>every
   client</strong>, or <strong>a named list</strong>" came out as five boxes
   with a 10px gap before the comma and the phrases out of reading order. Two
   items showed it; the rule was wrong for any of the 400 that carries a
   <strong> or a link anywhere but the very start. */
.ticks li { position: relative; padding-left: 26px; color: var(--ink); }
.ticks svg { position: absolute; left: 0; top: 4px; flex: none; color: var(--green); }
.feature-link { display: inline-flex; align-items: center; gap: 6px; margin-top: 22px; font-weight: var(--w-bold); }
.feature .shot-phone { justify-self: center; }

/* Client section */
.clients-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 48px; align-items: end; }

/* Facts strip */
.facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border: 1px solid var(--line); border-radius: var(--r-card); background: var(--paper); overflow: hidden; }
.facts > div { padding: 24px; }
.facts > div + div { border-left: 1px solid var(--line); }
.facts strong { display: block; font-weight: var(--w-bold); margin-bottom: 6px; }
.facts p { color: var(--muted); font-size: var(--t-sm); }

/* Templates strip */
.packs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.pack { display: block; padding: 20px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--paper); color: var(--ink); text-decoration: none; transition: border-color var(--dur-fast), transform var(--dur), box-shadow var(--dur); }
.pack:hover { border-color: var(--violet-line); text-decoration: none; transform: var(--lift); box-shadow: var(--shadow-lift); }
.pack strong { display: block; font-weight: var(--w-bold); margin-bottom: 4px; }
.pack span:not(.tile) { color: var(--muted); font-size: var(--t-sm); }
.pack ul { margin: 14px 0 0; padding: 0; list-style: none; color: var(--ink-2); font-size: var(--t-sm); display: flex; flex-direction: column; gap: 4px; }
.pack li { padding-left: 14px; position: relative; }
.pack li::before { content: ''; position: absolute; left: 0; top: 9px; width: 6px; height: 6px; border-radius: 50%; background: var(--violet); opacity: .45; }

/* Call to action band */
.cta { padding: 0 0 88px; border-top: 0 !important; }
.cta-band { background: var(--violet-deep); color: var(--on-dark); border-radius: var(--r-band); padding: 64px; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 40px; align-items: center; }
.cta-band h2 { color: var(--on-dark); }
.cta-band p { color: var(--on-dark-2); margin-top: 12px; max-width: var(--measure-copy-tight); }
.cta-actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* Page header for inner pages */
.page-head { padding: var(--section-y-md) 0 56px; }
.page-head h1 { max-width: var(--measure-title); }
.page-head .lead { margin-top: 20px; max-width: var(--measure-copy); }

/* Steps (a real sequence) */
.steps { counter-reset: step; display: grid; gap: 0; }
.step { display: grid; grid-template-columns: 64px minmax(0, 5fr) minmax(0, 7fr); gap: 40px; padding: 56px 0; align-items: center; }
.step + .step { border-top: 1px solid var(--line); }
.step::before { counter-increment: step; content: counter(step); width: 48px; height: 48px; border-radius: var(--r-card); background: var(--violet); color: var(--on-dark); font-weight: var(--w-bold); display: grid; place-items: center; font-size: var(--t-body); }
.step h2 { font-size: var(--t-head); margin-bottom: 12px; }
.step > div:not(.ui-stage) p { color: var(--ink-2); }

/* Pricing */
.billing { display: inline-flex; padding: 4px; border: 1px solid var(--line); border-radius: var(--r-pill); background: var(--paper); margin-bottom: 40px; }
.billing button { height: 36px; padding: 0 16px; border: 0; border-radius: var(--r-pill); background: transparent; font: inherit; font-size: var(--t-sm); color: var(--ink-2); cursor: pointer; }
.billing button[aria-pressed="true"] { background: var(--violet); color: var(--on-dark); }
/* The one text size on the site nobody chose: `small` has no size rule here,
   so it fell to the browser's 0.8333em of the button's 15px and rendered at
   12.5px. Every other quiet label is --t-meta. */
.billing button small { font-size: var(--t-meta); color: inherit; opacity: .75; margin-left: 6px; }
.plans { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; align-items: stretch; }
.plan { position: relative; display: flex; flex-direction: column; padding: 28px; border: 1px solid var(--line); border-radius: var(--r-frame); background: var(--paper); }
.plan.is-featured { border-color: var(--violet-line); background: linear-gradient(var(--violet-tint), var(--paper) 220px); }
.plan-flag { position: absolute; top: -13px; left: 28px; padding: 4px 10px; border-radius: var(--r-pill); background: var(--violet); color: var(--on-dark); font-size: var(--t-meta); font-weight: var(--w-bold); }
.plan h3 { font-weight: var(--w-bold); }
.plan .plan-for { color: var(--muted); font-size: var(--t-sm); margin-top: 4px; min-height: 46px; }
.price { margin: 22px 0 4px; font-size: var(--t-price); font-weight: var(--w-bold); letter-spacing: -.03em; line-height: 1; font-variant-numeric: tabular-nums; }
.price small { font-size: var(--t-lead); font-weight: var(--w-bold); letter-spacing: 0; vertical-align: top; position: relative; top: 4px; margin-right: 2px; }
.plan .period { color: var(--muted); font-size: var(--t-sm); min-height: 22px; }
.plan .btn { margin: 24px 0; }
.plan .plan-buy { margin: -12px 0 24px; font-size: var(--t-sm); text-align: center; }
.plan .ticks { margin: 0; gap: 9px; font-size: var(--t-sm); }
.plan .ticks li { color: var(--ink-2); }

/* FAQ */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary { list-style: none; cursor: pointer; padding: 20px 0; font-weight: var(--w-bold); display: flex; justify-content: space-between; align-items: center; gap: 24px; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: ''; width: 10px; height: 10px; border-right: 2px solid var(--ink); border-bottom: 2px solid var(--ink); transform: rotate(45deg); transition: transform var(--dur-fast); flex: none; margin-right: 6px; }
.faq details[open] summary::after { transform: rotate(225deg); border-color: var(--violet); }
.faq details > div { padding: 0 0 22px; color: var(--ink-2); max-width: var(--measure-copy-wide); }

/* Tables */
/* ── A TABLE, DRAWN AS THE APP WOULD SHOW IT ─────────────────────────────────
   Kish, 10 Sep 2026, of the plain tables: "not looking professional ... make it
   like the design we have got it approved"; then, of the week drawn as rows,
   "have like a mini calendar ... columns monday tuesday ... and then have tasks
   ... obviously not the full sentence ... you can use the full page ... centre
   it ... do it for all those tables". The page keeps a real table for the
   checks; renderTable in squares.js draws it as columns, cards, a comparison or
   rows, across the whole container, on the pictures' own stage. */
.ui-stage.table-stage { width: 100%; margin-inline: auto; }
/* Words can follow a table directly (the honest last line under the shared
   folder comparison), and the drawing under the frame hangs about 35px. */
.ui-stage.table-stage:not(:last-child) { margin-bottom: 52px; }
.ui.ui-table .ui-body { padding: 22px 26px 26px; }
.ui.ui-table :is(.ui-head, .ui-sub) + :is(.ui-cols, .ui-cards, .ui-compare, .ui-rows) { margin-top: 18px; }
/* Columns: a week, a run of stages, a board. */
/* Columns are counted by the frame's own width, not the window's, so a board
   in a help article's column behaves as it would on a narrow screen. All of them
   side by side when there is room; then three (six stages read 3 and 3), a
   board of four as 2 and 2; then two; then one. "As many as fit" put five of
   six stages on a row and the sixth alone under them. Cards take as many
   300px tracks as fit. */
.ui.ui-table .ui-body { container: frame / inline-size; }
.ui-cols { display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); gap: 10px; align-items: start; }
@container frame (max-width: 1000px) {
  .ui-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ui-cols:is([data-cols="2"], [data-cols="4"]) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ui-cols[data-cols="1"] { grid-template-columns: minmax(0, 1fr); }
}
@container frame (max-width: 640px) {
  .ui-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ui-cols[data-cols="1"] { grid-template-columns: minmax(0, 1fr); }
}
@container frame (max-width: 440px) {
  .ui-cols, .ui-cols[data-cols] { grid-template-columns: minmax(0, 1fr); }
}
.ui-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 10px; border-radius: var(--r); background: var(--ground); }
.ui-col-head { display: flex; align-items: center; gap: 8px; padding: 2px 4px; font-size: var(--t-meta); font-weight: var(--w-bold); color: var(--ink-2); }
.ui-step { flex: none; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: var(--violet); color: var(--on-dark); font-size: var(--t-micro); font-weight: var(--w-bold); }
.ui-card { display: flex; gap: 9px; align-items: flex-start; min-width: 0; padding: 10px 11px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); }
.ui-card-icon { flex: none; margin-top: 2px; color: var(--violet); }
.ui-card-main { min-width: 0; }
.ui.ui-table .ui-card-text { font-size: var(--t-sm); font-weight: var(--w-medium); line-height: 1.35; }
.ui.ui-table .ui-card-sub { margin-top: 3px; font-size: var(--t-meta); color: var(--muted); line-height: 1.4; }
.ui-card-main .ui-chip { margin-top: 7px; }
/* Cards: a set of things, each with its tag. */
.ui-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: 10px; }
.ui-card.ui-card-block { flex-direction: column; gap: 5px; padding: 14px 15px; }
.ui-card-top { display: flex; align-items: flex-start; gap: 9px; width: 100%; margin-bottom: 2px; }
.ui.ui-table .ui-card-title { flex: 1; min-width: 0; font-size: var(--t-sm); font-weight: var(--w-bold); line-height: 1.35; }
.ui.ui-table .ui-card-line { font-size: var(--t-meta); color: var(--ink-2); line-height: 1.45; }
/* Compare: the sides, point by point. */
.ui-cmp-row { display: grid; grid-template-columns: minmax(0, 1.15fr) repeat(var(--sides), minmax(0, 1fr)); gap: 0 20px; align-items: start; padding: 11px 0; border-top: 1px solid var(--line); }
.ui-cmp-row.ui-cmp-top { padding: 0 0 9px; border-top: 0; }
.ui.ui-table .ui-cmp-side { font-size: var(--t-meta); font-weight: var(--w-bold); color: var(--muted); }
.ui.ui-table .ui-cmp-side.ours { color: var(--violet-ink); }
.ui.ui-table .ui-cmp-what { font-size: var(--t-sm); font-weight: var(--w-medium); line-height: 1.4; }
.ui.ui-table .ui-cmp-cell { display: flex; gap: 8px; align-items: flex-start; font-size: var(--t-sm); color: var(--ink-2); line-height: 1.4; }
.ui-cmp-cell svg { flex: none; margin-top: 2px; }
.ui-cmp-cell.yes svg { color: var(--green); }
.ui-cmp-cell.no svg { color: var(--muted); }
.ui-cmp-cell.part svg { color: var(--violet); }
.ui-cmp-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* Rows: a row each, the rest beneath. */
.ui.ui-table .ui-row { align-items: start; padding: 13px 0; }
.ui.ui-table .ui-row:first-child { padding-top: 0; }
.ui.ui-table .ui-who { font-size: var(--t-sm); color: var(--ink-2); line-height: 1.5; margin-top: 3px; }
.ui.ui-table .ui-label { color: var(--muted); }
.ui.ui-table .ui-group { padding-top: 14px; }
.ui.ui-table .ui-group:first-child { padding-top: 0; }
/* From two reviewers who read every table at 1280, 1000 and 390.
   A card or a side without an icon keeps the icon's room, so its words line
   up with the rest ("The seller opens it once", "Built for"). */
span.ui-card-icon, .ui-cmp-gap { flex: none; display: block; width: 16px; height: 16px; }
/* Six columns side by side are 170px each: the icon goes above the words there,
   so a title has 128px rather than 103 and "Immunisations," fits its card. A
   numbered stage's name may take two lines, so every head keeps two and the
   cards start level. Seven cards three to a row left the seventh alone: the
   last one on its own takes the row. */
@container frame (min-width: 1001px) {
  .ui-cols[data-cols="6"] .ui-card { flex-direction: column; gap: 6px; }
  .ui-cols:has(.ui-step) .ui-col-head { align-items: flex-start; min-height: 38px; }
  .ui-cards > .ui-card-block:last-child:nth-child(3n + 1) { grid-column: 1 / -1; }
}
.ui.ui-table :is(.ui-card-text, .ui-card-title, .ui-card-sub, .ui-card-line, .ui-cmp-what, .ui-cmp-cell) { overflow-wrap: break-word; }
/* A tag drops under its title when the card is narrow, instead of pressing
   "Password reset link" onto two lines beside it. The query reads the card's
   inside width: 270 on a phone, 317 three to a row at 1280, where the tag
   stays beside the title. */
.ui-card.ui-card-block { container: card / inline-size; }
@container card (max-width: 300px) {
  .ui-card-top { flex-wrap: wrap; row-gap: 6px; }
  .ui.ui-table .ui-card-top .ui-card-title { flex: 1 1 calc(100% - 25px); }
  .ui-card-top .ui-chip { margin-left: 25px; }
}
/* A menu path breaks between its steps, never inside a button's name. */
.ui.ui-table .ui-card-line strong { white-space: nowrap; }
/* A full-width frame's corner drawing sits just inside the frame: at 1000 the
   page's margin is 24px, and a drawing reaching 30px out was cut by the window. */
@media (min-width: 900px) { .ui-stage.table-stage .ui-motif-main { left: 20px; } }
/* A table in a marketing page's article column takes the page's width, as Kish
   asked ("use the full page ... centre it"), and the words around it keep their
   measure. A help article's column sits beside the rail, so its tables stay the
   column's width. */
.container:not(.help-layout) > .prose:has(> .table-stage) { max-width: none; }
.container:not(.help-layout) > .prose:has(> .table-stage) > :not(.table-stage) { max-width: var(--measure-prose); }
@media (max-width: 599px) {
  .ui.ui-table .ui-body { padding: 18px 20px 24px; } /* a picture's own phone padding: at 16 the corner mark came within 8px of a card */
  .ui-cmp-row { grid-template-columns: minmax(0, 1fr); gap: 5px; }
  .ui-cmp-row.ui-cmp-top { display: none; }
  .ui-cmp-name { position: static; width: auto; height: auto; overflow: visible; clip-path: none; white-space: normal; color: var(--muted); font-weight: var(--w-regular); }
  .ui-cmp-row.ui-cmp-top + .ui-cmp-row { border-top: 0; padding-top: 0; }
}
.yes { color: var(--green); font-weight: var(--w-bold); }
.no { color: var(--muted); }

/* A heading beside its list, used on the solutions pages */
.split { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 48px; align-items: start; }
.split > div p:not(.kicker) { margin-top: 14px; color: var(--ink-2); }
.ticks.two { margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 12px 32px; }

/* Read next: three plain links under a hairline each, no boxes */
.rel-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.rel-grid.four { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }

.rel { display: block; padding: 18px 20px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--paper); text-decoration: none; color: var(--ink); transition: border-color var(--dur-fast), transform var(--dur), box-shadow var(--dur); }
.rel:hover { border-color: var(--violet-line); text-decoration: none; transform: var(--lift); box-shadow: var(--shadow-lift); }
.rel .tile { margin-bottom: 12px; }
.rel:hover .tile { background: var(--violet); color: var(--on-dark); }
.rel strong { display: block; font-weight: var(--w-bold); }
/* `:not(.tile)` because the icon tile is a span too. `.rel span` made it a
   block and painted it grey, so all 185 icons sat grey in the top-left corner
   of their tiles; `.pack` and `.help-card` greyed theirs the same way. */
.rel span:not(.tile) { display: block; margin-top: 4px; color: var(--muted); font-size: var(--t-sm); }
.rel:hover strong { text-decoration: underline; text-underline-offset: 3px; }

/* Tabs */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 32px; overflow-x: auto; }
.tabs [role="tab"] { height: 44px; padding: 0 14px; border: 0; border-bottom: 2px solid transparent; margin-bottom: -1px; background: transparent; font: inherit; color: var(--ink-2); cursor: pointer; white-space: nowrap; }
.tabs [role="tab"][aria-selected="true"] { color: var(--ink); font-weight: var(--w-bold); border-bottom-color: var(--violet); }

/* Prose pages (help, legal, about) */
/* ── A CLOSING NOTE ───────────────────────────────────────────────────────────
   Every solutions page ends by saying what Docsroom is not — that it does not
   file the return, does not do the check, does not replace the judgment. It is
   the honest paragraph and the last one a buyer reads, and it was set as a
   single 60-word block in a full-width section, so more than half of the final
   thing on the page was empty. Kish's words: "too much empty space".

   Called `.closing` and not `.note`: `.note` is already the violet-ruled aside
   inside a help article, eighteen of them, and taking that name silently put
   every one of their sentences in a second grid column.

   On the same 5/7 grid as the bands above it, so it reads as the end of that
   rhythm rather than a new shape: the heading holds the left column, the words
   the right, and one hairline says the page has finished rather than run out. */
.closing { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 0 56px; padding-top: 40px; border-top: 1px solid var(--line); }
.closing h2 { grid-column: 1; font-size: var(--t-sub); }
/* Both paragraphs belong in the right column. Left to auto-flow, a second one
   wrapped back under the heading and the note read as a zigzag; and `gap`
   alone set the row gap too, which put 56px between two sentences. */
.closing p { grid-column: 2; color: var(--ink-2); max-width: var(--measure-copy); }
.closing p + p { margin-top: 14px; }
@media (max-width: 899px) {
  .closing { grid-template-columns: minmax(0, 1fr); gap: 12px; padding-top: 28px; }
  /* One column means one column. `grid-column: 2` above outlived it and made an
     implicit second track sized to the paragraph, the heading's track went to
     nothing, and "Clients use links" was drawn over its own words on a phone. */
  .closing h2, .closing p { grid-column: 1; }
}

/* ── THE HELP RAIL ───────────────────────────────────────────────────────────
   A help article was one narrow column of prose with the right two thirds of
   a 1120 container empty, and no way to reach another article except the
   browser's back button — on a help centre with eighteen of them. The rail
   holds the whole list, in the index's groups, with the current one marked; it
   fills the column the prose does not want and makes the set navigable.

   It sticks under the header while the article scrolls, and on anything under
   1000 it goes back to being a plain list above the words. */
.help-layout { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: 56px; align-items: start; }
.help-rail { position: sticky; top: 96px; font-size: var(--t-sm); }
.help-rail-head { margin: 0 0 8px; font-size: var(--t-meta); font-weight: var(--w-bold); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.help-rail ul + .help-rail-head { margin-top: 22px; }
.help-rail ul { margin: 0; padding: 0; list-style: none; }
.help-rail li + li { margin-top: 2px; }
.help-rail a { display: block; padding: 5px 10px; margin-left: -10px; border-radius: var(--r-sm); color: var(--ink-2); text-decoration: none; }
.help-rail a:hover { background: var(--sunken); }
.help-rail a[aria-current="page"] { background: var(--sunken); font-weight: var(--w-medium); }
@media (max-width: 999px) {
  /* Stacked, the rail would put eighteen links between the reader and the
     first sentence of the article they chose. It goes after the words instead,
     where it reads as the index at the end rather than a barrier at the top. */
  .help-layout { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .help-rail { position: static; order: 2; padding-top: 28px; border-top: 1px solid var(--line); }
}

.prose { max-width: var(--measure-prose); }
.prose h2 { font-size: var(--t-sub); margin: 48px 0 14px; }
/* A prose block that opens on its heading already has the section's padding
   above it; the article rhythm must not be added to that as well. */
.prose > h2:first-child, .prose > h3:first-child, .prose > .tile:first-child { margin-top: 0; }
/* An icon tile in running prose marks the section its heading names, so it has
   to read as part of that heading. Loose, the h2's own 48px top margin pushed
   the words away and eight tiles on /compare/ and /templates/ floated 60px
   above the heading they were drawn for, reading as strays.

   The heading's top margin goes, and the space that separates one section from
   the next stays where it already was — on the paragraph above. Two attempts
   before this one moved the gap onto the tile instead, which does nothing an
   eye can see: `.tile` is `inline-flex`, and making it block-level to take the
   margin collapsed it from 34px wide to 17, because `width: max-content` on a
   flex box measures the icon and forgets the padding. */
.prose > .tile + h2 { margin-top: 0; }
.prose h3 { margin: 32px 0 10px; }
/* An article's rules stop at a picture. `.prose p` outranked the phone's own
   white button text and set it black on a black button, and the list rules
   indented the bullets in the email pictures: the page styling the inside of
   a drawing it has no business with. */
.prose p:not(.kicker):not(.ui-stage *), .prose li:not(.ui-stage *) { color: var(--ink-2); }
.prose ul:not(.ui-stage *), .prose ol:not(.ui-stage *) { padding-left: 24px; margin: 12px 0; }
.prose li + li:not(.ui-stage *) { margin-top: 6px; }
/* A picture inside an article sat 8px under the paragraph before it, so the
   swirl crossed the next paragraph. Room for the decoration both ways, and more
   below: the drawing on the corner hangs 35px under the frame, which at 40px left 5px before
   the next paragraph's first line. 56px leaves 21. */
.prose .ui-stage { margin-block: 40px 56px; }
.prose figure { margin: 28px 0; }
.prose figcaption { margin-top: 10px; font-size: var(--t-sm); color: var(--muted); }
.prose code { font-family: var(--font-mono); font-size: var(--t-chip); background: var(--sunken); padding: 2px 6px; border-radius: var(--r-xs); color: var(--ink); }
.prose pre { background: var(--ink); color: var(--on-dark); padding: 18px 20px; border-radius: var(--r-card); overflow-x: auto; font-size: var(--t-chip); line-height: 1.5; }
.prose pre code { background: none; color: inherit; padding: 0; }
.prose .note { padding: 16px 18px; border: 1px solid var(--line); border-left: 3px solid var(--violet); border-radius: var(--r); background: var(--paper); margin: 20px 0; }
.prose .note p { color: var(--ink); }
.help-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.help-card { display: block; padding: 22px 24px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--paper); color: var(--ink); text-decoration: none; transition: border-color var(--dur-fast), transform var(--dur), box-shadow var(--dur); }
.help-card:hover { border-color: var(--violet-line); text-decoration: none; transform: var(--lift); box-shadow: var(--shadow-lift); }
.help-card strong { display: block; font-weight: var(--w-bold); margin-bottom: 4px; }
.help-card span:not(.tile) { color: var(--muted); font-size: var(--t-sm); }
.use-case-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.crumbs { font-size: var(--t-sm); color: var(--muted); margin-bottom: 20px; }
.crumbs a { color: inherit; }
.article-foot { margin-top: 56px; padding-top: 24px; border-top: 1px solid var(--line); display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap; color: var(--muted); font-size: var(--t-sm); }

/* Changelog */
.log { border-top: 1px solid var(--line); }
.log-entry { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 32px; padding: 40px 0; border-bottom: 1px solid var(--line); }
.log-entry time { color: var(--muted); font-size: var(--t-sm); }
.log-entry .version { display: block; font-weight: var(--w-bold); color: var(--ink); margin-top: 2px; }
.log-entry h2 { font-size: var(--t-sub); margin-bottom: 12px; }
.log-entry ul { margin: 12px 0 0; padding-left: 20px; color: var(--ink-2); }
.log-entry li + li { margin-top: 6px; }

/* Forms */
.form { display: grid; gap: 18px; max-width: var(--measure-form); }
.form label { display: grid; gap: 6px; font-size: var(--t-sm); color: var(--ink-2); }
.form input, .form textarea, .form select { font: inherit; height: 44px; padding: 0 14px; border: 1px solid var(--line-2); border-radius: var(--r); background: var(--paper); color: var(--ink); width: 100%; }
.form textarea { height: auto; min-height: 120px; padding: 12px 14px; resize: vertical; }
.form input:focus-visible, .form textarea:focus-visible, .form select:focus-visible {
  outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px var(--violet-tint), 0 0 0 4px var(--violet);
}
.form-sent { padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--r); background: var(--green-tint); color: var(--ink); }
.two-col { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 64px; align-items: start; }
.contact-side { display: grid; gap: 24px; }
.contact-side div { padding: 20px 22px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--paper); }
.contact-side strong { display: block; font-weight: var(--w-bold); margin-bottom: 4px; }
.contact-side p { color: var(--ink-2); font-size: var(--t-sm); }

/* Compare */
.versus { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.versus > div { padding: 28px; border: 1px solid var(--line); border-radius: var(--r-frame); background: var(--paper); }
.versus h3 { margin-bottom: 14px; }
.versus ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 10px; color: var(--ink-2); }
.versus li { display: flex; gap: 10px; }
.versus li svg { flex: none; margin-top: 4px; }
.versus .bad svg { color: var(--muted); }
.versus .good svg { color: var(--green); }

/* Footer */
.site-foot { border-top: 1px solid var(--line); background: var(--paper); padding: 56px 0 32px; }
.foot-grid { display: grid; grid-template-columns: minmax(0, 1.5fr) repeat(4, minmax(0, 1fr)); gap: 40px 32px; }
.foot-brand p { margin-top: 16px; color: var(--muted); font-size: var(--t-sm); max-width: var(--measure-copy-tight); }
.site-foot h2 { font-size: var(--t-sm); font-weight: var(--w-bold); color: var(--muted); margin-bottom: 14px; letter-spacing: 0; }
.site-foot div > a { display: block; color: var(--ink-2); text-decoration: none; padding: 5px 0; font-size: var(--t-sm); }
.site-foot div > a:hover { color: var(--ink); text-decoration: underline; }
.foot-bottom { margin-top: 48px; padding-top: 20px; border-top: 1px solid var(--line); display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; color: var(--muted); font-size: var(--t-sm); }
.foot-bottom a { color: inherit; }

/* Responsive */
@media (max-width: 1040px) {
  .threes > div { padding-right: 24px; }
  .threes > div + div { padding-left: 24px; }
  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .facts > div:nth-child(3) { border-left: 0; }
  .facts > div:nth-child(n + 3) { border-top: 1px solid var(--line); }
  .packs, .use-case-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .menu-toggle { display: flex; }
  /* Absolute, not fixed: the header's backdrop-filter makes it the containing
     block for fixed descendants, which would pin the menu inside a 64px box. */
  .site-nav { display: none; position: absolute; top: 100%; left: 0; right: 0; height: calc(100dvh - 64px); background: var(--ground); flex-direction: column; align-items: stretch; padding: 16px var(--gutter); gap: 4px; overflow-y: auto; border-top: 1px solid var(--line); }
  .site-nav.is-open { display: flex; }
  .site-nav > a { font-size: var(--t-lead); padding: 12px; }
  .site-nav-actions { margin: 16px 0 0; flex-direction: column; align-items: stretch; }
  /* In the open menu, Sign in is one more row of navigation and it lines up
     with the rows above it. As a quiet button it kept `justify-content: center`
     from the header, so its label sat at 143px while every nav link's sat at
     12 — the only row in the column that did not line up. Start free stays a
     button, and a button's label belongs in the middle of it. */
  .site-nav-actions .btn-quiet { justify-content: flex-start; font-size: var(--t-lead); font-weight: var(--w-regular); padding: 12px; color: var(--ink-2); }
  .hero { padding: 56px 0 48px; }
  .hero-grid, .feature, .clients-grid, .two-col, .cta-band { grid-template-columns: minmax(0, 1fr); }
  .feature.flip .feature-copy { order: 0; }
  .feature { gap: 32px; padding: 48px 0; }
  .threes { grid-template-columns: minmax(0, 1fr); }
  .threes > div { padding: 24px 0 !important; border-left: 0 !important; }
  .threes > div + div { border-top: 1px solid var(--line); }
  .step { grid-template-columns: 48px minmax(0, 1fr); }
  /* The picture sits in the second column whatever it is drawn as. Named for
     `.shot` alone, a drawn screen fell into the 48px number column and rendered
     48px wide — a rule that knew about one kind of picture and not the other. */
  .step :is(.shot, .ui-stage) { grid-column: 2; }
  .plans, .versus, .help-grid { grid-template-columns: minmax(0, 1fr); }
  .help-grid.use-case-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .page-head { padding: 56px 0 40px; }
  .cta { padding-bottom: 64px; }
  /* The footer was 1850px on a phone, a third of the pricing page and 28% of a
     help article: five groups of one-link-per-line, 34 rows, at the end of
     every page. One link per line is the right shape for a 180px desktop
     column and the wrong one as soon as the column is wide. The links flow and
     wrap from here down, so every one is still present and tappable and the
     footer is a fraction of the height. */
  .foot-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot-grid > div:not(.foot-brand) { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 18px; }
  .foot-grid > div:not(.foot-brand) h2 { flex: 1 0 100%; margin-bottom: 4px; }
  .site-foot div:not(.foot-brand) > a { padding: 6px 0; }
  .log-entry { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .cta-band { padding: 40px 28px; }
  section { padding: var(--section-y-sm) 0; }
  .shot-phone { width: 260px; }
}
@media (max-width: 560px) {
  .facts { grid-template-columns: minmax(0, 1fr); }
  .facts > div + div { border-left: 0; border-top: 1px solid var(--line); }
  .packs, .help-grid.use-case-grid { grid-template-columns: minmax(0, 1fr); }
  .foot-grid { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .hero-actions .btn { width: 100%; }
  /* "5 requests" was wrapping to two lines in a 49px column beside a title
     that had itself wrapped to two. Below this width the count is meta under
     the title, which is where a phone puts it. */
  .demo-head { flex-direction: column; align-items: flex-start; gap: 6px; }
  .demo-count { white-space: nowrap; }
  .demo-row { grid-template-columns: 24px minmax(0, 1fr); }
  .demo-status { grid-column: 2; text-align: left; min-width: 0; }
  .demo-status .to { position: static; display: none; }
  .demo-body.play .demo-status .to { display: inline-flex; }
  .demo-reply { margin-left: 18px; }
}

@media (max-width: 1080px) { .rel-grid.four { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; gap: 28px; }
  .ticks.two { grid-template-columns: 1fr; }
  .rel-grid, .rel-grid.four { grid-template-columns: 1fr; gap: 8px; }
  /* One column of cards reads as rows, the tile beside the words, as the help
     cards do. `padding: 18px 0` took the sides away from a card that kept its
     border, so every tile and title touched the edge of its own card. */
  .rel { display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 2px 14px; align-items: start; padding: 16px 18px; }
  .rel .tile { margin: 0; grid-row: 1 / span 2; }
}

/* ── MORE OF THE DRAWN SCREEN ────────────────────────────────────────────────

   The same frame, the same ladder, different things inside it: a list being
   built, the email that goes out, the reply that comes back, the pack that is
   finished. Each picture says ONE thing, because a picture on a marketing page
   is read at a glance and a second idea in it is not a bonus, it is noise. */

/* The quiet add row at the foot of a list being built. */
.ui-add { display: flex; align-items: center; gap: 9px; padding-top: 13px; border-top: 1px solid var(--line); font-size: var(--t-meta); font-weight: var(--w-medium); color: var(--violet-ink); }
.ui-add span { display: grid; place-items: center; width: 20px; height: 20px; border-radius: var(--r-sm); background: var(--violet-tint); }

/* An email, drawn: who it is to, what it says, and the one thing to press. */
.ui-mail { display: flex; flex-direction: column; gap: 3px; padding-bottom: 14px; border-bottom: 1px solid var(--line); margin-bottom: 16px; }
.ui-mail-to { font-size: var(--t-meta); color: var(--muted); }
.ui-mail-subject { font-size: var(--t-sm); font-weight: var(--w-medium); }
.ui-ask { display: flex; align-items: flex-start; gap: 9px; padding: 8px 0; font-size: var(--t-sm); }
.ui-ask::before { content: ""; flex: none; width: 5px; height: 5px; margin-top: 8px; border-radius: 50%; background: var(--violet); }
.ui-cta { margin-top: auto; padding-top: 18px; }
.ui-cta .ui-do { display: block; text-align: center; padding: 10px 14px; font-size: var(--t-chip); }

/* What one request looks like as a conversation. */
.ui-say { max-width: 88%; border-radius: var(--r); padding: 10px 12px; font-size: var(--t-chip); line-height: 1.45; }
.ui-say + .ui-say { margin-top: 12px; }
.ui-say-who { display: block; font-size: var(--t-meta); font-weight: var(--w-medium); color: var(--muted); margin-bottom: 3px; }
.ui-say.us { background: var(--sunken); color: var(--ink); }
.ui-say.them { margin-left: auto; background: var(--violet-tint); border: 1px solid var(--violet-line); }
.ui-say .ui-file { margin-top: 8px; }
.ui-mail-body { font-size: var(--t-chip); line-height: 1.5; color: var(--ink-2); padding-bottom: 6px; }

/* ── THE PICTURE DECIDES WHEN A BAND IS TWO COLUMNS ──────────────────────────

   A two-column band gives its picture whatever is left of the container. The
   frame is the fixed thing here, and the layout yields to it: when frames were
   a 520 square, a narrower column wrapped the same words onto more lines and
   the square overflowed. Frames are 440 wide now and as tall as their content.

   The bands go side by side only where the picture column holds 440:
   `.art-band` needs (vw − 88) × 6/11 ≥ 440, which is vw ≥ 895, and `.step`
   needs (vw − 192) × 7/12 ≥ 440, which is vw ≥ 947. 1100 clears both with
   room. Below that the copy sits above its picture at full width, which is a
   normal reading order. */
@media (max-width: 1099px) {
  .art-band .container { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .art-band.flip .art-copy { order: 0; }
  .feature:has(.ui) { grid-template-columns: minmax(0, 1fr); gap: 32px; align-items: start; }
  /* The reset to words-first lived only under 900, so from 901 to 1099 a
     flipped band stacked its picture ABOVE its own heading, and the drawing
     under the frame reached for that heading. */
  .feature.flip:has(.ui) .feature-copy { order: 0; }
  .step:has(.ui) { grid-template-columns: 48px minmax(0, 1fr); }
  .step :is(.shot, .ui-stage) { grid-column: 2; }
}
/* On a phone the number goes above its step. Beside it, a 48px column and a
   40px gap took 88px of 358, so a picture drew 253 wide instead of 342 and
   "Public liability insurance" broke over three lines. */
@media (max-width: 599px) {
  .step, .step:has(.ui) { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .step :is(.shot, .ui-stage) { grid-column: 1; }
}

/* The reply box a client types into, and the one field a sign-in page asks for.
   Drawn rather than photographed for the same reason as everything else here:
   at this size a screenshot of a text box is a grey smear. */
.ui-reply { border-radius: var(--r); border: 1px solid var(--line-2); padding: 13px 14px; margin-top: 14px; }
.ui-reply-label { font-size: var(--t-meta); font-weight: var(--w-medium); color: var(--muted); margin-bottom: 5px; }
.ui-reply-box { font-size: var(--t-chip); line-height: 1.45; }
.ui-input { border-radius: var(--r-sm); background: var(--sunken); padding: 10px 12px; font-size: var(--t-chip); }
.ui-hint { font-size: var(--t-meta); color: var(--muted); line-height: 1.5; margin-top: 9px; }

/* A phone. Its stage hugs it (see `.ui.ui-plain`), so the phone itself sits on
   the same disc, swirl and dot as every other picture, not inside an empty box. */
.ui-plain { display: flex; align-items: center; justify-content: center; padding: 26px; background: var(--ground); }
.ui-phone { width: 200px; border: 1px solid var(--line-2); border-radius: 26px; padding: 8px; background: var(--paper); box-shadow: var(--shadow-frame); }
.ui-phone-screen { border-radius: var(--r-band); border: 1px solid var(--line); padding: 18px 16px 16px; display: flex; flex-direction: column; gap: 4px; }
.ui-phone-title { font-size: var(--t-chip); font-weight: var(--w-medium); line-height: 1.3; }
.ui-phone-meta { font-size: var(--t-meta); color: var(--muted); }
.ui-phone-shot { margin: 14px 0; display: grid; place-items: center; height: 116px; border-radius: var(--r); background: var(--sunken); color: var(--muted); }
.ui-phone-do { border-radius: var(--r-sm); background: var(--ink); color: var(--on-dark); text-align: center; padding: 8px; font-size: var(--t-meta); font-weight: var(--w-medium); }

/* The six kinds of request, as six things rather than a paragraph. */
.ui-kinds { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.ui-kind { border-radius: var(--r); background: var(--sunken); padding: 10px 12px; }
.ui-kind b { display: block; font-size: var(--t-meta); font-weight: var(--w-medium); }
.ui-kind span { display: block; font-size: var(--t-meta); color: var(--muted); line-height: 1.35; margin-top: 1px; }

/* A practice's own name and mark, where a client sees it. */
.ui-brand { display: flex; align-items: center; gap: 11px; padding-bottom: 14px; border-bottom: 1px solid var(--line); margin-bottom: 16px; }
.ui-brand i { display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-sm); background: var(--violet); color: var(--on-dark); font-style: normal; font-weight: var(--w-bold); font-size: var(--t-meta); }
.ui-brand b { font-size: var(--t-sm); font-weight: var(--w-medium); }

/* A field with something typed in it, and what came back. */
.ui-search { display: flex; align-items: center; gap: 8px; border-radius: var(--r-sm); background: var(--sunken); padding: 9px 11px; font-size: var(--t-chip); color: var(--muted); margin-bottom: 14px; }
.ui-search b { color: var(--ink); font-weight: var(--w-regular); }
.ui-group { font-size: var(--t-meta); font-weight: var(--w-medium); color: var(--muted); padding: 9px 0 4px; }

/* ── THE LIST CARRIES ON ─────────────────────────────────────────────────────

   Kish: "you know how the website loads when there is no internet, you would
   show some of the lines like that too... just subtle."

   Grey bars where the next rows would be. They say the list is longer than the
   picture without adding a word to read, which is the opposite of what filling
   the space with more real rows would do. They carry no information, so they
   are hidden from a screen reader, and they are the quiet fill — never an
   outline, never a shimmer. */
.ui-ghost { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 18px; align-items: center; padding: 12px 0; border-top: 1px solid var(--line); }
.ui-ghost i { display: block; height: 7px; border-radius: var(--r-pill); background: var(--sunken); }
.ui-ghost i + i { margin-top: 7px; height: 6px; }
.ui-ghost b { display: block; width: 42px; height: 15px; border-radius: var(--r-sm); background: var(--sunken); }
/* Uneven, the way real titles are. Even bars read as a pattern, not as text. */
.ui-ghost:nth-of-type(1) i:first-child { width: 64%; }
.ui-ghost:nth-of-type(1) i + i { width: 38%; }
.ui-ghost:nth-of-type(2) i:first-child { width: 47%; }
.ui-ghost:nth-of-type(2) i + i { width: 30%; }
.ui-ghost:nth-of-type(3) i:first-child { width: 58%; }
.ui-ghost:nth-of-type(3) i + i { width: 34%; }
/* Further down the picture, further out of the way. */
.ui-ghost:nth-of-type(2) { opacity: .72; }
.ui-ghost:nth-of-type(3) { opacity: .48; }

/* The conversation carries on. Bars in a bubble rather than in a row, because
   the shape is what says which kind of list it is. */
.ui-say-ghost { padding: 12px; }
.ui-say-ghost i { display: block; height: 7px; border-radius: var(--r-pill); background: var(--line-2); opacity: .5; }
.ui-say-ghost i + i { margin-top: 7px; width: 58%; }
.ui-say-ghost:nth-of-type(even) { opacity: .6; }

/* Six kinds is six, not "six so far": three rows of two, each as tall as its
   tallest cell, rather than pretending there are more. */
.ui-rows > .ui-kinds { height: 100%; grid-template-rows: repeat(3, minmax(0, 1fr)); align-content: stretch; }
.ui-kind { display: flex; flex-direction: column; justify-content: center; }
/* Who, then the file: two parts, one separator. It is drawn in the gap before
   the file and clipped away when the file wraps onto a line of its own, so no
   line starts with "·". Inside the file it went along to the next line (390,
   two rows); outside, it was stranded at the end of the line above. */
.ui-meta { display: flex; flex-wrap: wrap; margin-left: -12px; }
.ui-meta > * { position: relative; margin-left: 12px; }
.ui-meta > * + *::before { content: '·'; position: absolute; top: 0; left: -8px; color: var(--line-2); }
.ui-who:has(> .ui-meta) { overflow: hidden; }
.ui-task { min-height: 52px; align-items: center; }
.ui-file-line { display: flex; margin-top: 7px; }

/* ── THE FRAME KEEPS ITS OWN RHYTHM ──────────────────────────────────────────

   `p + p { margin-top: 1em }` is the page's prose rhythm and it was reaching
   inside the drawn screen: a title and the meta line under it are two sibling
   paragraphs, so every one of them was pushed 14px apart. A row was 66px tall
   for 40px of text, and the whole set read as airy and loose — which, with the
   frame's own colours being overpainted by `.feature p` earlier, is twice the
   same fault. A component has to be able to say no to the page it sits in.

   Everything the frame needs is declared here, after the parts, so nothing
   below can quietly change what a row measures. */
.ui p + p { margin-top: 0; }
.ui .ui-sub { margin-top: 3px; }
.ui .ui-who { margin-top: 3px; }
.ui .ui-row, .ui .ui-task { min-height: 0; padding: 10px 0; }
.ui .ui-mail-subject { margin-top: 2px; }
/* The email lists more than the picture shows, the same way the lists do. */
.ui-ask-ghost i { display: block; height: 7px; border-radius: var(--r-pill); background: var(--sunken); }
.ui-ask-ghost:nth-of-type(odd) i { width: 62%; }
.ui-ask-ghost:nth-of-type(even) i { width: 44%; }
.ui-ask-ghost { flex: 1; align-items: center; opacity: .8; }
.ui-ask-ghost + .ui-ask-ghost { opacity: .55; }
.ui-field + .ui-field { margin-top: 12px; }
.ui .ui-field + .ui-hint { margin-top: 12px; }
.ui .ui-hint + .ui-row { margin-top: 12px; }
.ui .ui-group + .ui-row { border-top: 0; padding-top: 2px; }
.ui .ui-row + .ui-group { border-top: 1px solid var(--line); margin-top: 8px; }

/* ── A CARD WITH SOMETHING IN IT ─────────────────────────────────────────────

   Kish, of the card grids: "it's just blank white and black, that's it",
   "still no logos or images etc, or like very bland". A tile at the head of a
   card is not decoration — it is the thing the eye lands on, and it is what
   makes eight cards read as eight subjects rather than as eight paragraphs. */
.tile { display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r); background: var(--violet-tint); color: var(--violet-ink); }
.help-card .tile { margin-bottom: 14px; }
.help-card:hover .tile { background: var(--violet); color: var(--on-dark); }
/* The same tile the cards use, at the head of a column of prose. Without it a
   three-column band is three paragraphs and a visitor reads none of them. */
.threes .tile, .facts .tile { margin-bottom: 14px; }
.pack .tile { margin-bottom: 12px; }
.pack:hover .tile { background: var(--violet); color: var(--on-dark); }
/* On a tinted band the tile's own tint is the band's colour, so the tile
   disappears and the icon floats. White is the fill that reads as a tile there,
   the same way the violet tint does on white. */
section.tinted .tile { background: var(--paper); }

/* ── A PAGE THAT OPENS ON SOMETHING ──────────────────────────────────────────

   A trade page used to open with a headline, a paragraph, and then a picture
   on its own line below the fold — an orphan rather than a hero. Where the head
   carries a drawn screen it becomes two columns: the words on the left, the
   picture beside them, at the width the frame needs.

   Above 1100 only, for the same reason the bands stack there — under it the
   picture column cannot hold a 440 frame beside the words, and a frame at any
   other width is the one thing this component exists to prevent. */
.page-head:has(.ui) .container { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: 8px 56px; align-content: center; }
.page-head:has(.ui) .container > *:not(.ui-stage) { grid-column: 1; }
.page-head:has(.ui) .ui-stage { grid-column: 2; grid-row: 1 / span 10; align-self: center; }
.page-head:has(.ui) h1 { margin-bottom: 14px; }
@media (max-width: 1099px) {
  .page-head:has(.ui) .container { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .page-head:has(.ui) :is(.crumbs, h1, .lead, .ui-stage) { grid-column: 1; grid-row: auto; }
}
.contact-side .tile { margin-bottom: 10px; }

/* ── CARDS BECOME ROWS ON A PHONE ────────────────────────────────────────────

   Eight cards stacked one above another is 1,961px of a 13,000px page — the
   single tallest thing on the home page on a phone, and the reader is scrolling
   past it rather than through it. On a narrow screen a card whose whole content
   is a title and a sentence is better read as a row: the tile beside the words
   instead of above them, which is how a phone shows a list of anything. */
@media (max-width: 700px) {
  .help-card { display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 2px 14px; align-items: start; padding: 16px 18px; }
  .help-card .tile { margin-bottom: 0; grid-row: 1 / span 2; }
  .help-grid { gap: 8px; }
}

/* ── THE SECURITY PAGE READS AS PANELS, NOT AS A POLICY ──────────────────────

   Nine detailed sections one under another is a document somebody skims and
   does not trust. The same nine as panels, each with the subject at its head,
   is a page a buyer can find their own question in. The words are unchanged:
   this is about being able to see there are nine answers. */
.security-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-items: start; }
.security-grid > div { padding: 22px 24px; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--paper); }
.security-grid h2 { font-size: var(--t-lead); margin: 12px 0 8px; }
.security-grid p { font-size: var(--t-sm); color: var(--ink-2); }
.security-grid p + p { margin-top: 10px; }
.security-grid ul { margin: 10px 0 0; padding-left: 18px; font-size: var(--t-sm); color: var(--ink-2); }
.security-grid li + li { margin-top: 6px; }
@media (max-width: 860px) { .security-grid { grid-template-columns: minmax(0, 1fr); } }
/* A prose heading with a subject beside it: the tile sits on the heading's line
   rather than above it, because in a column of prose an icon on its own line
   reads as the start of a new section rather than as the mark of this one. */
/* Not a Read next card's tile (`:where` keeps the weight the same): floated,
   a card's second line of text wrapped round under its icon. */
.prose .tile:not(:where(.rel *)) { float: left; margin: 2px 12px 0 0; }
.prose h2:has(+ p) { clear: none; }
/* Text for a screen reader and nothing else: the corner cell of a comparison
   table has no visible label and must not be empty for someone who cannot see
   that the row headings underneath it explain it. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* The way out of a mailto that never opened. Shown only after a submit, so it
   is not a wall of instructions on a form nobody has touched yet. */
.form-fallback { border-radius: var(--r); background: var(--sunken); padding: 16px 18px; }
.form-fallback p { font-size: var(--t-sm); color: var(--ink-2); margin-bottom: 10px; }
.form-fallback pre { margin: 0 0 12px; padding: 12px 14px; border-radius: var(--r-sm); background: var(--paper); border: 1px solid var(--line); font-family: var(--font-mono); font-size: var(--t-meta); line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }
/* A worked pack on the templates page: the tile marks where one list ends and
   the next begins, in a page that is five long lists in a row. */
.prose > .tile { display: inline-grid; margin: 32px 0 12px; float: none; }
.prose > .tile:first-child { margin-top: 0; }
/* A link inside the dark call-to-action band. The site's link colour is a
   violet chosen against white; on this ground it is barely legible, and the
   accessibility sweep could not have caught it because there was no link in
   this band until now. White, underlined, so it still reads as a link. */
.cta-band a:not(.btn) { color: var(--on-dark); text-decoration-color: var(--on-dark-2); }
.cta-band a:not(.btn):hover { text-decoration-thickness: 2px; }
