/* ⛔ GENERATED FILE — DO NOT EDIT.
   Source: design/components.css · regenerate with `npm run tokens`.
   It exists only because marketing/site/ deploys as its own root. */
/* ═════════════════════════════════════════════════════════════════════════════
   MentionChecker — the shared component layer. Built entirely from design/tokens.css.

   ⛔ GENERATED COPY at marketing/site/components.css — edit this one, run `npm run tokens`.
   ⛔ A component that exists on both surfaces lives HERE. The site having its own button
   and the app having another is exactly how the two drifted into opposite languages —
   a bordered, 999px-pill, 76px-rhythm site in front of a borderless, 96px-rhythm app.
   ═════════════════════════════════════════════════════════════════════════════ */

/* ── layout ──────────────────────────────────────────────────────────────────
   ⭐ A COLUMN, not a full-bleed grid. A report stretched to 1400px stops being
   readable prose and becomes a spreadsheet. */
.wrap { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 var(--s6); }
.col  { width: 100%; max-width: 840px; margin: 0 auto; }
.col-wide { max-width: 1000px; }

/* ⭐ THE SECTION BAND — the Xero move. When a section needs to be set apart, the PAGE
   changes colour full-bleed. It does not grow another box. */
.band { background: var(--band); }
.section { padding: var(--s9) 0; }
.section-lg { padding: var(--s10) 0; }
.sec-head { max-width: 660px; margin-bottom: var(--s6); }
.sec-head > * + * { margin-top: var(--s3); }

/* ── planes: the only "card", and it has no border (rule 1) ─────────────────── */
.plane    { background: var(--plane); border-radius: var(--r-lg); padding: var(--s6); }
.plane-sm { background: var(--plane); border-radius: var(--r);    padding: var(--s5); }
/* A plane that lifts off the BAND instead of sinking into the page. */
.raised   { background: var(--page);  border-radius: var(--r-lg); padding: var(--s6); box-shadow: var(--lift); }

/* ── buttons ─────────────────────────────────────────────────────────────────
   ⛔ RULE 5: --r-sm rectangles, never pills. Neither calendly.com nor xero.com uses a
   pill CTA; a pill is the most generic shape on the web and it was the loudest thing
   making the old site read as a template. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  height: 44px; padding: 0 var(--s5); border-radius: var(--r-sm);
  font-size: .9375rem; font-weight: var(--w-med); letter-spacing: -.012em; white-space: nowrap;
  /* ⛔ Explicit, for the same reason .field sets border:0 below — the app gets these from
     Tailwind's preflight, the static site has no preflight, and the site's primary CTA is now
     a real <button> submitting a real form. Without them it renders with the native 1px border
     and the system font, which is visibly not the same control as the app's. */
  border: 0; cursor: pointer; font-family: inherit;
  transition: background var(--t-fast) ease, box-shadow var(--t-fast) ease,
              opacity var(--t-fast) ease, transform .12s ease;
}
.btn:active:not(:disabled) { transform: scale(.985); }
.btn:disabled { opacity: .35; cursor: not-allowed; }
/* ⭐ THE PRIMARY ACTION, on both surfaces — the site's "Check" and the app's "Run check"
   are the same act and must not be two different colours.
   ⚠️ It is --cta (green), NOT --accent (blue). The accent identifies the product; the CTA
   is the thing you press. See design/tokens.css. */
.btn-a { background: var(--cta); color: var(--on-cta); }
.btn-a:hover:not(:disabled) { background: var(--cta-press); }
/* Navy. The secondary weight-bearing action — Calendly's near-black CTA. */
.btn-p { background: var(--ink); color: var(--on-ink); }
.btn-p:hover:not(:disabled) { opacity: .88; }
/* ⛔ A ring, not a border — a 1px border shifts layout by 1px and leaves a row of
   mixed buttons sitting half a pixel off. */
.btn-o { color: var(--ink); box-shadow: inset 0 0 0 1px var(--hair-2); }
/**
 * ⛔⛔ HOVER IS A SCRIM, NOT `--plane`, AND THAT IS THE WHOLE POINT.
 *
 * 🪤 MEASURED 2026-09-08, ON BOTH SURFACES AND IN BOTH THEMES: these buttons live inside `.pk`
 * cards and the quote panel, which ARE `--plane` — so hovering painted the card's own colour onto
 * the button and nothing happened. light card rgb(245,243,238) → hover rgb(245,243,238);
 * dark card rgb(17,25,40) → hover rgb(17,25,40). The site's pricing cards had it too.
 *
 * ⭐ An absolute token can only be right on the one ground it was picked against. `--scrim` is a 5%
 * overlay — navy in light, white in dark — so it is a STEP FROM WHATEVER IS UNDERNEATH: the page,
 * a card, a panel, a plate. ⛔ Do not put a named surface back here.
 */
.btn-o:hover:not(:disabled) { background: var(--scrim); }
.btn-q { color: var(--ink-3); }
/* ⛔ Same reason as `.btn-o` above — a quiet button sits on a card just as often. */
.btn-q:hover:not(:disabled) { background: var(--scrim); color: var(--ink); }
.btn-lg { height: 52px; padding: 0 var(--s6); font-size: 1rem; }
.btn-sm { height: 36px; padding: 0 var(--s4); font-size: .8125rem; }
.btn-xs { height: 28px; padding: 0 var(--s3); font-size: .75rem; gap: var(--s1); }

/* ── inputs ──────────────────────────────────────────────────────────────────
   A field is a WELL — a recess in the page, not a box drawn on top of it. */
.field {
  width: 100%; height: 46px; padding: 0 var(--s4);
  background: var(--well); border-radius: var(--r-sm);
  /* ⛔ border:0 explicitly. The app gets this free from Tailwind's preflight; the static
     site has no preflight, and the native 1px input border was showing through the well. */
  border: 0; appearance: none;
  transition: box-shadow var(--t-fast) ease, background var(--t-fast) ease;
}
.field::placeholder { color: var(--ink-4); }
/* ⚠️ background-COLOR, not the shorthand. The shorthand resets background-image, which wiped the
   chevron off a focused select — the one moment it is most needed. */
.field:focus { outline: none; background-color: var(--page); box-shadow: 0 0 0 1px var(--accent-ink), 0 0 0 4px var(--accent-wash); }

/* ⭐ A SELECT HAS TO LOOK LIKE ONE. `.field` sets `appearance: none` above — deliberately, so the
   well is not fighting a native control — and that also removes the chevron. The result reads as a
   text box: it invites typing, ignores it, and hides the fact that there is anything to choose.
   ⛔ It affected EVERY select in the product, not one screen: the scan drawer's market and
   "ask each question" controls had shipped this way, and setup's market control inherited it.
   ⚠️ The right padding is reserved for the chevron so a long label cannot run underneath it. */
select.field {
  padding-right: calc(var(--s4) * 2 + 12px);
  background-image: var(--caret);
  background-repeat: no-repeat;
  background-position: right var(--s4) center;
  background-size: 12px 12px;
  cursor: pointer;
}
.field-lg { height: 56px; padding: 0 var(--s5); font-size: 1.0625rem; border-radius: var(--r); }
/* Reveals itself only on focus — for editing text in place. */
.field-bare { background: transparent; height: auto; padding: 0; border-radius: 0; width: 100%; }
.field-bare:focus { background: transparent; box-shadow: none; outline: none; }

/* ⭐ THE ONE FIELD — the hero control, and the product's whole promise in one shape. */
.checkbar {
  display: flex; align-items: center; gap: var(--s2);
  background: var(--page); border-radius: var(--r); padding: 6px 6px 6px var(--s5);
  box-shadow: inset 0 0 0 1px var(--hair-2), var(--lift);
  transition: box-shadow var(--t) var(--ease);
}
.checkbar:focus-within { box-shadow: inset 0 0 0 1px var(--accent-ink), 0 0 0 4px var(--accent-wash), var(--lift); }
.checkbar .field { background: transparent; box-shadow: none; padding: 0; height: 44px; font-size: 1.0625rem; }

/* ── chips — the ONLY pill (rule 5) ─────────────────────────────────────────── */
.chip {
  display: inline-flex; align-items: center; gap: var(--s2);
  height: 26px; padding: 0 10px; border-radius: var(--r-pill);
  font-size: .75rem; font-weight: var(--w-med); white-space: nowrap;
  background: var(--well); color: var(--ink-3);
}
.chip-ok   { background: var(--ok-wash);     color: var(--ok); }
.chip-warn { background: var(--warn-wash);   color: var(--warn); }
.chip-bad  { background: var(--bad-wash);    color: var(--bad); }
.chip-acc  { background: var(--accent-wash); color: var(--accent-ink); }
.chip .x { color: var(--ink-4); margin-right: -3px; padding: 0 2px; line-height: 1; }
.chip .x:hover { color: var(--bad); }
/* The action INSIDE a chip that is not "remove" — "Track" on Settings' second tier (P11.3). ⛔ Not
   `.x`: that one turns red on hover, which is the wrong promise for a button that adds. */
.chip .tr { color: var(--ink-3); padding: 0 4px; font-size: .6875rem; font-weight: var(--w-med); line-height: 1;
  border-left: 1px solid var(--hair-2); margin-left: 2px; padding-left: 8px; }
.chip .tr:hover:not(:disabled) { color: var(--accent-ink); }
/* ⭐ A chip that is a BUTTON — "Track" on a name the answers added (PLAN.md P11.3). Chip-sized so
   it sits level with the "you" chip and with Exclude beside it; a hairline and the hover plane are
   what say it can be pressed. ⛔ Not a `.btn`: a 36px button beside a 26px chip would make every
   row a different height. ⚠️ Once pressed nothing takes its place — the "tracked" chip it used to
   turn into is gone (Pavel, 2026-09-14). */
.chip-btn { cursor: pointer; border: 0; font: inherit; font-size: .75rem; font-weight: var(--w-med);
  background: transparent; color: var(--ink-3); box-shadow: inset 0 0 0 1px var(--hair-2);
  transition: background var(--t-fast) ease, color var(--t-fast) ease; }
.chip-btn:hover:not(:disabled) { background: var(--scrim); color: var(--ink); }
.chip-btn:disabled { color: var(--ink-4); cursor: default; }

/* ── segmented control ───────────────────────────────────────────────────────
   One well with a sliding plane inside it. Not a row of pills. */
.seg { display: inline-flex; padding: 3px; background: var(--well); border-radius: var(--r-sm); gap: 2px; }
/* ⭐ `a` AS WELL AS `button`, added 2026-09-08 for the account area's tab strip. A tab that NAVIGATES
   is a link — it has an href, it opens in a new tab, it middle-clicks. ⛔ Rendering it as a button
   to reuse this selector would have been styling deciding semantics, which is the wrong way round.
   ⚠️ `a` needs the flex centring `button` gets natively, hence display/align below. */
.seg button, .seg a {
  height: 32px; padding: 0 var(--s4); border-radius: var(--r-xs);
  display: inline-flex; align-items: center;
  font-size: .8125rem; font-weight: var(--w-med); color: var(--ink-3);
  transition: background var(--t) ease, color var(--t) ease, box-shadow var(--t) ease;
}
.seg button:hover, .seg a:hover { color: var(--ink); }
.seg button.on, .seg a.on { background: var(--page); color: var(--ink); box-shadow: var(--lift); }

/* ── rows: a list separated by a hairline and nothing else ──────────────────── */
.row { display: flex; align-items: center; gap: var(--s4); padding: var(--s4) 0; }
.row + .row { border-top: 1px solid var(--hair); }

/* ── meters ──────────────────────────────────────────────────────────────────
   ⭐ The track is a WELL and the fill is --you or --rival. Never a third colour:
   every bar on this product answers the same question. */
.meter { position: relative; height: 6px; border-radius: var(--r-pill); background: var(--well); overflow: hidden; }
.meter i { position: absolute; inset: 0 auto 0 0; border-radius: var(--r-pill); display: block; background: var(--rival); }
.meter i.you  { background: var(--you); }
.meter i.grow { transition: width 1.1s var(--ease); }

/* ── ⭐ the you / rival pair. The product's dichotomy, as a component. ───────── */
.vs { display: flex; align-items: center; gap: var(--s4); }
.vs .nm { width: 96px; flex: none; font-size: .875rem; color: var(--ink-2); }
.vs .n  { width: 40px; text-align: right; font-size: .8125rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.vs .meter { flex: 1; }
.vs.me .nm, .vs.me .n { color: var(--you); font-weight: var(--w-med); }

/* ── the masthead's one disclosure: "N questions", and which N on a click ───────
   ⭐ Here and not in app/globals.css because the hero mock IS the app's report and carries it too
   (2026-09-14). A dotted underline, not a link's solid one: it opens something on the page rather
   than leaving it, and it keeps the label's ink until asked. The panel is anchored to the META
   LINE (`position: relative` on that line), never to the trigger — at 390px the trigger wraps to
   the middle of the line, and a panel hung off it would leave the page. `100%` is the line's
   width, so on a phone the panel is the page's width and on a desk it stops at 560px.
   ⚠️ It sits inside `.t-label`, which is uppercased, tracked and --ink-4; the questions are prose
   somebody typed and must read as prose. ⚠️ `list-style` set explicitly — the app's Tailwind
   preflight strips it from every `ol`. The app's print block hides the panel and the underline. */
.qs-btn {
  text-decoration: underline dotted; text-decoration-color: var(--ink-4);
  text-decoration-thickness: 1px; text-underline-offset: 3px;
  transition: color var(--t-fast) ease;
}
.qs-btn:hover, .qs-btn:focus-visible, .qs-btn[aria-expanded="true"] { color: var(--accent-ink); text-decoration-color: currentColor; }
.qs-pop {
  position: absolute; z-index: 40; top: calc(100% + var(--s2)); left: 0;
  width: min(560px, 100%); max-height: min(70vh, 540px); overflow-y: auto;
  padding: var(--s3) var(--s4);
  background: var(--raised); border-radius: var(--r);
  box-shadow: inset 0 0 0 1px var(--hair), var(--lift);
  text-transform: none; letter-spacing: 0; font-weight: var(--w-body);
  font-size: .875rem; line-height: 1.5; color: var(--ink-2); text-wrap: pretty;
}
.qs-pop[hidden] { display: none; }
.qs-list { margin: 0; padding-left: 1.6em; display: grid; gap: var(--s2); list-style: decimal; }
.qs-list li::marker { color: var(--ink-4); font-variant-numeric: tabular-nums; }

/* ── the stat: a micro-label over a large number ────────────────────────────── */
.stat .t-label { display: block; margin-bottom: var(--s2); }
.stat .v { font-size: 2.25rem; font-variant-numeric: tabular-nums; letter-spacing: -.035em; font-weight: var(--w-semi); line-height: 1; }
.stat .v small { font-size: .8125rem; font-weight: var(--w-body); color: var(--ink-4); letter-spacing: -.01em; margin-left: var(--s2); }

@media (max-width: 860px) {
  .wrap { padding: 0 var(--s4); }
  .section { padding: var(--s8) 0; }
  .section-lg { padding: var(--s9) 0; }
}

/* ── the engine marks, on plates (five plates for six engines since 2026-09-11) ────────────────────────────────────────
   ⭐ MOVED HERE FROM marketing/site/styles.css 2026-09-03: it is on BOTH surfaces now — the
   site's hero and the app's "The questions we'll ask" — and a component that exists on both
   lives in this file. ⛔ Do not copy it back; two copies is the drift this file exists to end.
   ⭐ Sized entirely in `em`, so the cluster tracks whatever heading it sits in without a single
   media query — a 4rem display on the site, a 1.3rem h2 in the app.
  (original note follows.)
   ⭐ THE FOUR ENGINES, on plates. Sized in em throughout, so the whole cluster tracks the
   display's clamp() at every width — nothing here needs a media query.

   ⛔ The headline carries no highlighter: the marks are the accent (rule 4), and a wash
   under "AI search" plus four coloured logos is two accents fighting. --accent-mark is
   still live on the app's landing headline.

   ⭐ THE PLATE IS --plate, NOT --page. That token exists for exactly this: the white
   ground under a THIRD PARTY's artwork, drawn for a light background, which stays light
   even when everything around it does not. See design/tokens.css.

   ⛔ The unevenness is DELIBERATE and must stay irregular. Size, corner radius, tilt and
   baseline offset all differ per plate, and none of the four rotations is a round number
   or a mirror of another. Regularise any one of them and the row snaps back to a stock
   logo strip — which is the thing it exists not to be. */
/* ⚠️ vertical-align sits the plates on the CAP band, not the baseline. The cluster is
   taller than the caps, so aligning it to the baseline hangs it visibly low. */
.engines { display: inline-flex; align-items: center; gap: .07em; margin-left: .26em; vertical-align: .07em; }
/* ⭐ THE SHAPE IS THE MARK'S. Our logo is a SQUIRCLE — flat sides, generous smooth corners
   — so the plates are squircles too, and the row reads as part of the same family instead
   of as a strip of borrowed logos.
   ⛔ An earlier pass skewed each plate to force irregularity. It looked wrong, and the
   reason is worth keeping: skew makes the SIDES bend, and our mark's sides are straight.
   The unevenness has to come from size, corner and tilt — never from distortion.
   ⚠️ The radius is a PERCENTAGE, not an em: a squircle's corner scales with the box, and
   the four plates are deliberately different sizes. */
.engines .plate {
  display: grid; place-items: center; flex: none;
  background: var(--plate);
  /* ⛔ NO RING. --lift is tuned for a 28px-padded plane and disappears under a 50px chip,
     so this is a tighter shadow of the same family — small radius, low alpha, no visible
     edge (rule 6). A 1px ring here read as a drawn border, which is what rule 1 is against. */
  box-shadow: 0 1px 2px rgba(var(--ink-rgb), .05), 0 5px 14px -5px rgba(var(--ink-rgb), .16);
}
/* ⚠️ height only — each mark keeps its own aspect. Squaring them distorts Perplexity,
   whose official artwork is 29.65 × 37.5, not a square. */
.engines .plate svg { display: block; height: .44em; width: auto; }
/* ⭐ OPTICAL sizing, not mathematical. At equal heights the Gemini star reads small (its
   mass is central) and the Perplexity mark reads tall (its artwork is narrow). */
/* ⛔⛔ `svg.` IS LOAD-BEARING, NOT TIDINESS. These were `.engines .e-gem` / `.e-ppx` (0,2,0) against
   `.engines .plate svg` (0,2,1) above — so BOTH LOST ON SPECIFICITY and every mark rendered at the
   same .44em, which is exactly the thing the note above says not to do. MEASURED 2026-09-07: every
   glyph identical in the site hero and the app. ⚠️ Fixing it makes Gemini bigger and Perplexity
   smaller everywhere both surfaces draw the cluster — that is the correction, not a side effect. */
.engines .plate svg.e-gem { height: .50em; }
.engines .plate svg.e-ppx { height: .41em; }
/* Copilot's ribbons are 513 × 481 — near square, mass in the middle like Gemini's; a touch over the base. */
.engines .plate svg.e-cop { height: .47em; }

/* ⭐ The unevenness: size, corner and tilt all vary, and no value is a round number, a
   repeat, or a mirror of another. ⛔ Do not tidy these into a pattern.

   ⚠️ Two louder versions were tried and rejected. Skewing each shape bent its SIDES, and
   the mark's sides are straight — it read as damaged. Non-square boxes with per-corner
   radii and a 6–13° tilt made the irregularity obvious, and obvious was worse. The tilt
   here is deliberately near-invisible at 31% roundness: the row should feel hand-placed,
   not hand-drawn. */
.engines .p1 { width: .86em; height: .86em; border-radius: 31%; transform: rotate(-7deg)   translateY(.015em); }
.engines .p2 { width: .78em; height: .78em; border-radius: 34%; transform: rotate(5deg)    translateY(-.04em); }
.engines .p3 { width: .84em; height: .84em; border-radius: 29%; transform: rotate(-3.5deg) translateY(.035em); }
.engines .p4 { width: .80em; height: .80em; border-radius: 33%; transform: rotate(8deg)    translateY(-.02em); }
/* ⭐ THE FIFTH PLATE — Copilot, after the four (2026-09-11). Same rule: its own size, corner and
   tilt, none of them a repeat of the others'. */
.engines .p5 { width: .83em; height: .83em; border-radius: 30%; transform: rotate(-5.5deg) translateY(.025em); }

/* A tilted plate is decoration; do not spin it for anyone who asked the page to hold still. */
@media (prefers-reduced-motion: reduce) { .engines .plate { transition: none; } }

/* ⭐ ONE DECLARATION SCALES ALL FOUR. Everything in `.engines` is sized in `em` off the cluster's
   own font-size, so a modifier here moves the plates, the gaps and the optical corrections
   together — there is nothing per-plate to keep in sync.
   ⚠️ Needed because the site's hero heading is ~64px and the app's h2 is 22px. At the shared
   ratio the marks came out ~19px in the app, which is smaller than the favicon beside the brand
   name and read as an afterthought rather than as the four places being checked. */
.engines-lg { font-size: 1.9em; }

/* ⭐ THE SAME PLATE, INLINE IN A SENTENCE — for a mark that is NAMING a service rather than
   decorating a headline. The heading cluster above is decoration and gets to be uneven; these sit
   in running text beside their own names, so they are regular, square and quiet.

   ⛔ THE PLATE IS --plate AND THAT IS THE WHOLE POINT. Every one of these logos is drawn for a
   light background — the OpenAI knot is solid black, Perplexity is a dark stroke — so on the dark
   theme, unplated, ChatGPT disappears entirely. --plate is the one token that stays light when
   everything around it does not (design/tokens.css). ⛔ Never swap it for --page or --plane.

   ⚠️ Sized in em so the row tracks whatever text it sits in, and the two optical corrections are
   the cluster's: the Gemini star reads small because its mass is central, Perplexity reads tall
   because its artwork is 29.65 × 37.5 rather than square. */
.engine-inline {
  display: inline-grid; place-items: center;
  width: 1.12em; height: 1.12em; border-radius: 29%;
  background: var(--plate);
  box-shadow: 0 1px 2px rgba(var(--ink-rgb), .05), 0 3px 8px -4px rgba(var(--ink-rgb), .14);
  /* ⭐⭐ `.08em`, AND IT IS MEASURED RATHER THAN EYEBALLED — reported live 2026-09-09 (Pavel:
     "engine names a bit down").
     ⛔ THIS FILE USED TO SAY "no vertical-align: a magic offset would only be right at one font
     size", and that conclusion was half wrong. The 2026-09-03 note behind it measured a plate
     sitting 4.8px BELOW the label — a NEGATIVE offset, i.e. the wrong SIGN. Rejecting the whole
     approach on one bad value cost the label its baseline for six days.
     ⭐ The label is now plain inline text in the paragraph (app/Engines.js), so its baseline is the
     paragraph's BY CONSTRUCTION — measured at exactly 0.00px against surrounding text, at every
     size and for all four marks. Only the decoration needs a nudge, and `em` makes it track:
       MEASURED in Chrome against this stylesheet, plate centre vs surrounding text centre —
         13px text:  middle +1.05px · 0em +0.80px · .04em +0.29px · .08em −0.23px · .12em −0.74px
         15px text:  middle +1.52px · 0em +1.24px · .04em +0.64px · .08em +0.05px · .12em −0.56px
     ⚠️ `middle` is what the inline-flex version effectively did, and note it gets WORSE as the type
     grows — which is the failure the old comment predicted, just from the other direction. */
  vertical-align: .08em;
  margin-right: .3em;
}
.engine-inline svg { display: block; height: .58em; width: auto; }
.engine-inline .e-gem { height: .66em; }
.engine-inline .e-ppx { height: .55em; }
.engine-inline .e-cop { height: .62em; }


/* ── the pricing ladder and its quote panel, on BOTH surfaces ────────────────
   ⭐⭐ CANONICAL HERE SINCE 2026-09-08. The site's pricing panel and the app's Billing screen sell
   the same eleven rungs out of the same `lib/packs.js`; this is the one copy of how they look.
   ⛔ Do not re-add any of it to marketing/site/styles.css or to a component's own <style> — the
   whole reason it is here is that it was in three places and drifting in each.

   ⚠️ THE SITE'S LOCAL ALIASES ARE RESOLVED. `styles.css` defines `--fg`, `--fg-2`, `--fg-3` and
   `--accent-bg` for its own convenience; design/ cannot depend on those, so the real tokens are
   named. The site renders identically — its aliases point at these. */
/* ⚠️ FOUR, and the two surfaces reach it differently — do not "simplify" this comment away.
   The SITE shows the free card plus FEATURED=3 paid rungs ($9/$17/$39 — everything under the $85
   ceiling in `scripts/site-pricing.mjs`); the APP has no free rung and its own FEATURED.
   ⛔ The two counts are independent since 2026-09-09 and must not be resynced — the ceiling is a
   rule for strangers, and a signed-in customer has no flinch left to protect.
   ⚠️ It went 4 → 3 → 4 within one day as the ladder was repriced. `test/site-pricing.test.mjs`
   asserts this number IS the site's card count, so it cannot drift silently again. */
.pk-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s4); }
.pk { border-radius: var(--r-lg); padding: var(--s6) var(--s5); background: var(--plane); display: flex; flex-direction: column; }
/* ⭐ The picked card is the ONE place a ring is worth spending — on the site that is the free card,
   the thing we want pressed. ⚠️ The app has no free rung, so nothing carries this there. */
.pk.pick { background: var(--page); box-shadow: inset 0 0 0 1px var(--accent-ring), var(--lift-2); }
/* ⭐ THE NAME ROW CARRIES THE BADGE, so it is a space-between row. ⚠️ A card with NO badge is just
   the name — nothing below it moves, which is what lets the entry rung drop its placeholder. */
.pk .nm { font-size: .8125rem; font-weight: var(--w-semi); letter-spacing: -.015em; display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.pk .nm .tg { font-size: .625rem; font-weight: var(--w-med); letter-spacing: .06em; text-transform: uppercase; color: var(--accent-ink); background: var(--accent-wash); border-radius: var(--r-pill); padding: 2px 8px; }
/* ⭐ THE PRICE — the accent serif, one of only two places it is allowed (design/tokens.css).
   ⚠️ Adjust the SIZE when the face changes, never the weight. */
/* ⚠️ NOTHING UNDER THE PRICE SINCE 2026-09-13 (Pavel: the rate, the saving badge and the free
   card's grey line all went that day), so the price carries the gap to the button itself. */
.pk .amt { font-family: var(--font-accent); font-weight: var(--w-accent); margin-top: var(--s4); margin-bottom: var(--s6); font-size: 2.375rem; letter-spacing: -.018em; line-height: 1; }
/* ⚠️ `margin-top: auto` is what keeps the buttons on one line across cards of unequal height. */
.pk .btn { margin-top: auto; padding-top: 0; width: 100%; height: 40px; font-size: .8125rem; }

/* ⛔ `.save` / `.pk-quote-save` ARE GONE — 2026-09-13 (Pavel: "not making sense … feels like lower
   rates are a rip-off"). The badge measured every rung against the $9 door, and on a ladder with a
   22× spread that put "Save 95%" on the big packs, which reads as the door being the con. Nothing
   relative is printed on a card any more: a credit count, a price, a button. */

/* ⭐ A PANEL IN THE CARDS' OWN LANGUAGE — same --plane, same radius, same serif price — because it
   is the next thing you can buy, not a stray form control. ⛔ It was a bare field on the page
   ground with a right-aligned number and nothing binding them, and that came out again. */
.pk-quote { margin-top: var(--s4); background: var(--plane); border-radius: var(--r-lg); padding: var(--s6); }
/* ⚠️ THE ROW. Named for the site's no-JS split — `.pk-quote-fallback` shows until the script runs,
   `.pk-quote-live` after. The app is always scripted, so it simply always uses this one; ⛔ that is
   better than a second class name for one rule. */
.pk-quote-live { display: flex; align-items: center; justify-content: space-between; gap: var(--s6); flex-wrap: wrap; }
.pk-quote-fallback { font-size: .9375rem; color: var(--ink-2); }
.pk-quote-fallback b { color: var(--ink); font-weight: var(--w-semi); }
.pk-quote-fallback[hidden], .pk-quote-live[hidden] { display: none; }
/* ⛔⛔ THE ASK COLUMN TAKES THE LEFTOVER SPACE; IT DOES NOT SET THE ROW'S WIDTH.
   🪤 Pavel, 2026-09-10: *"see how many credits card, it doesn't fit"*. ⚠️ Flex children size to
   MAX-CONTENT by default, and `.pk-quote-terms` — the two lines of small print added under the
   field the day before — is one ~300px sentence. So this column demanded 300px next to a 190px
   answer column in a 472px row, and the row wrapped: the price and the Buy button dropped below
   the field with the panel half empty beside them.
   ⭐ `flex: 1 1 auto; min-width: 0` makes the SENTENCE wrap instead of the ROW. `flex: none` on the
   answer keeps the price and the button off the shrink path — they are the two things on this
   panel that must never be squeezed. ⚠️ Harmless on the marketing site, whose ask column holds only
   the label and the field and is narrower than its share either way. */
.pk-quote-ask { flex: 1 1 auto; min-width: 0; }
.pk-quote-ask label { display: block; font-size: 1.0625rem; font-weight: var(--w-semi); letter-spacing: -.024em; color: var(--ink); }
.pk-quote-field { margin-top: var(--s3); display: flex; align-items: center; gap: var(--s3); }
/* ⚠️ Sized for "1,000,000" and no wider — a field that can hold a paragraph invites one. */
.pk-quote-field .field { width: 11ch; background: var(--page); font-variant-numeric: tabular-nums; }
.pk-quote-field span { font-size: .9375rem; color: var(--ink-3); }
/* ⭐ THE TERMS OF THE PURCHASE, UNDER THE FIELD THAT MAKES IT (Pavel, 2026-09-10). ⛔ They used to
   be a paragraph BELOW the whole panel and a clause in the screen's lede — two places, neither of
   them where the number is typed. ⚠️ The left column, because the question is "how many credits?"
   and these are the answer's small print; the right column is the price and the button and nothing
   else belongs in it. ⭐ `display: block` on the children rather than a `<br>`: they are two
   separate facts and each wraps on its own at 390px. */
/* ⚠️ `text-wrap: pretty` for the ORPHAN, not for the balance: at 390px the first line ends on a
   bare "to." on its own row. ⛔ Progressive — where it is unsupported the line simply wraps as it
   did, which is why the copy is not written to depend on it. */
.pk-quote-terms { margin-top: var(--s4); font-size: .75rem; line-height: 1.5; color: var(--ink-4);
                  text-wrap: pretty; }
.pk-quote-terms > span { display: block; }

/* ⭐ THE RIGHT-HAND END: the price, and under it the button that acts on it. ⛔ Wrapped together
   because the row is space-between — a third loose child would centre the price between the field
   and the button instead of keeping the answer whole.
   ⭐ THE BUTTON SITS UNDER THE PRICE, not beside it — same order as a pack card, where the thing
   you press is the last thing in the column. */
.pk-quote-end { display: flex; flex-direction: column; align-items: flex-end; gap: var(--s3); flex: none; }
.pk-quote-out { text-align: right; }
/* ⭐ THE FIGURE LINE: the price and its saving on one baseline, because they are one fact.
   ⚠️ `align-items: baseline` sits a 13px pill on the baseline of a 40px serif rather than centring
   it against the cap. */
.pk-quote-fig { display: flex; align-items: baseline; justify-content: flex-end; gap: var(--s3); }
.pk-quote-out output { font-family: var(--font-accent); font-weight: var(--w-accent);
                       font-size: 2.5rem; line-height: 1; letter-spacing: -.018em; }
.pk-quote-out output[hidden], .pk-quote-talk[hidden], .pk-quote-buy[hidden] { display: none; }
/* ⛔ A REAL BUTTON, not the accent serif. It sat in the price's slot styled like the price — large,
   blue, no affordance — and read as a heading rather than something to press (Pavel, 2026-09-04).
   ⚠️ `.btn-p` (ink) and not `.btn-a` (mint): mint is the primary action on both surfaces and
   belongs to the free check. A contact CTA that out-shouts it is the wrong thing loudest. */
.pk-quote-talk { text-decoration: none; flex: none; }
/* ⭐ THE RATE AND ITS BADGE ON ONE ROW — both describe the per-credit price, one absolutely and one
   against the entry rung. ⚠️ Right-aligned to the same edge the figure above them sits on. */
.pk-quote-meta { display: flex; align-items: center; justify-content: flex-end; gap: var(--s3);
                 margin-top: var(--s2); }
.pk-quote-rate { font-size: .8125rem; color: var(--ink-3); }
/* ⛔⛔ THE TALK STATE'S SENTENCE GOES HERE, NOT IN `.pk-quote-rate` — `FIXED 2026-09-09`.
   ⚠️ Both surfaces used to write "Over 100,000 credits — we price that one with you." into the
   RATE slot, which is a right-aligned micro-label sized for "$0.138 a credit". MEASURED at 1440px:
   it took `.pk-quote-end` from 175px to 295px, which no longer fits beside the 181px field in a
   496px `space-between` row — so the row WRAPPED and the button ended up floating mid-panel with
   the sentence stranded underneath it.
   ⭐ A full-width line under the row instead: the two-column question/answer shape survives into
   the talk state, which is the one state where the answer is a person rather than a number.
   ⚠️ It became reachable in ordinary use the same day TALK_ABOVE fell from 1,000,000 to 100,000;
   the bug predates that and nobody had typed a seven-figure number to find it. */
.pk-quote-note { margin-top: var(--s4); font-size: .8125rem; line-height: 1.5; color: var(--ink-3); }
/* ⚠️ Only present when the quote rounds up. Warm rather than red — it is a fact, not a fault. */
.pk-quote-round { display: inline-block; margin-top: var(--s2); font-size: .75rem; color: var(--warn);
                  background: var(--warn-wash); border-radius: var(--r-pill); padding: 2px 10px; }
.pk-quote-round[hidden] { display: none; }

/* ⚠️ MOBILE — THE PANEL'S ROW ONLY. ⛔ `.pk-grid`'s breakpoints are NOT here, deliberately: the
   two surfaces have different measures for it and each already owns them. The site steps 4 → 2 → 1
   at 1080 / 860 (its own section width); the app steps 3 → 2 → 1 at 820 / 460 (an 840px column).
   ⚠️ Rules here for that would be overridden on both surfaces and read as the truth on neither. */
@media (max-width: 560px) {
  .pk-quote-live { flex-direction: column; align-items: stretch; }
  .pk-quote-end { align-items: stretch; }
  .pk-quote-out { text-align: left; }
  .pk-quote-fig, .pk-quote-meta { justify-content: flex-start; }
  .pk-quote-end .btn { width: 100%; }
}
