/* The marketing site.
 *
 * ⚠️ SHARES THE TOKENS, NOT THE FRAME. vokt.css draws a 390px phone app and
 * every measurement in it assumes that. This file is loaded after it and
 * deliberately overrides the pieces that are phone-shaped: the button is not
 * full width here, the page is not a centred column, and there is a desktop.
 *
 * One breakpoint, at 900px. Two would be two to maintain and the content has
 * one real change of shape: side by side, or stacked. */

/* ⚠️ THE ONE OVERRIDE THAT MATTERS, and it was missing.
 *
 * vokt.css sets `body { display: flex; justify-content: center }` — that is how
 * the app centres its 390px column, and it is the frame this file's header
 * claims not to inherit. Without this line every <section> becomes a flex item
 * and the whole brochure lays out SIDEWAYS: eight columns of text scrolling
 * horizontally off the right of a phone.
 *
 * block, explicitly, rather than relying on anything else to win. */
.site {
  display: block;
  margin: 0;
  background: var(--paper);
  color: var(--ink);
}
.site img { max-width: 100%; }

/* Visually hidden until focused, then a real target at the top of the page. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 10;
  background: var(--ink); color: var(--on-accent);
  padding: 10px 16px; border-radius: 0 0 10px 0;
  font-size: 14px; font-weight: 600; text-decoration: none;
}
.skip:focus { left: 0; }
.site a:focus-visible, .site summary:focus-visible {
  outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 4px;
}
/* ⚠️ h4 IS IN THE RESET, and it was not until 2026-09-13. Nothing on the
   brochure used an h4 until "How it works" moved into the hero and its step
   titles were demoted one level; the h4s then arrived carrying the browser's
   default 1.33em top AND bottom margin, which opened about 40px between every
   step title and its own body text. It read as a spacing choice, which is why
   it took a second look to see.

   ⚠️ :where() here for the same reason as p and section below — as `.site h3`
   these weighed (0,1,1) and outranked every single-class rule that wanted to
   set a heading size, including .hero__how's own. */
:where(.site) h1, :where(.site) h2, :where(.site) h3, :where(.site) h4 {
  margin: 0; letter-spacing: var(--display-tracking);
}
:where(.site) h1 { font-size: 34px; font-weight: 800; line-height: 1.08; }
:where(.site) h2 { font-size: 26px; font-weight: 800; line-height: 1.15; }
:where(.site) h3 { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }
/* ⚠️ :where(.site), not .site. These two are the BASE layer — the default for
   any p or section that says nothing for itself — and a base layer must lose to
   a component that does.

   As `.site p` and `.site section` they had specificity (0,1,1), which outranks
   every single-class rule in this file: .readout__figure, .hero__lede,
   .hero__price, .band--vehicle, .scr__lede, and .hero's own padding. None of
   them had ever applied. The brochure's headline figure rendered at 16px
   instead of 64px — smaller than the same number drawn inside the phone beside
   it — which inverted the one decision the section above is named for.

   The tell was in the file: five `max-width: none` declarations, written to
   escape `.site p`'s 68ch and each one outranked in turn. If a fix has to be
   repeated defensively, the rule it is fighting is the bug.

   :where() contributes zero specificity, so these now weigh (0,0,1) — element
   level — and any component class beats them. Do not add a class back onto
   these two selectors. */
:where(.site) p { margin: 0; font-size: 16px; line-height: 1.6; color: var(--ink-2); max-width: 68ch; }
:where(.site) section { padding: 44px var(--gutter); max-width: 1080px; margin: 0 auto; }

/* The app's button fills its column. Here it sits inline beside another one. */
.site .btn {
  width: auto; display: inline-flex; align-items: center; justify-content: center;
  padding: 0 22px; height: 50px; font-size: 15px;
}
.site .btn--ghost { background: none; border: 1.5px solid var(--ink); color: var(--ink); }
/* ⚠️ [aria-disabled], NOT the `disabled` attribute — these CTAs are <a>
   elements (they need to keep looking and sitting like the real buttons they
   replace), and `disabled` only exists on form controls; an anchor with it
   set stays clickable. `pointer-events: none` is what actually stops the
   click; the rest matches vokt.css's .btn:disabled look so this reads as the
   same "unavailable" state the product already uses elsewhere. */
.site .btn[aria-disabled="true"], .site-nav__cta[aria-disabled="true"],
.site-nav a[aria-disabled="true"] {
  opacity: 0.5; pointer-events: none; cursor: default;
}

/* ---- chrome ------------------------------------------------------------- */

.site-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 18px var(--gutter);
  max-width: 1080px; margin: 0 auto;
}
/* ⚠️ color/text-decoration are prophylactic, not a fix for anything visible.
   This anchor wraps only an <img>, so the browser's default blue and underline
   have no text to land on and nothing shows. Found 2026-09-13 while giving
   prose links a default: it was the one anchor on the site with no colour rule
   at all. The moment anyone puts a word beside the wordmark it renders in UA
   blue, on every page. */
.site-head__mark { display: block; line-height: 0; color: inherit; text-decoration: none; }
.site-nav { display: flex; align-items: center; gap: 18px; }
.site-nav a {
  font-size: 14.5px; font-weight: 600; color: var(--ink-2); text-decoration: none;
}
.site-nav a[aria-current="page"] { color: var(--ink); }
.site-nav__cta {
  background: var(--ink); color: var(--on-accent) !important;
  padding: 9px 16px; border-radius: 999px;
}
/* The "not black" version, same box-model as .site-nav__cta so the two read
   as a matched pair of buttons rather than two different components, once it
   is one — see the display: none below.
   ⚠️ HIDDEN FOR PRE-LAUNCH, DELIBERATELY NOT REMOVED FROM THE TEMPLATE. No
   /login route exists yet and there's nothing for an existing customer to
   sign into — see _shell.html's comment on the element itself. Bringing it
   back is two changes, not one: delete the display: none line below AND give
   the <a> a real href, removing its aria-disabled — either alone leaves it
   either invisible with a working link, or visible and going nowhere. */
.site-nav__login {
  background: none; border: 1.5px solid var(--ink); color: var(--ink) !important;
  padding: 7.5px 16px; border-radius: 999px;
  display: none;
}

.site-foot { border-top: 1px solid var(--rule); margin-top: 30px; }
/* ⚠️ NO RULE UNDER THE DARK BAND. The 30px gap and the hairline above exist to
   separate the footer from content sitting on the page background, which is
   what /support ends with and where they read correctly. When the last section
   is the full-bleed .cta, the band has ALREADY made that break — so the gap
   became a strip of page colour under a dark block with a stray line floating
   in it, which is exactly how it looked.

   Keyed on the page's own last section rather than on a body class, so a page
   that gains or loses its CTA is handled without anyone remembering this rule.
   Where :has() is unsupported the footer simply keeps its rule, which is the
   behaviour every page had until now — no layout breaks. */
main:has(> .cta:last-child) + .site-foot { margin-top: 0; border-top-color: transparent; }
.site-foot__inner {
  display: flex; flex-wrap: wrap; gap: 26px; justify-content: space-between;
  max-width: 1080px; margin: 0 auto; padding: 34px var(--gutter) 20px;
}
.site-foot__brand p { font-size: 14px; margin-top: 8px; }
.site-foot__links { display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-start; }
.site-foot__links a { font-size: 14px; font-weight: 500; color: var(--ink-2); text-decoration: none; }
.site-foot__fine {
  max-width: 1080px; margin: 0 auto; padding: 0 var(--gutter) 34px;
  font-size: 12px; line-height: 1.6; color: var(--ink-2);
}

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

/* ⚠️ align-items: start, not center. The shot column (readout + a 538px phone)
   is ~280px taller than the words, so centring floated the readout's top edge
   above the h1 and the headline read as a caption to a number beside it. The
   two now start on the same line. Below 900px the hero is one column and this
   has no effect. */
.hero { display: grid; gap: 34px; align-items: start; padding-top: 24px; }
.hero__lede { font-size: 17px; margin-top: 16px; }
.hero__turn { margin-top: 12px; font-weight: 500; color: var(--ink); }
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; }
.hero__waitlist-line { font-size: 14px; color: var(--ink-2); margin-top: 14px; }
.hero__waitlist-line a { color: var(--ink); font-weight: 600; }
/* ⚠️ .hero__price, .hero__bound and .hero__soon were deleted 2026-09-13 with
   the paragraphs they styled: the price line, the money boundary and the
   pre-launch note all left the hero in one edit. The money boundary is now
   note 2 at the foot of the page; the pre-launch note is gone from the site
   entirely. Do not re-add a price to the hero without reading the comment
   above the notes section in home.html. */

.hero__how { margin-top: 34px; padding-top: 28px; border-top: 1px solid var(--rule); }
.hero__how h3 { font-size: 22px; font-weight: 800; letter-spacing: var(--display-tracking); }
.hero__how h4 { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
.hero__shot { display: flex; flex-direction: column; align-items: center; gap: 26px; }

/* ---- an iPhone, drawn ---------------------------------------------------- */

.phone { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.phone__body {
  position: relative; width: 274px; padding: 10px;
  background: var(--ink); border-radius: 40px;
  box-shadow: 0 18px 40px rgba(21, 24, 28, 0.16);
}
/* ⚠️ A PILL, NOT A NOTCH, since 2026-09-24 — the Dynamic Island shape, to
   match the screenshots' own device rather than an older, rectangular-notch
   one. Founder's call, tried live against the actual hero and disclosure
   photos rather than guessed.

   ⚠️ top: 20px IS MEASURED, not eyeballed — it centres the pill on the real
   status bar icons' own vertical centre, found by scanning both
   screenshots' pixels for the icon row (home.png: rows 55–91; disclosure.png:
   rows 49–81 — both land on the same real status bar height once scaled to
   the phone's display width). It also has to clear disclosure.png's
   centred "vokt." title sitting directly below at that screen's scale,
   which the pill's height keeps clear of with room to spare. Two screens,
   one shared rule — a size or position that works for one and not the
   other is wrong, not a tradeoff to accept. */
.phone__notch {
  position: absolute; top: 20px; left: 50%; transform: translateX(-50%);
  width: 64px; height: 18px; background: var(--ink);
  border-radius: 999px; z-index: 2;
}
.phone__screen {
  /* position: relative for .scr__tabs, which anchors to the foot of the screen
     rather than to the end of the content. */
  position: relative;
  background: var(--paper); border-radius: 31px; overflow: hidden;
  height: 538px; padding: 30px 14px 14px;
}
/* ⚠️ NO TOP PADDING, unlike the base rule above — a real screenshot already
   carries its own status bar (see home.png), so the 30px this file reserves
   elsewhere to clear .phone__notch would just double it up as dead space.
   The notch overlaps the screenshot's own top ~20px instead, which is blank
   background there (the real status bar's icons sit off to one side), the
   same way a physical notch overlaps a real phone's status bar. height:auto,
   not the base rule's fixed 538px: that figure was sized for hand-laid-out
   content, and a photo has its own aspect ratio to keep instead. */
.phone__screen--photo { height: auto; padding: 0; }
.phone__screen--photo img { display: block; width: 100%; height: auto; }
.phone__caption { font-size: 12.5px; color: var(--ink-2); text-align: center; max-width: 270px; }

/* ⚠️ .phone--hero exists to replace the readout card that was removed on
   2026-09-13, and it is load-bearing rather than decorative. The card's job was
   to get ONE figure out of the 274px bezel and onto the page at a size that
   beat the price; deleting it without enlarging the phone would have put the
   largest numeral on the brochure back on $49.99.

   `zoom`, not `transform: scale()`. Zoom reflows — the enlarged phone actually
   occupies its new size in the grid — where a transform scales the paint and
   leaves a 274px hole in the layout, so the caption and the column gap would
   sit against the old box. Zoom is in every engine this site targets; where it
   is not, the phone renders at its normal size and nothing breaks.

   ⚠️ 1.28, which is what fits: the hero's shot column is ~460px at 1440 and
   274 * 1.28 = 351, leaving the gutter the drop shadow needs. Raising it
   overflows the column before it overflows the page, so the failure is a
   cramped shadow rather than a scrollbar, and it is easy to miss. */
.phone--hero { zoom: 1.28; }

/* ⚠️ .phone--sm is for a phone standing beside a SHORT column. Common questions
   is five collapsed rows and a link — 340px against a 585px phone — and unlike
   the hero there is no more copy to add that the section wants.

   ⚠️ 0.86 is a floor, not a preference. The screen's smallest type is 7.5px
   (.scr__gauge-ends, .scr__strip-sub), and 0.86 takes that to 6.4px. Going
   further to close the gap completely would need ~0.65, which renders those
   labels at 4.9px — illegible, and the phone stops being evidence that these
   are real screens, which is the only reason it is on the page. The remaining
   space is the better trade. */
.phone--sm { zoom: 0.86; }

@media (max-width: 899px) {
  /* Both modifiers off on a phone: the column is already narrow and the
     screens are at their legibility floor there. */
  .phone--hero, .phone--sm { zoom: 1; }

  /* ⚠️ PRICING AND SUPPORT DROP OFF ENTIRELY BELOW 900PX — not hidden behind
     anything, just not in the header at this width. They're still reachable
     from site-foot__links, the same way About/Terms/Privacy always have been
     at every width. Login and Coming soon are the two things worth a
     permanent spot in a phone's limited header space; a menu to tuck the
     other two into was tried (git history, 2026-09-25) and dropped once it
     was actually used on a phone — not worth the interaction cost for two
     links the footer already carries. */
  .site-nav__link--pricing, .site-nav__link--support { display: none; }
}

/* ⚠️ --ink-2, NOT --ink-3, on every one of the drawn-screen rules below.
   vokt.css's token block records a 2026-09-10 audit: --ink-3 is ~3.1:1 on
   --paper and fails WCAG AA for body text, so it is for inverted panels and
   decoration only. tests/test_public.py greps for exactly this.

   ⚠️ THE TRAP IS THAT THE APP USES --ink-3 HERE. These screens reproduce app
   components, and copying the app's token was the obvious thing to do — but the
   app's own comment says the same thing the test does, and a brochure is a more
   public place to fail contrast than a screen behind a login. Two exceptions
   stay: the ✕ glyph and the chart axis, both named in the test.

/* ---- the reproduced screens --------------------------------------------- */
/* Built from the product's tokens, so a palette change reaches the brochure —
   and since 2026-09-13 from its real icons, logotype and vehicle renders too.
   See the note at the top of site/_screens.html. */

.scr { display: flex; flex-direction: column; gap: 10px; font-size: 11px; }
/* ⚠️ A tabbed screen reserves room for the bar, which is absolutely positioned
   against .phone__screen. Without the padding the last card sits under it. */
.scr--tabbed { height: 100%; padding-bottom: 40px; }
.scr__bar { display: flex; justify-content: center; padding-bottom: 2px; }
.scr__bar--back { justify-content: space-between; align-items: center; color: var(--ink); }
.scr__bar-spacer { width: 13px; }
/* The real logotype, at the scale 74px sits at on a 390px screen. */
.scr__bar svg.topbar__logo { width: 48px; height: auto; }
.scr__sec { display: flex; align-items: center; gap: 5px; color: var(--ink-2); }
/* ⚠️ Now a flex row, because every label on the real screens carries an icon
   and the drawing had none. Anything that was a bare label still works. */
.scr__label {
  font-size: 8.5px; font-weight: 500; letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--ink-2);
  display: flex; align-items: center; gap: 4px;
}
.scr__label svg { flex: none; width: 10px; height: 10px; }
/* Two-word labels ("Licensed to", "RUC remaining") wrap at this scale and the
   icon then sits beside a ragged block. Tightening the tracking buys the line
   back without dropping the font size, which is already at the floor. */
.scr__pair .scr__label, .scr__duo .scr__label { letter-spacing: 0.08em; }
.scr__val { font-size: 11.5px; font-weight: 600; color: var(--ink); display: block; }
.scr__when { font-size: 8px; font-weight: 500; color: var(--ink-2); display: block; margin-top: 1px; }
.scr__hr { height: 1px; background: var(--rule); }

/* ---- the vehicle strip, the part that was missing entirely --------------- */
.scr__strip { display: flex; gap: 7px; }
.scr__strip-card {
  flex: 1; min-width: 0; background: var(--panel); border-radius: 11px;
  padding: 7px; display: flex; flex-direction: column; gap: 4px; text-align: center;
}
.scr__strip-name { font-size: 9.5px; font-weight: 600; line-height: 1.2; }
.scr__strip-middle {
  flex: 1; display: flex; flex-direction: column; justify-content: center;
  align-items: center; gap: 0; min-height: 0;
}
/* ⚠️ THE PLATE USED TO BE A SEPARATE OVERLAID <span>, CENTRED HERE WITH
   PADDING TUNED AGAINST line-height:1's UNUSED DESCENDER SPACE. That fight
   is gone as of 2026-09-24: the plate is baked into the image itself now
   (see _screens.html's top comment for why), so this rule is just an <img>.
   Chasing history: .scr__plate's padding went through three calibration
   passes (2026-09-22 twice, 2026-09-24 once) and still wasn't stable across
   browser zoom levels, because `.phone--hero`'s `zoom: 1.28` re-rounds
   sub-pixel padding differently at different total zoom — a moving target,
   not a bug with one correct answer. */
.scr__render { display: block; width: 100%; height: 40px; object-fit: contain; }
.scr__strip-make { font-size: 8.5px; font-weight: 600; line-height: 1.25; color: var(--ink); }
.scr__strip-sub { font-size: 7.5px; font-weight: 500; line-height: 1.3; color: var(--ink-2); }
.scr__strip-card--empty {
  align-items: center; justify-content: center; gap: 2px; color: var(--ink-2);
}
.scr__strip-card--empty svg { width: 14px; height: 14px; }
.scr__empty-title { font-size: 9px; font-weight: 600; color: var(--ink-2); }
.scr__duo, .scr__pair { display: flex; gap: 10px; align-items: stretch; text-align: center; }
.scr__duo { background: var(--panel); border-radius: 12px; padding: 9px 11px; }
/* ⚠️ :not(.scr__rule) is the fix, NOT `flex: none` on the divider itself.
   `.scr__duo > div` weighs (0,1,1) and `.scr__rule` only (0,1,0), so the
   divider can never win on its own selector — the same specificity trap as the
   base layer at the top of this file, one more time. Exclude it here. */
.scr__duo > div:not(.scr__rule), .scr__pair > div:not(.scr__rule) { flex: 1; }
/* ⚠️ flex: none, or THE DIVIDER BECOMES A BLOCK. .scr__rule is a div, so the
   `.scr__duo > div { flex: 1 }` rule above catches it too and grows a 1px line
   into a third column the width of the other two. It has looked like this
   since the screens were drawn; it is easy to read as a deliberate grey panel
   rather than as a broken hairline, which is why it survived. */
.scr__rule { flex: none; width: 1px; background: var(--rule); align-self: stretch; }
.scr__card, .scr__aside { background: var(--panel); border-radius: 12px; padding: 10px 11px; display: flex; flex-direction: column; gap: 8px; }
.scr__figure { display: flex; align-items: baseline; gap: 5px; }
.scr__figure strong { font-size: 26px; font-weight: 600; letter-spacing: -0.02em; }
.scr__figure span { font-size: 11px; color: var(--ink-2); }
.scr__figure em { margin-left: auto; font-style: normal; font-size: 10px; color: var(--ink-2); }
.scr__gauge { height: 5px; border-radius: 3px; background: var(--rule); overflow: hidden; }
.scr__gauge span { display: block; height: 100%; background: var(--ink); }
/* ⚠️ The gauge's end labels. A bar half full says nothing without the size of
   the licence it is half of, and the drawing had the bar without the words. */
.scr__gauge-ends {
  display: flex; justify-content: space-between; align-items: baseline; gap: 6px;
  font-size: 7.5px; font-weight: 500; color: var(--ink-2); margin-top: -3px;
}
.scr__aside p { font-size: 9.5px; line-height: 1.4; color: var(--ink-2); margin: 0; }
.scr__aside-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.scr__aside-head svg { flex: none; width: 10px; height: 10px; color: var(--ink-2); }
/* The third disclosure group, collapsed, with its count — the app's `peek`. */
.scr__fold {
  display: flex; align-items: center; gap: 5px; color: var(--ink-2);
  padding-top: 2px;
}
.scr__fold .scr__label { flex: 1; }
.scr__count {
  font-size: 7.5px; font-weight: 700; color: var(--ink-2);
  background: var(--rule); border-radius: 6px; padding: 1px 5px;
}

/* ---- the tab bar --------------------------------------------------------- */
/* Absolutely positioned so it sits at the foot of the screen the way it does on
   the phone, rather than after whatever content happens to be tall enough. */
.scr__tabs {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; padding: 5px 4px 6px;
  background: var(--paper); border-top: 1px solid var(--rule);
}
.scr__tab {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
  color: var(--ink-2); font-size: 6.5px; font-weight: 500;
}
.scr__tab svg { width: 13px; height: 13px; }
.scr__tab.on { color: var(--ink); font-weight: 600; }
.scr__steps { display: flex; gap: 3px; }
.scr__steps i { flex: 1; height: 3px; border-radius: 2px; background: var(--rule); }
.scr__steps i.on { background: var(--ink); }
.scr__head { font-size: 17px; font-weight: 800; letter-spacing: -0.03em; }
.scr__lede { font-size: 10px; line-height: 1.45; color: var(--ink-2); margin: 0; }
.scr__row { display: flex; align-items: center; gap: 8px; font-size: 10.5px; font-weight: 500; color: var(--ink-2); }
.scr__row i {
  width: 14px; height: 14px; border-radius: 7px; flex: none; font-style: normal;
  display: flex; align-items: center; justify-content: center;
  font-size: 7px; border: 1px solid var(--rule); color: var(--ink-3);
}
.scr__row i.yes { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.scr__row--wide { justify-content: space-between; color: var(--ink); }
.scr__row--wide em { display: block; font-style: normal; font-size: 9px; color: var(--ink-2); }
.scr__btn {
  background: var(--ink); color: var(--on-accent); border-radius: 9px;
  text-align: center; padding: 10px; font-size: 11.5px; font-weight: 600; margin-top: 2px;
}
.scr__note {
  font-size: 8px; line-height: 1.5; color: var(--ink-2);
  text-align: center; margin: 2px 0 0; max-width: none;
}
.scr__readout { display: flex; align-items: baseline; gap: 6px; }
.scr__readout strong { font-size: 13px; font-weight: 600; }
.scr__readout span { font-size: 10px; color: var(--ink-2); }
.scr__chart { width: 100%; height: 62px; }
.scr__chart line { stroke: var(--rule); stroke-width: 1; }
.scr__chart path { stroke: var(--ink); stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.scr__chart circle { fill: var(--ink); }
.scr__axis { display: flex; justify-content: space-between; font-size: 8.5px; color: var(--ink-3); }

/* ---- what you get ------------------------------------------------------- */
/* Two columns on desktop: seven items in one column runs long and thin beside
   1080px of nothing, and the list is the whole section. */
/* ⚠️ grid-column: 1 — the FIRST column only, so it lands under the two tiles
   rather than spanning the page. It has been in three places today: inside the
   list column as a footnote to the list, then spanning both columns, now under
   the prices it actually qualifies. This is the right one: it is a statement
   about what the price does not buy, and it now sits under the price.

   ⚠️ max-width: none, not "no max-width". Deleting the declaration does not
   free the paragraph — it hands it back to `:where(.site) p`, which sets 68ch.
   In a column this narrow that would not bite today, but it is why the rule is
   written out rather than omitted. */
/* The scope note under the benefits list. Quieter than the ticks and set off
   by a rule, because it is what the price does NOT stretch to. */
.gets__fine {
  margin: 18px 0 0; padding-top: 16px; border-top: 1px solid var(--rule);
  font-size: 13px; line-height: 1.6; color: var(--ink-2); max-width: none;
}
.offer__fine {
  /* No grid-column: it is not a grid child any more, it is the second thing in
     .offer__left. The margin is the whole spacing now. */
  margin: 14px 0 0; font-size: 12px; line-height: 1.55;
  color: var(--ink-2); max-width: none;
}

/* ---- terms, privacy and about, in the site frame -------------------------- */
/* ⚠️ These three pages are shared with the app, so their markup uses vokt.css's
   app classes — .block, .display, .lede, .legal-h2, .legal-meta. Those all
   exist here because site.css layers over vokt.css. What they do NOT have is a
   column: base.html's .app wrapper is what held them to 390px, and without it
   they would run the full 1080px, which is unreadable for a page of prose.

   ⚠️ Deliberately NOT a phone-width column either. The point of moving them is
   that somebody on a laptop can read them. 74ch is a measure, not a device. */
/* ⚠️ NO max-width ANYWHERE ON THESE THREE PAGES, INCLUDING PARAGRAPHS —
   founder's call, 2026-09-26, overriding `:where(.site) p`'s 68ch measure
   specifically here. Every other page on the site keeps that 68ch prose cap;
   these three don't, so headings, list items and paragraph text all run the
   same 1080px column instead of paragraphs alone reading narrower than
   everything around them. There was a 74ch cap on the whole block before
   that, and briefly a 68ch one on just .banner/.legal-toc after — both were
   my inventions, not asked for, and both got reverted the same day this
   comment was rewritten. Nothing on these pages is capped now; leave it that
   way unless asked. */
.legal p { max-width: none; }

/* ⚠️ Do not put max-width on .legal itself either: `:where(.site) section` has
   `margin: 0 auto`, so narrowing the section centres the whole page and it
   stops lining up with the header and the footer. That was the first attempt. */
.legal .display { font-size: 38px; line-height: 1.1; }
/* Every adjacent pair, not just block-to-block: the list heading sits in a
   .block directly after a .banner and had nothing separating them. */
.legal > * + * { margin-top: 26px; }
.legal .lede { font-size: 16px; }
.legal .spacer { display: none; }

/* The numbered <h2>s read fine at the 390px size vokt.css gives them, but on
   a reading column this wide they look undersized next to the 38px .display
   above them — the same gap .legal .display exists to close. */
.legal .legal-h2 { font-size: 22px; padding-top: 28px; }
.legal .legal-h2--first { padding-top: 0; }

/* ---- content bands ------------------------------------------------------- */

/* ⚠️ align-items: start, the same note .hero and .steps carry. On /pricing the
   excluded column is taller than the included one — it carries the NZTA fine
   print — so centring floated the two h2s off each other's baseline and the
   two halves stopped reading as a comparison. */
.band { display: grid; gap: 26px; align-items: start; }
/* ⚠️ .band--vehicle, .band__render and .band__shot were deleted 2026-09-13 with
   the "Teslas, today" section. .band and .band--split SURVIVE — /pricing and
   /support both still use them, so do not take the rest of this block with
   them. The render itself lives on in the hero; see .hero__render above. */
.band__fine { font-size: 13.5px; color: var(--ink-2); margin-top: 12px; }
.band--split h2 { font-size: 20px; }
.band--split p { margin-top: 10px; font-size: 15px; }

/* ⚠️ THE .steps SECTION IS GONE — "How it works" folded into the hero on
   2026-09-13 — and its layout rules went with it. What survives below is the
   list only, which now lives inside .hero__how.

   ⚠️ KEEP THIS WARNING. vokt.css:137 styles `.steps` as the app's signup
   progress bar (`display: flex; gap: 6px`), and site.css layers over vokt.css.
   Any future <section class="steps"> on the brochure inherits that and lays out
   sideways — heading, body and closing line in a row — which is what a0967fb
   "Stop the marketing site laying out sideways" was about, and what this
   section hit again afterwards. Give any new .steps an explicit `display`, or
   pick a name the app does not already own. The children are safe: .steps__list
   and .steps__n do not collide with vokt.css's .steps__step or .steps-list. */
/* ⚠️ .steps__edge was deleted with the competitive line it styled — see the
   comment in home.html for the sentence itself and why it went. */
.steps__list { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 20px; }
/* ⚠️ THE NUMBER SITS BESIDE THE STEP, not above it. Two columns: the disc in
   the first, the title and body stacked in the second, with the disc spanning
   both rows so it reads as belonging to the whole step rather than to the
   title.

   It also buys back the height the third step costs — stacked, each step was
   three rows (disc, title, body) and ran about 100px; beside, it is two rows
   and runs about 65px. Three steps laid out this way take roughly the same
   space as two did stacked. */
.steps__list li {
  display: grid; grid-template-columns: 28px 1fr;
  column-gap: 14px; row-gap: 6px; align-items: start;
}
.steps__n {
  grid-column: 1; grid-row: 1 / span 2;
  width: 28px; height: 28px; border-radius: 14px; background: var(--ink);
  color: var(--on-accent); display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 600;
  /* Nudged to sit optically level with the title's cap height rather than with
     the top of its line box. */
  margin-top: 1px;
}
.steps__list li h4, .steps__list li p { grid-column: 2; }
.steps__list p { font-size: 15px; }
/* ⚠️ Step 2's link points at #disclosures, the Common questions section, NOT at
   /settings/what-vokt-stores. That reference page is the fuller answer but it
   sits behind `current_user`, so a stranger reading the brochure would be sent
   to a sign-in wall by a link offering to show them what vokt reads before they
   sign up — the exact opposite of what the link is for. The section it does
   point at carries the disclosure screen and the question it answers. If a
   public disclosure page is wanted, that is a small new route and this href
   should move to it. */
.steps__link {
  color: var(--ink); text-decoration: underline;
  text-underline-offset: 3px; font-weight: 500;
}
.steps__link:hover { color: var(--ink-2); }

/* ⚠️ .shots__* and .diff__* went with the two sections cut from home on
   2026-09-13. .next__* stayed: the roadmap moved to /pricing rather than
   being deleted. */
.next__grid { display: grid; gap: 20px; margin-top: 22px; }
.next__item p { margin-top: 7px; font-size: 15px; }
.next__item {
  background: var(--panel); border-radius: 16px; padding: 18px 20px;
}
.next__tag {
  display: inline-block; font-size: 10px; font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-2);
  border: 1px solid var(--rule); border-radius: 999px; padding: 3px 9px; margin-bottom: 9px;
}
.next--narrow { max-width: 860px; }

/* ⚠️ Added 2026-09-30 with the roadmap reorder. "Read more" is a native
   <details>, styled to match .qa's device without its rules. The request line
   sits under the grid rather than in it. */
.next__more { margin-top: 10px; }
.next__more summary {
  cursor: pointer; list-style: none; font-size: 14px; font-weight: 500;
  color: var(--ink-2); text-decoration: underline; text-underline-offset: 3px;
}
.next__more summary::-webkit-details-marker { display: none; }
/* "Read more" says "Read less" while it is open, and sits BELOW the extra text so
   it moves down as the text opens. A checkbox rather than <details>, because
   <details> always puts its summary above its content. Both words are in the
   markup and CSS picks one, so it needs no script. */
.next__more { margin-top: 10px; position: relative; }
.next__more-toggle { position: absolute; opacity: 0; width: 1px; height: 1px; }
.next__more-extra { display: none; }
.next__more-extra p { margin-top: 0; font-size: 15px; }
.next__more-toggle:checked ~ .next__more-extra { display: block; }
.next__more-label {
  display: inline-block; margin-top: 8px; cursor: pointer; font-size: 14px;
  font-weight: 500; color: var(--ink-2); text-decoration: underline;
  text-underline-offset: 3px;
}
.next__more-toggle:focus-visible ~ .next__more-label {
  outline: 2px solid currentColor; outline-offset: 3px;
}
.next__more-close { display: none; }
.next__more-toggle:checked ~ .next__more-label .next__more-open { display: none; }
.next__more-toggle:checked ~ .next__more-label .next__more-close { display: inline; }
.next__request { margin-top: 24px; font-size: 15px; color: var(--ink-2); }

.ticks { margin: 12px 0 0; padding: 0; list-style: none; display: grid; gap: 9px; }
.ticks li { position: relative; padding-left: 24px; font-size: 15px; color: var(--ink-2); }
.ticks li::before {
  content: "\2713"; position: absolute; left: 0; top: 0;
  width: 16px; height: 16px; border-radius: 8px; background: var(--ink);
  color: var(--paper); font-size: 9px; display: flex; align-items: center; justify-content: center;
}
/* ⚠️ The excluded list. Same disc, a multiplication sign rather than a tick,
   and --ink-3 rather than --ink. NO RED: the brand is monochrome by decision
   (see the app's disclosure marks in vokt.css), so the difference has to be
   carried by the glyph and the tone. That is also what keeps it legible to
   anyone who cannot separate red from green. */
.ticks--no li::before { content: "\2715"; background: var(--ink-3); font-size: 8.5px; }

.page-head { padding-bottom: 8px; }
/* ⚠️ A section directly under a page heading does not need its own 66px of top
   padding — the heading is already the break. Without this, /support ran 74px
   of nothing between "Support" and "Common questions" once the standfirst was
   removed.

   :where() so it carries no specificity: /pricing's .offer sets its own
   padding-top and must keep winning, and any future page-head neighbour can
   override by saying so. */
:where(.page-head + section) { padding-top: 18px; }
.page-head p { margin-top: 12px; font-size: 17px; max-width: 60ch; }

/* ⚠️ padding-top: 0 closes the hole the standfirst left. With the subtitle
   gone, .page-head's 8px bottom plus this section's default 66px top put ~113px
   of nothing between "Pricing" and the cards, which read as a missing element
   rather than as breathing room. .plans is used on /pricing only, so this is
   safe to set here rather than scoping it. */
/* ⚠️ TWO COLUMNS AT EVERY WIDTH, phones included. It was single-column below
   900px; the founder's call is that two plans a thumb apart can be compared
   where one stacked above the other reads as a sequence. Everything else in
   .plan shrinks under 900px to pay for it — see the media query at the foot. */
.plans { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
/* The list column. .offer is the grid; these are its two children. */
/* ⚠️ padding-top is NOT 0. It was, to close the hole the removed standfirst
   left — but the cards then sat hard under the h1 and the badge's -9px
   overhang had no clearance. 22px is the founder's "a bit more space". */
.offer { display: grid; gap: 30px; align-items: start; padding-top: 22px; }
.plan {
  /* ⚠️ 2px, matching .plan--best. At 1.5px against the selected card's 2px the
     two cards' inner boxes differed by half a pixel, so every row in them sat
     0.5px apart — invisible, but it is the kind of drift that becomes visible
     the moment anything else changes. Same metrics, different colour. */
  background: var(--panel); border: 2px solid var(--rule); border-radius: 18px;
  padding: 18px 18px 20px; display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
}
.plan--best { border-color: var(--ink); }
/* ⚠️ THE PILL IS OUT OF FLOW, and that is what keeps the two cards aligned at
   every width. It has been through three positions in one day:

     1. Stacked above the heading — added ~28px to the Yearly card alone, so its
        heading, price, note and button all sat lower than Monthly's.
     2. In the heading row, pushed right — fixed the alignment until the cards
        were narrowed on 2026-09-13, at which point the row needed 205px and had
        157px, the pill wrapped, and (1) came back.
     3. This: a corner badge, absolutely positioned, contributing nothing to the
        card's vertical rhythm. The cards can now be any width without the
        Yearly one growing a row the Monthly one does not have.

   ⚠️ So .plan needs position: relative, and the .plans grid needs clearance
   above it for the -9px overhang — which the section's own top padding gives. */
.plan { position: relative; }
.plan__tag {
  position: absolute; top: -9px; right: 14px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  background: var(--ink); color: var(--on-accent); border-radius: 999px; padding: 4px 10px;
}
.plan__price { font-size: 27px; font-weight: 800; letter-spacing: -0.03em; color: var(--ink); }
/* ⚠️ white-space: nowrap on the ROW, sized so it fits. "a year" wrapped under
   "$49.99" on a 201px card at a 34px figure, which gave the Yearly card an
   extra line the Monthly one did not have and broke the alignment the corner
   badge exists to protect. Sized from measurement: at 30px the figure is ~97px
   and the period ~42px inside 161px of card. If the price ever gets longer
   than $99.99, re-measure rather than assume. */
/* ⚠️ The label is a SEPARATE element, not a span inside .plan__price. Inside
   it, `.plan__price span` — which styles the period — would have caught it too,
   and the row's white-space: nowrap would have had to hold three pieces on one
   line inside a 144px card. Quieter than the figure, which is the founder's
   brief: the price leads, the label says which price it is. */
.plan__label {
  font-size: 13px; font-weight: 600; color: var(--ink-2);
  letter-spacing: 0.01em; margin: 0;
}
.plan__price { white-space: nowrap; }
.plan__price span { font-size: 14px; font-weight: 500; color: var(--ink-2); margin-left: 5px; letter-spacing: 0; }
.plan__note { font-size: 14px; }
/* ⚠️ align-self: center overrides .plan's align-items: flex-start for this
   child only. The card is now a figure and a button, so a left-hung button
   under a centred-looking price read as misaligned rather than as deliberate.
   Smaller too: the default .site .btn is 50px, which is sized for the hero
   where it is the only thing on the row. */
.plan .btn {
  margin-top: auto; align-self: center;
  height: 42px; padding: 0 18px; font-size: 14px;
}
/* ⚠️ Matched to .hero__how h3 on home — 22px/800 — rather than left at the
   site h2 default of 31px. Founder's call: the two headings do the same job on
   their respective pages and should carry the same weight. If .hero__how h3
   changes, change this with it; they are deliberately a pair. */
.gets h2 {
  margin-bottom: 6px; font-size: 22px; font-weight: 800;
  letter-spacing: var(--display-tracking);
}

.qa { border-bottom: 1px solid var(--rule); padding: 16px 0; }
.qa summary {
  font-size: 16px; font-weight: 600; letter-spacing: -0.01em; color: var(--ink);
  cursor: pointer; list-style: none;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary::after { content: "+"; float: right; color: var(--ink-2); font-weight: 500; }
.qa[open] summary::after { content: "\2212"; }
.qa p { margin-top: 10px; font-size: 15px; max-width: 68ch; }
/* The mailto in "How do I cancel?". Underlined rather than coloured — the brand
   is monochrome, so colour is not available to mark a link. */
/* ⚠️ PROSE LINKS, and this is why it is not just `.site a`.
   Every mailto on /support was rendering in the browser's default BLUE, because
   site.css styled the nav, the footer, .faq__more and .qa individually and
   never set a default for a link sitting in ordinary copy.

   ⚠️ Scoped to p / li / dd rather than to all anchors, because .btn IS an
   anchor and vokt.css's .btn does NOT clear text-decoration — a blanket
   `.site a { text-decoration: underline }` would have underlined every button
   on the site, including the nav's Get started. Buttons are never inside a
   paragraph; prose links always are.

   :where() so it carries zero specificity and every component rule still wins
   — .site-nav a, .site-foot__links a and .steps__link all sit above it. */
:where(.site) p a, :where(.site) li a, :where(.site) dd a {
  color: var(--ink); text-decoration: underline; text-underline-offset: 3px;
}
:where(.site) p a:hover, :where(.site) li a:hover, :where(.site) dd a:hover {
  color: var(--ink-2);
}
/* ⚠️ .faq--split, NOT .faq. Two columns since 2026-09-13, when the disclosure
   phone moved in beside home's questions: that section was words-only and
   368px tall between two 700px+ neighbours, so the page read tall, short,
   tall. One column below 900px, phone last.

   ⚠️ IT WAS ON BARE .faq FOR ABOUT AN HOUR AND THAT BROKE /support. Support
   uses <section class="faq"> with the h2 and every <details> as DIRECT
   children — there is no words wrapper to be column one — so the grid dealt
   the questions alternately into two columns. Source order then ran across the
   page instead of down it, and the heading sat alone in a cell. It still
   looked deliberate, which is what made it easy to miss: the page returned 200
   and nothing overflowed.

   The modifier is the guard. Any .faq with a phone gets .faq--split and the
   grid; a plain .faq stays in normal flow. Matches .band / .band--split. */
.faq--split { display: grid; gap: 26px; align-items: start; }
.faq h2 { margin-bottom: 6px; }
.faq__shot { display: flex; justify-content: center; }
.faq__more { display: inline-block; margin-top: 20px; font-size: 15px; font-weight: 600; color: var(--ink); }

.cta {
  text-align: center; background: var(--ink); max-width: none;
  padding-top: 52px; padding-bottom: 52px;
}
.cta h2 { color: var(--paper); }
.cta > * { max-width: 1080px; margin-left: auto; margin-right: auto; }
.cta p { color: var(--ink-3); margin: 12px auto 24px; max-width: 46ch; }
.cta .btn--primary { background: var(--paper); color: var(--ink); }

/* ---- waitlist ------------------------------------------------------------- */
/* The first form this site has ever had. Narrower than the default 1080px
   section — .fields/.consents/.actions (vokt.css) were built for the app's
   390px column, and a form stretched to the brochure's full width reads odd
   long before it reads wide. */
.waitlist-form { max-width: 420px; }
.waitlist-form .fields { margin-top: 28px; }
.waitlist-form .consents { margin-top: 20px; }
.waitlist-form .actions { margin-top: 24px; }
.waitlist-form .btn { width: 100%; }

/* The honeypot. Hidden here AND marked aria-hidden/tabindex="-1" on the input
   itself (waitlist.html) — a plain `display: none` is what a careful bot
   checks for and skips, but a screen-reader user must never be able to reach
   this field at all, or they could fill it and trip the same silent-drop a
   bot does. Belt and suspenders: CSS hides it visually, the markup hides it
   from assistive tech and the tab order. */
.waitlist-form__hp {
  position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden;
}

.waitlist-success { text-align: center; }
.waitlist-success p { margin: 12px auto 0; max-width: 46ch; }

/* ---- narrow phones ------------------------------------------------------- */
/* ⚠️ UNVERIFIED IN A REAL BROWSER and the numbers say why it is needed. Two
   cards side by side is the founder's call, so at a 390px iPhone the content
   column is ~342px and each card is ~165px — inner width ~129px after padding.
   "$49.99" at 28px is ~88px and " a year" ~40px, which is 128px of 129. One
   font-metric difference and the period wraps.

   ⚠️ Chrome will not size a window below 500px, so this could not be checked
   the way everything else in this file was. It is sized from measurement at
   500px scaled down, not from looking at it. CHECK IT ON A PHONE. */
@media (max-width: 479px) {
  .plan { padding: 14px 14px 16px; }
  .plan h2 { font-size: 19px; }
  .plan__price { font-size: 23px; }
  .plan__price span { font-size: 12.5px; margin-left: 4px; }
  .plan__note { font-size: 12.5px; }
  .plan .btn { height: 42px; padding: 0 14px; font-size: 13.5px; }
  .plan__tag {
    font-size: 8.5px; letter-spacing: 0.06em; padding: 3px 7px; right: 10px; top: -8px;
  }
  .plans { gap: 10px; }
}

/* ---- desktop ------------------------------------------------------------- */

@media (min-width: 900px) {
  :where(.site) h1 { font-size: 46px; }
  :where(.site) h2 { font-size: 31px; }
  /* ⚠️ :where() here too, and for the same reason as the base rule above.
     As `.site section` this outranked `.hero`'s padding-top: 34px on the very
     next line, and `.band--vehicle`'s left/right 32px three lines down. */
  :where(.site) section { padding: 66px 32px; }
  .hero { grid-template-columns: 1.05fr 0.95fr; gap: 48px; padding-top: 34px; }
  .band { grid-template-columns: 1fr 1fr; gap: 44px; }
  /* ⚠️ This used to be repeat(3, 1fr) three times on three consecutive lines,
     for three consecutive sections. The page had one layout idea and used it
     three times in a row. */
  .faq--split { grid-template-columns: 1.1fr 0.9fr; gap: 48px; }
  .steps__list { gap: 24px; }
  /* ⚠️ FOUR COLUMNS, one per tile, founder's call 2026-09-13 after seeing 2x2.
     Each lands at about 255px on a 1080px band.

     ⚠️ THE COUNT IS HAND-PICKED AND MATCHES THE TILES. This section held 3
     tiles, then 2, then 3, then 4 across a single day, and every change needed
     this number changed with it or a tile was orphaned on its own row. A fifth
     tile will not fit at this width — switch to
     `repeat(auto-fit, minmax(240px, 1fr))` then rather than picking again. */
  .next__grid { grid-template-columns: repeat(4, 1fr); }
  /* ⚠️ The cards sit in the NARROWER column and the list in the wider one.
     The list is seven lines and needs the room; the cards are two figures and
     do not. Swap the ratio if the cards should lead instead. */
  /* ⚠️ 0.76fr, narrowed 2026-09-13. With the headings gone the cards hold a
     figure and a button, so at 0.86fr they were 201 wide by 144 tall — wider
     than tall, having been taller than wide an hour earlier. Narrowing the
     column squares them from the width side rather than padding them out from
     the inside, and hands the difference to the list, which has eight lines. */
  /* ⚠️ column-gap and row-gap SEPARATELY. As a single `gap: 46px` the row gap
     applied between the tiles and the disclaimer under them too, which put 46px
     of grid gap plus the paragraph's own margin between the two — the reason it
     read as floating rather than as a note on the tiles. The columns still want
     46px; the rows do not. */
  .offer { grid-template-columns: 0.76fr 1.24fr; gap: 46px; }
  .plans { gap: 16px; }
  /* ⚠️ Squarer since the period and note left the card — the stack is now
     heading, figure, button, so the padding does the shaping rather than the
     content. gap is the lever if it needs to be squarer still. */
  /* ⚠️ Re-squared after the labels came back on 2026-09-13: the extra row took
     the card from 176x163 (1.08) to 176x198 (0.89), past square in the
     direction the founder had already asked to fix once. Padding and gap are
     the levers; the column width is what sets the 176. */
  .plan { padding: 22px 14px 22px; gap: 10px; }
  .plan__price { font-size: 28px; }
}

/* ⚠️ RESTATED HERE, 2026-09-26, privacy/terms audit — vokt.css already has a
   @media print block hiding .site-head/.site-nav/.site-foot/.legal-toc, but
   it is dead on this frame, for TWO separate reasons:
   1. This file loads AFTER vokt.css (see site/_shell.html) and sets
      .site-head/.site-nav to `display: flex` unconditionally, above. Same
      specificity, later in the cascade, so that rule wins even when
      printing.
   2. vokt.css's print rule also tried `body { background: #fff }`, but
      .site (this file, line ~20) sets the background on <body class="site">
      via a CLASS selector — specificity 0,1,0 against `body`'s 0,0,1 — so
      .site wins regardless of source order, print or not. A plain `body`
      selector was never going to beat it.
   Confirmed by rendering /privacy to print: the nav bar, the "Coming soon"
   pill and the beige page background all printed. Fixed by restating the
   hides here (last in the cascade, so #1 stops mattering) and targeting
   `.site` itself for the background (so #2 stops mattering too). */
@media print {
  .site-head, .site-nav, .site-foot, .legal-toc { display: none; }
  .site { background: #fff; color: #000; }
}
