/* THE CLAIM JOURNEY (Maaz's prototype, approved 2026-09-16).

   Source: ~/clawd/projects/bsp-proto/claim-onboarding.html — the three-step
   line, the gold YOUR BACKSTAGE card, the two-up name/email row, the niche
   grid and the plan cards, copied for layout and structure. What is ours is
   the palette and the two type voices: the proto's own `:root` block
   (#0A0A0B / #E4C07A / #F6F5EF / #E85C4A) is the door mood's tokens spelled
   by hand, so every colour here reads `var(--…)` and the page inherits
   `body.door`. No Google Fonts — `--display` and `--sans` are the self-hosted
   faces tokens.css already loads.

   EVERY CLASS IS NAMESPACED `cj-` AND EVERY SELECTOR IS SCOPED BY `.cj`.
   The proto's own names are `.card`, `.field`, `.chip`, `.status`, `.steps`,
   `.plan`, `.otp` — six live rules in application.css between them — so an
   unprefixed class here is a rule fight nobody would see coming (the
   landing page's `lp-` lesson, and `.fan-card`'s before it). The scope is
   what keeps ~300 lines of one journey's CSS off every other screen in the
   product; `claim_css_declared_test` holds both halves.

   THE LIVE-RED IS THE HOUSE'S ONE LIVE-RED. The brief names #E85C4A for the
   "Not available" state; `--live` is #e5484d and is what every refusal in
   this product already wears, and two reds one shade apart is the drift this
   house sweeps rather than ships. */

body.cj { background: var(--bg); }

.cj { padding: 0 0 80px; }

.cj-wrap { max-width: 860px; margin: 0 auto; padding: 40px 20px 0; }
.cj-wrap--wide { max-width: 1080px; }

/* ── the three steps ─────────────────────────────────────────────────────── */

.cj-steps {
  display: flex; flex-wrap: wrap; gap: 16px;
  margin: 0 0 28px; padding: 0; list-style: none;
}
.cj-step {
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--dim);
}
.cj-step--on { color: var(--accent); }

/* ── the gold card ───────────────────────────────────────────────────────── */

.cj-card {
  border: 1px solid var(--hair-48);
  background: linear-gradient(180deg, color-mix(in srgb, var(--gold) 14%, transparent), var(--surface));
  border-radius: 14px; padding: 28px; margin-bottom: 18px;
}
/* Step 1's card is centred (the prototype's own `.addr-card.center`): it
   holds one fact and nothing to line up against. Step 2's is not — its
   status pill lives hard right and its Change-handle panel is a form. */
.cj-card--center { text-align: center; }
.cj-card--center .cj-addr { justify-content: center; }
/* `field-sizing: content` IS WHAT MAKES THE PAIR CENTRED, and without it the
   row centres the BOXES while the reader sees the INK off to the left. An
   `<input>` with `width: auto` takes the UA's own intrinsic width — about 20
   characters, MEASURED 351px here — so `bsp.live/` ended at 590 and the box
   ran 592→943 with the handle's own glyphs stopping wherever they stopped:
   the ink's middle sat 145px left of the card's on Maaz's own screenshot
   while the flex row's arithmetic was perfectly correct. Sizing the box to
   its content is the whole fix (measured: ink middle 700.0 against a card
   middle of 700.0), and `flex-shrink: 1` + `min-width: 0` is what still lets
   a 30-character handle give way on a phone rather than push the document.
   Where the property is unsupported the row falls back to exactly what
   shipped, which is why it needs no second mechanism. */
.cj-card--center input.cj-addr__input {
  flex: 0 1 auto; text-align: left; field-sizing: content; min-width: 0;
}
.cj-card__top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.cj-kicker {
  font-family: var(--display); font-size: 0.75rem; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--accent); margin: 0;
}
.cj-card__said { margin: 10px 0 0; color: var(--muted); }
.cj-card__said[hidden] { display: none; }

/* The address. `--lh` is a RATIO and `--lh-snap` turns it into a whole-pixel
   length against this element's own font size (tokens.css's r8 rule); a bare
   `line-height` here would compute to a LENGTH the children inherit. */
.cj-addr {
  display: flex; align-items: baseline; gap: 2px; margin: 10px 0 0;
  font-family: var(--display); font-weight: 600;
  font-size: clamp(1.9rem, 5vw, 3rem);
  --lh: 1.06; line-height: var(--lh-snap);
}
.cj-addr--said { flex-wrap: wrap; }
/* THE HOST IS INK AND THE HANDLE IS GOLD (Maaz's QA, 2026-09-16). It was
   `--dim`, which made the one fact this card states read as two thirds
   furniture — and the prototype's own markup has no span on the host at all
   (`<div class="addr">bsp.live/<em>handle</em></div>`), so it inherits the
   card's own ink. The span stays because the display address is built out of
   two server-rendered parts on three surfaces; only the colour moved.
   `.cj-handlebox`'s own prefix is the exception below: in a FIELD the host is
   a static affordance in front of the editable half, which is the one the
   prototype does paint quiet (`.prefix { color: var(--cream-40) }`). */
.cj-addr__host { color: var(--text); }
.cj-addr em { font-style: normal; color: var(--accent); }
/* `input.` IS LOAD-BEARING, and the house says so in its own comment:
   `input[type="text"]` is (0,1,1) and a bare class is (0,1,0), so the generic
   form-control rule wins and the address draws as a 16px bordered box in the
   middle of a 48px display line. Qualifying by element ties the specificity
   and this sheet loads second (the `input.field-row` precedent, one rule
   over). The same applies to `.cj-otp__box` below, which that rule would
   otherwise stretch to `width: 100%`. */
input.cj-addr__input {
  flex: 1; min-width: 0; width: auto; background: none; border: 0; outline: none;
  padding: 0; border-radius: 0;
  font: inherit; color: var(--accent);
  --lh: 1.06; line-height: var(--lh-snap);
}
input.cj-addr__input::placeholder { color: var(--dim); }

/* Available / Not available. The refusal is a pill because it is the one
   thing on this card a reader has to notice; Available is a plain line,
   because "it worked" needs no box. */
.cj-status {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  font-size: 0.8rem; font-weight: 600;
}
.cj-status--ok { color: var(--ok); }
.cj-status--no {
  color: var(--live); padding: 4px 10px; border-radius: 999px;
  border: var(--hair-w) solid var(--hair-live);
  background: color-mix(in srgb, var(--live) 16%, transparent);
}
.cj-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }

/* ── change handle, inside the card ──────────────────────────────────────── */

/* CHANGE HANDLE SITS ON THE SENTENCE'S OWN LINE (Maaz's QA, 2026-09-16), and
   the hairline that used to divide them is gone — the prototype's line is
   `This address is yours. Change handle` with the second half an inline link,
   and a rule across the card made one fact read as two sections.

   THE DISCLOSURE GOES INLINE AND ITS BODY IS A BLOCK INSIDE IT, which is the
   one arrangement that satisfies all three constraints at once:

     · The sentence cannot live INSIDE the `<details>` — a closed one renders
       nothing but its summary, and the card is normally closed (MEASURED: the
       sentence came back a 0×0 box at 0,0 when it was in there).
     · It is still a `<details>`, because no JavaScript has to be a working
       control (the prototype's own control is a button, which would be dead).
     · The body has to span the card, and the summary has to sit beside a
       sentence — one box cannot be both narrow and full width.

   `display: inline` on the details makes the summary sit on the sentence's
   line; the body is a BLOCK inside that inline, so CSS breaks the anonymous
   inline box around it and it takes a full-width row of its own. The
   alternative — a flex row that goes `flex: 1 0 100%` on `[open]` — drops
   "Change handle" onto a second line the moment it is opened, which is a jump
   under the reader's own finger. */
.cj-said { margin: 10px 0 0; }
.cj-said__line { margin: 0; }
.cj-edit { display: inline; }
.cj-edit > summary {
  display: inline; list-style: none; cursor: pointer;
}
.cj-edit > summary::-webkit-details-marker { display: none; }
.cj-edit__body { display: block; margin-top: 14px; }
.cj-handlebox {
  display: flex; align-items: center; gap: 8px; min-height: 52px;
  padding: 0 16px; margin-top: 6px; border-radius: var(--radius);
  background: var(--input-bg); border: 1px solid var(--hair-48);
}
/* The box gives up ten of its sixteen pixels ONLY when Confirm is actually in
   it: the button carries its own 14px, and with no JavaScript (where it stays
   hidden) the field keeps exactly the box that shipped. */
.cj-handlebox:has(.cj-confirm:not([hidden])) { padding-right: 6px; }
/* THE FIELD'S PREFIX IS THE QUIET HALF, and the display address's is ink (the
   rule above). Two roles, one class: in the card the host is part of the one
   fact being stated, and in front of an editable field it is furniture —
   which is the split the prototype draws with two classes of its own. */
.cj-handlebox .cj-addr__host { color: var(--dim); }
.cj-handlebox input {
  flex: 1; min-width: 0; background: none; border: 0; outline: none;
  padding: 14px 0; font: inherit; color: var(--text);
}
/* CONFIRM LIVES IN THE BOX, ON THE RIGHT (Maaz's QA). It is drawn `hidden`
   and revealed by `claim-you`, because with no JavaScript there is nothing
   for it to do that the disclosure's own summary and the one tap below do not
   already do — and a control that cannot act is the dead button this house
   refuses. Its `[hidden]` rule is the r14 trap's (a class that hands an
   element a display has to hand the hidden state back). */
.cj-confirm {
  flex: none; padding: 8px 14px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid var(--accent); background: none; color: var(--accent);
  font: inherit; font-size: 0.8rem; font-weight: 600;
}
.cj-confirm:hover:not(:disabled) { background: color-mix(in srgb, var(--gold) 14%, transparent); }
.cj-confirm:disabled { opacity: 0.4; cursor: not-allowed; }
.cj-confirm[hidden] { display: none; }
.cj-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.cj-chip {
  padding: 8px 14px; border-radius: 999px; cursor: pointer; font: inherit;
  font-size: 0.82rem; color: var(--text); background: var(--surface-2);
  border: var(--hair-w) solid var(--border-strong);
}
.cj-chip:hover { border-color: var(--accent); color: var(--accent); }

/* ── fields ──────────────────────────────────────────────────────────────── */

.cj-form { display: flex; flex-direction: column; gap: 14px; }
/* THE YOU STEP HOLDS BLOCKS, NOT FIELDS, SO ITS OWN MARGINS OWN THE RHYTHM
   (Maaz's QA, 2026-09-16: "the page currently feels spread out"). `gap: 14px`
   is right for step 1, which is a stack of three fields; on step 2 the same
   form holds a card, a two-up row, a heading, a subtitle, a grid, a
   disclosure and the one tap — each already carrying a margin of its own, so
   every distance on the page was TWO numbers added together and neither could
   be read off the sheet. It is also what made the two tightest asks
   impossible: with the gap in play the floor under the card was 32px and
   under the heading 14px. MEASURED, before → after: card→duo 48 → 24,
   duo→heading 38+38 (with a rule between) → 28, heading→subtitle 22 → 6,
   subtitle→niches 30 → 16, More niches→Continue 42 → 24. */
.cj-form--blocks { gap: 0; }
.cj-lab { display: block; font-size: 0.8rem; font-weight: 600; color: var(--muted); }
.cj-field { display: block; }
.cj-field input {
  display: flex; width: 100%; min-height: 52px; margin-top: 6px;
  padding: 0 16px; border-radius: var(--radius); font: inherit; color: var(--text);
  background: var(--surface); border: 1px solid var(--border-strong); outline: none;
}
.cj-field input:focus, .cj-handlebox:focus-within, .cj-mini input:focus {
  border-color: var(--hair-60);
}
.cj-field input[readonly] { color: var(--muted); }

.cj-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 6px 0 0; }
.cj-mini {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; padding: 12px 16px;
}
.cj-mini input {
  width: 100%; background: none; border: 0; outline: none;
  padding: 6px 0 2px; font: inherit; font-weight: 600; color: var(--text);
}
.cj-verify {
  margin-top: 8px; padding: 7px 12px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid var(--accent); background: none; color: var(--accent);
  font: inherit; font-size: 0.75rem; font-weight: 600;
}
/* `.cj-verify` hands the element a display, so it has to hand the hidden
   state back: a class rule out-ranks the UA stylesheet's own `[hidden]`
   (the r14 trap, and this house has paid for it six times). */
.cj-verify[hidden] { display: none; }

/* ── the browser's own fill ───────────────────────────────────────────────── */

/* CHROME'S AUTOFILL IS NOT OURS TO STYLE, ONLY TO PAINT OVER (Maaz's QA,
   2026-09-16: a saved username dropdown, and picking it painted the field a
   blue-grey block). Four properties, and each is doing a different job:

     · `-webkit-box-shadow: 0 0 0 1000px <bg> inset` is the only way to cover
       the UA's own autofill background — it is not an author `background`, so
       `background: <ours>` does not reach it. The colour has to be the field's
       OWN ground, which is why this is one declaration per field shape rather
       than one rule for all of them.
     · `-webkit-text-fill-color` because in the autofill state that out-ranks
       `color`, and without it the handle draws in Chrome's own ink.
     · `caret-color`, which the fill state otherwise takes with it.
     · `transition: background-color 9999s` — the fill is applied through a
       transition, so a transition long enough never arrives. It is the belt
       to the box-shadow's braces: on a plane where the shadow is refused
       (a UA with no `-webkit-` prefix) this alone keeps the field its own
       colour.

   `:hover`, `:focus` and `:active` are named because Chrome re-applies the
   fill background on each of them. THE AUTOFILL STATE CANNOT BE PROVOKED FROM
   A TEST — it needs Chrome's own dropdown and a real gesture — so this is
   asserted at the stylesheet level (`claim_css_declared_test`) and nowhere
   else, which is stated rather than hidden. */
input.cj-addr__input:-webkit-autofill,
input.cj-addr__input:-webkit-autofill:hover,
input.cj-addr__input:-webkit-autofill:focus,
input.cj-addr__input:-webkit-autofill:active {
  /* NO 1000px INSET HERE, AND THAT IS THE ONE DELIBERATE OMISSION: this input
     sits on the gold card's own gradient, so an opaque flat inset is a
     rectangle painted across it (measured — a `--surface` box reads against
     the gradient at the address's height). The three properties that do not
     invent a colour are what it gets. */
  -webkit-text-fill-color: var(--accent);
  caret-color: var(--accent);
  transition: background-color 9999s ease-in-out 0s;
}
.cj-field input:-webkit-autofill,
.cj-field input:-webkit-autofill:hover,
.cj-field input:-webkit-autofill:focus,
.cj-field input:-webkit-autofill:active {
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
  transition: background-color 9999s ease-in-out 0s;
}
.cj-handlebox input:-webkit-autofill,
.cj-handlebox input:-webkit-autofill:hover,
.cj-handlebox input:-webkit-autofill:focus,
.cj-handlebox input:-webkit-autofill:active {
  -webkit-box-shadow: 0 0 0 1000px var(--input-bg) inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
  transition: background-color 9999s ease-in-out 0s;
}
/* The duo's Name and Email are the same two fields step 1 asks for, one step
   on, and they are where a browser fills most eagerly (`autocomplete="name"`
   and `"email"` are what it reads). The brief names `.cj-field input`; this
   pair is that control on the other step, and leaving it out would ship the
   bug on the page the screenshots are of. */
.cj-mini input:-webkit-autofill,
.cj-mini input:-webkit-autofill:hover,
.cj-mini input:-webkit-autofill:focus,
.cj-mini input:-webkit-autofill:active {
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
  transition: background-color 9999s ease-in-out 0s;
}

/* AND THE SELECTION IS CREAM ON INK, NEVER THE SYSTEM BLUE (Maaz's QA). A
   browser that fills a field also SELECTS what it filled, which is the
   blue-grey block in the screenshot — and it is the OS colour, so it arrives
   on every one of these fields whether the fill did or not. Inverse video in
   the house's own two colours: the block is cream and the words go to ink,
   which is the same shape `design/gilt.css` already states for its own
   canvas. Declared per input rather than on `.cj` because a page-wide
   `::selection` would repaint every sentence on the journey. */
input.cj-addr__input::selection,
.cj-field input::selection,
.cj-handlebox input::selection,
.cj-mini input::selection,
input.cj-otp__box::selection {
  background: var(--text); color: var(--bg);
}

.cj-err {
  margin: 0 0 14px; padding: 12px 14px; border-radius: var(--radius);
  color: var(--live); font-size: 0.85rem;
  border: 1px solid var(--hair-live);
  background: color-mix(in srgb, var(--live) 12%, transparent);
}


/* ── the code ────────────────────────────────────────────────────────────── */

.cj-otp { margin-top: 4px; }
.cj-otp__row { display: flex; justify-content: center; gap: 8px; margin: 12px 0 8px; }
/* The mini row sits inside a half-width cell and is left-aligned with the
   label above it; centring six 34px boxes there would float them off the
   field they belong to. */
.cj-otp--mini .cj-otp__row { justify-content: flex-start; gap: 5px; }
input.cj-otp__box {
  flex: none; width: 46px; height: 52px; padding: 0; text-align: center; font: inherit;
  font-size: 1.25rem; font-weight: 600; color: var(--text);
  border-radius: var(--radius); border: 1px solid var(--border-strong);
  background: var(--surface); outline: none;
}
.cj-otp--mini input.cj-otp__box { width: 34px; height: 40px; font-size: 1rem; }
input.cj-otp__box:focus { border-color: var(--accent); }
.cj-resend {
  display: block; margin-top: 12px; padding: 0; cursor: pointer;
  background: none; border: 0; color: var(--muted); font: inherit; font-size: 0.85rem;
}
.cj-resend:disabled { color: var(--dim); cursor: default; }
.cj-challenge { min-height: 65px; }
/* The two POSTs the code's controls belong to. Hidden changes nothing about a
   form-associated control — an input that names its owner submits whatever
   that owner's display is. */
.cj-hidden-form { display: none; }

/* ── niches ──────────────────────────────────────────────────────────────── */

/* `h1, h2` is uppercase in this house and the prototype's headings are
   sentence case — the display face is already the marquee voice, and SHOUTING
   a question is not how it asks one. Local, like every other override of a
   house rule on one screen. */
.cj-niche-title {
  font-family: var(--display); font-size: 2rem; font-weight: 600; margin: 28px 0 0;
  text-transform: none; letter-spacing: 0;
}
/* The subtitle is the heading's own second line, so it is spaced off the
   HEADING and not off `.cj-hint`, which has five other hosts on this journey
   (step 1's two, the OTP's, the taken-name line, the plan page's centred
   one). The prototype's own figure is 6px. */
.cj-niche-title + .cj-hint { margin-top: 6px; }
.cj-niches {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px; margin-top: 16px;
}
.cj-niches--more { margin-top: 12px; }
/* `position: relative` is load-bearing: the radio inside is `.sr-only`, which
   is `position: absolute`, and in a static row its containing block is the
   page — one hidden input laid out against the document is what made a
   1,512px viewport report 1,816px of it (the FOLLOWERS r2 defect). */
.cj-niche {
  position: relative; display: flex; align-items: center; gap: 10px;
  padding: 16px 14px; border-radius: 12px; cursor: pointer;
  font-size: 0.85rem; font-weight: 600; text-align: left;
  background: var(--surface); border: 1px solid var(--border);
}
.cj-niche__radio {
  flex: none; width: 14px; height: 14px; border-radius: 50%;
  border: 1.5px solid var(--dim);
}
/* The lit state is the radio's own, read in CSS — never a class a controller
   has to add, so the pick shows with no JavaScript at all. */
/* `min-width: 0` so a two-word category wraps inside its own tile rather
   than pushing the four-column grid sideways — a flex item's floor is its
   content, and "Personal Development" is the longest thing in the list. */
.cj-niche__word { min-width: 0; overflow-wrap: anywhere; }
.cj-niche:has(input:checked) { border-color: var(--accent); background: color-mix(in srgb, var(--gold) 12%, transparent); }
.cj-niche:has(input:checked) .cj-niche__radio {
  border-color: var(--accent); background: var(--accent);
  box-shadow: inset 0 0 0 3px var(--bg);
}
.cj-niche:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.cj-moreniches { margin-top: 14px; }
.cj-moreniches > summary { list-style: none; cursor: pointer; width: max-content; }
.cj-moreniches > summary::-webkit-details-marker { display: none; }

/* ── the one tap ─────────────────────────────────────────────────────────── */

.cj-primary {
  width: 100%; min-height: 52px; padding: 0 24px; cursor: pointer;
  border: 0; border-radius: var(--radius); font: inherit; font-weight: 600;
  background: var(--btn-bg); color: var(--btn-fg);
}
.cj-primary:hover { background: var(--btn-hover); }
.cj-primary:disabled { opacity: 0.4; cursor: not-allowed; }
.cj-primary--compact { width: auto; min-height: 38px; font-size: 0.82rem; }
.cj-cta { margin-top: 24px; }
.cj-hint { margin-top: 8px; font-size: 0.82rem; color: var(--dim); }
.cj-link { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
.cj-link:hover { color: var(--accent); }
.cj-back { margin-top: 26px; font-size: 0.85rem; }

/* ── the plans ───────────────────────────────────────────────────────────── */

.cj-title {
  font-family: var(--display); font-size: 2.5rem; margin: 10px 0 8px;
  text-transform: none; letter-spacing: 0;
  --lh: 1.06; line-height: var(--lh-snap);
}
.cj-gold { color: var(--accent); }
.cj-sub { color: var(--muted); margin-bottom: 28px; }
.cj-plans { display: grid; gap: 16px; }
.cj-plan {
  display: flex; flex-direction: column;
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 12px; padding: 24px;
}
.cj-plan--feat { background: var(--gold); color: var(--gold-ink); border-color: var(--gold); }
.cj-plan__head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cj-plan__name {
  font-family: var(--display); font-size: 0.75rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--accent);
}
.cj-plan--feat .cj-plan__name { color: color-mix(in srgb, var(--gold-ink) 60%, transparent); }
.cj-plan__badge {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--gold-ink) 14%, transparent);
}
.cj-plan__price { font-family: var(--display); font-size: 2.5rem; font-weight: 500; margin: 16px 0 18px; }
.cj-plan__per { font-size: 1rem; }
/* The trial line under the price (FHL launch): a quiet fact, not a second
   price. It takes back some of the price's own bottom margin so the pair
   reads as one block. */
.cj-plan__trial { margin: -10px 0 18px; font-size: 0.9rem; color: var(--muted); }
.cj-plan__features { list-style: none; margin: 0 0 18px; padding: 0; font-size: 0.82rem; color: var(--muted); }
.cj-plan--feat .cj-plan__features { color: color-mix(in srgb, var(--gold-ink) 78%, transparent); }
.cj-plan__features li { margin-bottom: 8px; }
.cj-plan__form { margin-top: auto; }
/* `margin-top: auto` on the LAST thing in the card, so three cards of three
   different feature counts still land their taps on one line. */
.cj-plan > .cj-plan__cta { margin-top: auto; }
.cj-plan__cta {
  display: block; width: 100%; padding: 12px; cursor: pointer; text-align: center;
  border: 0; border-radius: var(--radius); font: inherit; font-weight: 600;
  background: var(--btn-bg); color: var(--btn-fg);
}
.cj-plan--feat .cj-plan__cta { background: var(--gold-ink); color: var(--gold); }

@media (min-width: 900px) {
  .cj-plans { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 800px) {
  .cj-niches { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cj-duo { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 420px) {
  .cj-otp__row { gap: 5px; }
  /* Six boxes and five gaps in whatever is left: a fixed 46px overflows a
     390px column once the card's padding is off it. */
  input.cj-otp__box { flex: 1 1 0; width: auto; min-width: 0; }
}
