/* ===========================================================================
   Checkout — the one visual system for every "pay us" surface in the app.
   ===========================================================================

   Loaded globally from base_app.html rather than a page's {% block css_page %},
   because the shared method picker (templates/payments/_method_picker.html) is
   included from six different apps' templates — subscriptions checkout, the
   Business Pack detail page, SolarSizer project detail, the SME roadmap
   unlock — and a picker that is only styled on one of them is worse than one
   that is styled on none.

   Everything here is a class, and the checkout templates carry no inline
   style attributes and no embedded stylesheet element — both are ratcheted by
   tests/architecture/test_csp_readiness.py and are what keeps
   CSP_ENFORCE_STRICT off.

   Every colour is a token from static/css/tokens.css; there is no raw hex in
   this file, which scripts/lint_tokens.py enforces on changed lines. The
   local `--iai-co-*` names below are semantic aliases over that palette
   (ink / line / surface / accent / go), so a themed variant means overriding
   a dozen names rather than auditing four hundred declarations.

   The method picker needs NO JavaScript. Selection is a native radio group;
   the selected method's panel and its pay button are revealed by `:has()`
   rules on `.iai-pm-scope`. That matters for more than elegance — a checkout
   that depends on JS to show its pay button is a checkout that is dead
   whenever the bundle fails.
   -------------------------------------------------------------------------*/

/* Tokens are declared on BOTH wrappers, and that is not belt-and-braces.
   `.iai-checkout` wraps the subscriptions checkout page; `.iai-pm-scope`
   wraps one method picker anywhere else — the Business Pack page, SolarSizer's
   paywall, the SME roadmap unlock. Declared only on `.iai-checkout`, every
   `var()` below resolved to nothing on those five pages: the pay button's
   `background: var(--iai-co-go)` became invalid and it rendered as bare blue
   link text rather than a green button. Anything styled here must therefore
   live inside one of these two, and any new wrapper class has to be added
   to this selector. */
.iai-checkout,
.iai-pm-scope,
/* The theme toggle is placed outside both wrappers (page headers, toolbars),
   so it declares the tokens too — otherwise every var() below resolves to
   nothing and it renders as bare text rather than a button. */
.iai-theme-toggle {
  --iai-co-ink:        var(--slate-900);
  --iai-co-ink-soft:   var(--slate-500);
  --iai-co-ink-faint:  var(--slate-400);
  --iai-co-line:       var(--slate-200);
  --iai-co-line-soft:  var(--slate-150);
  --iai-co-surface:    var(--white);
  --iai-co-canvas:     var(--slate-50);
  --iai-co-accent:     var(--blue-600);
  --iai-co-accent-dim: var(--blue-50);
  --iai-co-go:         var(--green-600);
  --iai-co-go-dark:    var(--green-700);
  --iai-co-radius:     14px;
  --iai-co-shadow:     0 1px 2px rgba(15, 23, 42, .04), 0 8px 24px rgba(15, 23, 42, .05);
}

/* ── Page head ─────────────────────────────────────────────────────────── */

.iai-co-backlink {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-size: .82rem;
  color: var(--iai-co-ink-soft);
  text-decoration: none;
}
.iai-co-backlink:hover { color: var(--iai-co-accent); }

.iai-co-title {
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--iai-co-ink);
  margin: 0 0 .35rem;
}
.iai-co-lede {
  font-size: .9rem;
  color: var(--iai-co-ink-soft);
  margin: 0;
  max-width: 46ch;
}

/* ── Cards ─────────────────────────────────────────────────────────────── */

.iai-co-card {
  background: var(--iai-co-surface);
  border: 1px solid var(--iai-co-line);
  border-radius: var(--iai-co-radius);
  box-shadow: var(--iai-co-shadow);
}
.iai-co-card-body { padding: 1.5rem; }

.iai-co-legend {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--iai-co-ink-faint);
  margin: 0 0 .9rem;
}

/* ── Method picker ─────────────────────────────────────────────────────── */

/* Kept in the accessibility tree — visually-hidden, never display:none — so
   the group stays reachable and announced by a screen reader. The tiles are
   its visible face; see the `:has()` rules below for how the two are paired,
   and .iai-pm-tile's own focus rule for keyboard visibility. */
.iai-pm-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* One method per row, not a side-by-side grid.
   Three or four methods across a 560px column leaves each tile ~170px, which
   has to hold a radio dot, a name, the provider sub-line ("Visa & Mastercard,
   via Pesapal") and two card marks — every one of them wrapped onto three
   lines. A full-width row fits all of it on one line at any method count, and
   scanning a vertical list of payment options is the pattern customers
   already know from every other checkout. */
.iai-pm-tiles {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  margin-bottom: 1.1rem;
}

.iai-pm-tile {
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: .85rem .9rem;
  border: 1.5px solid var(--iai-co-line);
  border-radius: 11px;
  background: var(--iai-co-surface);
  cursor: pointer;
  margin: 0;
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.iai-pm-tile:hover { border-color: var(--slate-300); background: var(--iai-co-canvas); }

/* The radio's own dot, drawn on the label so the whole tile is the target. */
.iai-pm-dot {
  width: 17px;
  height: 17px;
  min-width: 17px;
  border-radius: 50%;
  border: 2px solid var(--slate-300);
  position: relative;
  transition: border-color .15s ease;
}
.iai-pm-dot::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--iai-co-accent);
  transform: scale(0);
  transition: transform .15s ease;
}

.iai-pm-label {
  display: flex;
  flex-direction: column;
  gap: .1rem;
  min-width: 0;
  flex: 1;
}
.iai-pm-name {
  font-size: .86rem;
  font-weight: 600;
  color: var(--iai-co-ink);
  line-height: 1.25;
}
.iai-pm-sub {
  font-size: .72rem;
  color: var(--iai-co-ink-faint);
  line-height: 1.3;
}

/* Pushed right by the label's `flex: 1`, so the amount and the brand marks
   form a consistent right-hand edge down the tile list. */
.iai-pm-amount {
  margin-left: auto;
  font-size: .86rem;
  font-weight: 700;
  color: var(--iai-co-ink);
  white-space: nowrap;
  flex-shrink: 0;
}

.iai-pm-mark {
  display: flex;
  align-items: center;
  gap: .25rem;
  flex-shrink: 0;
}

/* ── Selected state (pure CSS, keyed off the native radio) ─────────────── */

/* Matched through `:has()` on the scope, NOT `:checked + label`. The picker
   emits all of its radios together before the tile list, so a label is never
   its own radio's adjacent sibling and `+` matches nothing — which left the
   selected tile looking identical to the unselected ones while its panel was
   open below. */
.iai-pm-scope:has(.iai-pm-input[data-method="mpesa"]:checked)  .iai-pm-tile[data-method="mpesa"],
.iai-pm-scope:has(.iai-pm-input[data-method="card"]:checked)   .iai-pm-tile[data-method="card"],
.iai-pm-scope:has(.iai-pm-input[data-method="paypal"]:checked) .iai-pm-tile[data-method="paypal"] {
  border-color: var(--iai-co-accent);
  background: var(--iai-co-accent-dim);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .12);
}
.iai-pm-scope:has(.iai-pm-input[data-method="mpesa"]:checked)  .iai-pm-tile[data-method="mpesa"]  .iai-pm-dot,
.iai-pm-scope:has(.iai-pm-input[data-method="card"]:checked)   .iai-pm-tile[data-method="card"]   .iai-pm-dot,
.iai-pm-scope:has(.iai-pm-input[data-method="paypal"]:checked) .iai-pm-tile[data-method="paypal"] .iai-pm-dot {
  border-color: var(--iai-co-accent);
}
.iai-pm-scope:has(.iai-pm-input[data-method="mpesa"]:checked)  .iai-pm-tile[data-method="mpesa"]  .iai-pm-dot::after,
.iai-pm-scope:has(.iai-pm-input[data-method="card"]:checked)   .iai-pm-tile[data-method="card"]   .iai-pm-dot::after,
.iai-pm-scope:has(.iai-pm-input[data-method="paypal"]:checked) .iai-pm-tile[data-method="paypal"] .iai-pm-dot::after {
  transform: scale(1);
}

/* Keyboard focus has to be visible on the LABEL, since the input itself is
   visually hidden — without this the group is unusable by keyboard. */
.iai-pm-scope:has(.iai-pm-input[data-method="mpesa"]:focus-visible)  .iai-pm-tile[data-method="mpesa"],
.iai-pm-scope:has(.iai-pm-input[data-method="card"]:focus-visible)   .iai-pm-tile[data-method="card"],
.iai-pm-scope:has(.iai-pm-input[data-method="paypal"]:focus-visible) .iai-pm-tile[data-method="paypal"] {
  outline: 2px solid var(--iai-co-accent);
  outline-offset: 2px;
}

/* Panels and pay buttons: only the selected method's are shown.
   ------------------------------------------------------------------------
   `:has()` rather than a sibling combinator, because on the subscription
   checkout the radios live in the left column and their pay buttons in the
   right-hand summary — they are not siblings and cannot be made siblings
   without wrapping the two-column grid in a form. `.iai-pm-scope` is the
   nearest ancestor that owns one radio group, so two pickers on one page
   (SolarSizer's project detail renders both a report and a subscribe picker)
   do not drive each other.

   DEGRADATION MATTERS HERE — this is a payments page. Both the hide and the
   show rules are written under `:has()`, so a browser that does not support
   it drops BOTH and every method's panel and button render at once: stacked
   and unpolished, but every rail still reachable and chargeable. Never move
   the `display: none` out from under `:has()` — that inverts the failure
   into a checkout with no visible way to pay. */
.iai-pm-scope:has(.iai-pm-input:checked) .iai-pm-panel,
.iai-pm-scope:has(.iai-pm-input:checked) .iai-pm-submit { display: none; }

.iai-pm-scope:has(.iai-pm-input[data-method="mpesa"]:checked)  .iai-pm-panel[data-method="mpesa"],
.iai-pm-scope:has(.iai-pm-input[data-method="card"]:checked)   .iai-pm-panel[data-method="card"],
.iai-pm-scope:has(.iai-pm-input[data-method="paypal"]:checked) .iai-pm-panel[data-method="paypal"] {
  display: block;
}
.iai-pm-scope:has(.iai-pm-input[data-method="mpesa"]:checked)  .iai-pm-submit[data-method="mpesa"],
.iai-pm-scope:has(.iai-pm-input[data-method="card"]:checked)   .iai-pm-submit[data-method="card"],
.iai-pm-scope:has(.iai-pm-input[data-method="paypal"]:checked) .iai-pm-submit[data-method="paypal"] {
  display: flex;
}

/* Fallback spacing for the no-`:has()` case above, where panels stack. */
.iai-pm-panel + .iai-pm-panel { margin-top: .6rem; }

/* ── Method panel ──────────────────────────────────────────────────────── */

.iai-pm-panel {
  border: 1px solid var(--iai-co-line-soft);
  border-radius: 11px;
  background: var(--iai-co-canvas);
  padding: 1.1rem;
}

.iai-pm-field-label {
  display: block;
  font-size: .8rem;
  font-weight: 600;
  color: var(--iai-co-ink);
  margin-bottom: .4rem;
}
.iai-pm-input-group {
  display: flex;
  align-items: stretch;
  border: 1.5px solid var(--slate-300);
  border-radius: 9px;
  background: var(--iai-co-surface);
  overflow: hidden;
}
.iai-pm-input-group:focus-within {
  border-color: var(--iai-co-accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .12);
}
.iai-pm-input-addon {
  display: flex;
  align-items: center;
  padding: 0 .75rem;
  background: var(--iai-co-canvas);
  border-right: 1px solid var(--iai-co-line);
  color: var(--iai-co-ink-soft);
  font-size: .85rem;
}
.iai-pm-text-input {
  flex: 1;
  min-width: 0;
  border: 0;
  padding: .6rem .75rem;
  font-size: .9rem;
  color: var(--iai-co-ink);
  background: transparent;
}
.iai-pm-text-input:focus { outline: none; }

.iai-pm-help {
  font-size: .76rem;
  color: var(--iai-co-ink-soft);
  margin: .55rem 0 0;
  line-height: 1.5;
}

.iai-pm-handoff {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  font-size: .8rem;
  color: var(--iai-co-ink-soft);
  line-height: 1.55;
  margin: 0;
}
.iai-pm-handoff i { color: var(--iai-co-go); margin-top: .15rem; }

/* ── Pay button ────────────────────────────────────────────────────────── */

.iai-pm-submit {
  /* Flex in the base rule, not only in the `:has()` show rule above, so the
     no-`:has()` fallback renders every button correctly rather than as an
     inline anchor. */
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .8rem 1.1rem;
  border: 0;
  border-radius: 10px;
  background: var(--iai-co-go);
  color: var(--white);
  font-size: .95rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background .15s ease, box-shadow .15s ease, transform .1s ease;
}
/* Element + scope qualified, and only for the properties a host page is
   likely to fight over. This component is embedded in five differently
   themed pages; SolarSizer's paywall styles its own `a` at (0,2,0), which
   beat the plain `.iai-pm-submit` above and rendered "Subscribe & download"
   as blue text on the green button. (0,2,1) here settles it deterministically
   without reaching for !important — the M-Pesa rail was unaffected because
   its control is a <button>, so the bug only showed on the hosted-redirect
   rails and only on that one page. */
.iai-pm-scope a.iai-pm-submit,
.iai-pm-scope button.iai-pm-submit {
  color: var(--white);
  background: var(--iai-co-go);
  text-decoration: none;
}
.iai-pm-scope a.iai-pm-submit:hover,
.iai-pm-scope button.iai-pm-submit:hover,
.iai-pm-submit:hover {
  background: var(--iai-co-go-dark);
  color: var(--white);
  text-decoration: none;
  box-shadow: 0 6px 18px rgba(22, 163, 74, .3);
}
.iai-pm-submit:active { transform: translateY(1px); }
.iai-pm-submit:focus-visible { outline: 2px solid var(--iai-co-go-dark); outline-offset: 2px; }

/* Locked pay button: shown to visitors who cannot pay, so the primary
   action is still visible and says why it is unavailable. */
.iai-pm-scope button.iai-pm-submit--locked,
.iai-pm-submit--locked {
  background: var(--iai-co-line);
  color: var(--iai-co-ink-soft);
  cursor: not-allowed;
  box-shadow: none;
}
.iai-pm-scope button.iai-pm-submit--locked:hover { background: var(--iai-co-line); color: var(--iai-co-ink-soft); box-shadow: none; }
.iai-co-paynote {
  display: flex;
  align-items: flex-start;
  gap: .4rem;
  margin: .55rem 0 0;
  font-size: .75rem;
  color: var(--iai-co-ink-faint);
  line-height: 1.45;
}

/* ── Checkout progress ─────────────────────────────────────────────────── */
.iai-co-steps {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem 1.4rem;
  margin: 0 0 1.1rem;
  padding: 0;
  list-style: none;
  font-size: .8rem;
  font-weight: 600;
  color: var(--iai-co-ink-faint);
}
.iai-co-steps li { display: flex; align-items: center; gap: .45rem; }
.iai-co-steps li + li::before {
  content: "";
  width: 1.6rem;
  height: 1px;
  margin-right: .6rem;
  background: var(--iai-co-line);
}
.iai-co-steps span {
  display: grid;
  place-items: center;
  width: 1.45rem;
  height: 1.45rem;
  border: 1.5px solid var(--iai-co-line);
  border-radius: 50%;
  font-size: .72rem;
}
.iai-co-steps .is-done { color: var(--iai-co-go); }
.iai-co-steps .is-done span { border-color: var(--iai-co-go); background: var(--iai-co-go); color: var(--white); }
.iai-co-steps .is-current { color: var(--iai-co-ink); }
.iai-co-steps .is-current span { border-color: var(--iai-co-accent); color: var(--iai-co-accent); }

/* ── Can't-pay state (subscriptions/_purchase_blocked.html) ───────────── */
.iai-co-blocked {
  display: flex;
  gap: .9rem;
  padding: 1rem 1.1rem;
  border: 1px solid var(--iai-co-line);
  border-radius: 12px;
  background: var(--iai-co-canvas);
}
.iai-co-blocked-icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 10px;
  background: var(--iai-co-accent-dim);
  color: var(--iai-co-accent);
  font-size: 1.15rem;
}
.iai-co-blocked-title { margin: 0 0 .25rem; font-weight: 700; color: var(--iai-co-ink); }
.iai-co-blocked-text { margin: 0 0 .8rem; font-size: .88rem; color: var(--iai-co-ink-soft); line-height: 1.5; }
.iai-co-blocked-actions { display: flex; flex-wrap: wrap; gap: .5rem; }
.iai-co-btn {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem .9rem;
  border: 1px solid var(--iai-co-line);
  border-radius: 8px;
  background: var(--iai-co-surface);
  color: var(--iai-co-ink);
  font-size: .82rem;
  font-weight: 600;
  text-decoration: none;
}
.iai-co-btn:hover { border-color: var(--iai-co-accent); color: var(--iai-co-accent); }
.iai-co-btn--primary { border-color: var(--iai-co-accent); background: var(--iai-co-accent); color: var(--white); }
.iai-co-btn--primary:hover { color: var(--white); filter: brightness(1.08); }
.iai-co-blocked-methods {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4rem;
  margin: .8rem 0 0;
  font-size: .78rem;
  color: var(--iai-co-ink-faint);
}
.iai-co-methodchip {
  padding: .15rem .55rem;
  border: 1px solid var(--iai-co-line);
  border-radius: 999px;
  color: var(--iai-co-ink-soft);
  font-weight: 600;
}

/* Inline variant — used where the picker stands alone (Business Packs,
   SolarSizer, the SME roadmap unlock) and there is no summary column to put
   the button in. */
.iai-pm-submit--inline { margin-top: .9rem; }

/* ── Checkout grid ─────────────────────────────────────────────────────── */

/* Below lg this is plain block flow, so the DOM order is the reading order:
   methods → summary → billing detail. That order is deliberate — see the
   comment in subscriptions/upgrade.html on why the pay button must not
   precede the M-Pesa phone field.

   From lg up it becomes a named grid rather than a Bootstrap row, because a
   row cannot do what this layout needs: the summary has to span BOTH rows on
   the right while the billing detail sits directly under the methods. With
   three plain columns the third wraps below the TALLER of the first two,
   leaving a ~200px hole under the method picker. `grid-template-areas` places
   all three exactly and needs no ordering classes. */
.iai-co-grid {
  display: grid;
  gap: 1rem;
}

@media (min-width: 992px) {
  .iai-co-grid {
    grid-template-columns: 7fr 5fr;
    grid-template-areas:
      "methods summary"
      "details summary";
    align-items: start;
  }
  .iai-co-grid-methods { grid-area: methods; }
  .iai-co-grid-summary { grid-area: summary; }
  .iai-co-grid-details { grid-area: details; }
}

/* ── Billing-country control ───────────────────────────────────────────── */

/* A <details>, collapsed by default — a correction, not a step. Most customers
   see the right methods already and must not be made to answer a question to
   reach the pay button. */
.iai-co-country { margin-top: .9rem; }

.iai-co-country > summary {
  font-size: .78rem;
  color: var(--iai-co-ink-soft);
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .2rem 0;
}
.iai-co-country > summary::-webkit-details-marker { display: none; }
.iai-co-country > summary::before {
  content: "\F282";               /* bi-plus, matching the app's icon font */
  font-family: "bootstrap-icons";
  font-size: .8rem;
  line-height: 1;
}
.iai-co-country[open] > summary::before { content: "\F2EA"; }   /* bi-dash */
.iai-co-country > summary:hover { color: var(--iai-co-accent); }
.iai-co-country > summary:focus-visible {
  outline: 2px solid var(--iai-co-accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.iai-co-country-form {
  margin-top: .7rem;
  padding: .9rem;
  border: 1px solid var(--iai-co-line-soft);
  border-radius: 10px;
  background: var(--iai-co-canvas);
}

.iai-co-country-select {
  width: 100%;
  padding: .55rem .7rem;
  border: 1.5px solid var(--slate-300);
  border-radius: 9px;
  background: var(--iai-co-surface);
  color: var(--iai-co-ink);
  font-size: .9rem;
}
.iai-co-country-select:focus {
  outline: none;
  border-color: var(--iai-co-accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .12);
}

.iai-co-country-btn {
  margin-top: .6rem;
  width: 100%;
  padding: .55rem .9rem;
  border: 1.5px solid var(--iai-co-line);
  border-radius: 9px;
  background: var(--iai-co-surface);
  color: var(--iai-co-ink);
  font-size: .82rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.iai-co-country-btn:hover {
  border-color: var(--iai-co-accent);
  color: var(--iai-co-accent);
}
.iai-co-country-btn:focus-visible {
  outline: 2px solid var(--iai-co-accent);
  outline-offset: 2px;
}

/* ── Order summary ─────────────────────────────────────────────────────── */

.iai-co-summary { position: sticky; top: 1.25rem; }

.iai-co-plan {
  background: var(--iai-co-canvas);
  border: 1px solid var(--iai-co-line-soft);
  border-radius: 11px;
  padding: 1rem 1.1rem;
  margin-bottom: 1.1rem;
}
.iai-co-plan-name {
  font-size: .95rem;
  font-weight: 700;
  color: var(--iai-co-ink);
  margin: 0 0 .15rem;
}
.iai-co-plan-blurb {
  font-size: .78rem;
  color: var(--iai-co-ink-soft);
  margin: 0 0 .7rem;
  line-height: 1.5;
}
.iai-co-plan-price {
  display: flex;
  align-items: baseline;
  gap: .3rem;
  margin-bottom: .85rem;
}
.iai-co-plan-price b {
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: -.03em;
  color: var(--iai-co-ink);
  line-height: 1;
}
.iai-co-plan-price span { font-size: .82rem; color: var(--iai-co-ink-faint); }

.iai-co-changeplan {
  display: block;
  text-align: center;
  padding: .5rem;
  border-radius: 8px;
  background: rgba(37, 99, 235, .08);
  color: var(--iai-co-accent);
  font-size: .8rem;
  font-weight: 600;
  text-decoration: none;
}
.iai-co-changeplan:hover { background: rgba(37, 99, 235, .15); color: var(--iai-co-accent); }

/* ── Plan switcher (order summary) ─────────────────────────────────────
   The other plans as tiles that reload the checkout, replacing the old
   "Change plan" link that left the page for the plans list. */
.iai-co-sublegend {
  margin: 0 0 .45rem;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--iai-co-ink-faint);
}
.iai-co-planpick {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  grid-auto-flow: column;
  gap: .4rem;
  margin-bottom: 1.1rem;
}
.iai-co-planpick-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: .15rem;
  padding: .6rem .7rem;
  border: 1.5px solid var(--iai-co-line);
  border-radius: 10px;
  background: var(--iai-co-surface);
  color: var(--iai-co-ink);
  text-decoration: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.iai-co-planpick-tile:hover { border-color: var(--iai-co-accent); color: var(--iai-co-ink); }
.iai-co-planpick-tile.is-active {
  border-color: var(--iai-co-accent);
  background: var(--iai-co-accent-dim);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .12);
}
.iai-co-planpick-name { font-size: .8rem; font-weight: 700; }
.iai-co-planpick-price { font-size: .85rem; font-weight: 700; color: var(--iai-co-ink-soft); }
.iai-co-planpick-price small { font-weight: 500; color: var(--iai-co-ink-faint); }
.iai-co-planpick-tile i { position: absolute; top: .45rem; right: .5rem; color: var(--iai-co-accent); font-size: .85rem; }

/* Billing-period toggle. Two links, not a form — each is a real URL
   (?period=monthly / ?period=yearly) so the choice survives a reload and can
   be shared, and so it needs no JS. */
.iai-co-period {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .3rem;
  padding: .25rem;
  background: var(--iai-co-canvas);
  border: 1px solid var(--iai-co-line-soft);
  border-radius: 10px;
  margin-bottom: 1.1rem;
}
.iai-co-period a {
  text-align: center;
  padding: .45rem .3rem;
  border-radius: 7px;
  font-size: .78rem;
  font-weight: 600;
  color: var(--iai-co-ink-soft);
  text-decoration: none;
}
.iai-co-period a:hover { color: var(--iai-co-ink); }
.iai-co-period a.is-active {
  background: var(--iai-co-surface);
  color: var(--iai-co-ink);
  box-shadow: 0 1px 3px rgba(15, 23, 42, .1);
}
.iai-co-period-save {
  display: block;
  font-size: .65rem;
  font-weight: 600;
  color: var(--iai-co-go);
  letter-spacing: .02em;
}

.iai-co-lines { margin-bottom: 1rem; }
.iai-co-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  font-size: .84rem;
  color: var(--iai-co-ink-soft);
  padding: .4rem 0;
}
.iai-co-line b { color: var(--iai-co-ink); font-weight: 600; }
.iai-co-line--credit { color: var(--iai-co-go); }
.iai-co-line--credit b { color: var(--iai-co-go); }
.iai-co-line--note {
  font-size: .74rem;
  color: var(--iai-co-ink-faint);
  display: block;
  padding-top: 0;
  line-height: 1.5;
}
.iai-co-line--total {
  border-top: 1px solid var(--iai-co-line);
  margin-top: .35rem;
  padding-top: .8rem;
  font-size: .95rem;
  color: var(--iai-co-ink);
  font-weight: 600;
}
.iai-co-line--total b { font-size: 1.35rem; font-weight: 800; letter-spacing: -.02em; }

.iai-co-finalnote {
  font-size: .72rem;
  color: var(--iai-co-ink-faint);
  line-height: 1.6;
  margin: .9rem 0 0;
  text-align: center;
}
.iai-co-finalnote a { color: var(--iai-co-ink-soft); }

/* ── Trust list ────────────────────────────────────────────────────────── */

.iai-co-trust { list-style: none; padding: 0; margin: 0; }
.iai-co-trust li {
  display: flex;
  align-items: flex-start;
  gap: .55rem;
  font-size: .8rem;
  color: var(--iai-co-ink-soft);
  line-height: 1.55;
  padding: .3rem 0;
}
.iai-co-trust i { color: var(--iai-co-go); margin-top: .15rem; flex-shrink: 0; }

/* ── Billed-to block ───────────────────────────────────────────────────── */

.iai-co-billedto {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
}
.iai-co-billedto div { min-width: 0; }
.iai-co-billedto dt {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--iai-co-ink-faint);
  margin-bottom: .2rem;
}
.iai-co-billedto dd {
  font-size: .85rem;
  color: var(--iai-co-ink);
  margin: 0;
  overflow-wrap: anywhere;
}

/* ── Accepted-payment brand strip ──────────────────────────────────────── */

.iai-paymarks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
}
/* Deliberately heavier than the fine print around them. These marks are doing
   a job — they are the answer to "can I actually pay you?", asked by someone
   deciding whether to trust the page — and at 0.72rem in muted grey they read
   as a footer, which is the one thing they must not. Full-contrast ink, a
   lifted card, and a real hover. */
.iai-paymark {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem .8rem;
  border: 1.5px solid var(--iai-co-line);
  border-radius: 10px;
  background: var(--iai-co-surface);
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--iai-co-ink);
  white-space: nowrap;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .05);
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.iai-paymark:hover {
  border-color: var(--iai-co-accent);
  box-shadow: 0 4px 12px rgba(15, 23, 42, .1);
  transform: translateY(-1px);
}
/* The brand marks are fixed-colour artwork, so on a dark ground they need a
   light plate behind them or the navy Visa block disappears into the card. */
.iai-paymark svg {
  display: block;
  border-radius: 4px;
}
[data-theme="dark"] .iai-paymark svg,
[data-theme="dark"] .iai-pm-mark svg {
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .92);
}
@media (prefers-color-scheme: dark) {
  html:not([data-theme]) .iai-paymark svg,
  html:not([data-theme]) .iai-pm-mark svg {
    box-shadow: 0 0 0 2px rgba(255, 255, 255, .92);
  }
}
.iai-paymarks-note {
  font-size: .72rem;
  color: var(--iai-co-ink-faint);
  display: inline-flex;
  align-items: center;
  gap: .3rem;
}
.iai-paymarks-note i { color: var(--iai-co-go); }

/* ── Option A / Option B layout (one-off vs subscribe) ─────────────────── */

.iai-co-optiontag {
  display: inline-block;
  font-size: .64rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--iai-co-accent);
  background: var(--iai-co-accent-dim);
  border-radius: 20px;
  padding: .22rem .6rem;
  margin-bottom: .6rem;
}
.iai-co-optiontag--alt { color: var(--violet-600); background: var(--violet-50); }

.iai-co-optionprice {
  display: flex;
  align-items: baseline;
  gap: .35rem;
  margin-bottom: .9rem;
}
.iai-co-optionprice b {
  font-size: 2.1rem;
  font-weight: 800;
  letter-spacing: -.03em;
  color: var(--iai-co-ink);
  line-height: 1;
}
.iai-co-optionprice span { font-size: .82rem; color: var(--iai-co-ink-faint); }

/* ── Alerts ────────────────────────────────────────────────────────────── */

.iai-co-notice {
  display: flex;
  align-items: flex-start;
  gap: .55rem;
  padding: .7rem .85rem;
  border-radius: 9px;
  font-size: .8rem;
  line-height: 1.55;
  background: var(--amber-50);
  border: 1px solid var(--amber-200);
  color: var(--amber-800);
  margin: 0;
}
.iai-co-notice i { margin-top: .15rem; flex-shrink: 0; }
.iai-co-notice--info { background: var(--iai-co-accent-dim); border-color: var(--blue-200); color: var(--blue-800); }

/* ── Responsive ────────────────────────────────────────────────────────── */

@media (max-width: 991.98px) {
  /* The summary stops being a sidebar and becomes a block above the methods,
     so the total is read before the choice rather than scrolled past it. */
  .iai-co-summary { position: static; }
}

@media (max-width: 575.98px) {
  .iai-co-card-body { padding: 1.15rem; }
  .iai-pm-tiles { grid-template-columns: 1fr; }
  .iai-co-title { font-size: 1.35rem; }
  .iai-co-line--total b { font-size: 1.2rem; }
  .iai-co-billedto { gap: .85rem; }
}

/* ── Dark mode ─────────────────────────────────────────────────────────── */

/* Driven by `data-theme` on <html> (static/js/theme-toggle.js), with the OS
   preference as the default when the customer has not chosen. Three selectors
   are needed and each does a different job:
     [data-theme="dark"]                     — the customer picked dark
     [data-theme="light"]                    — the customer picked light, and
                                               must win over a dark OS
     @media + :not([data-theme])             — no choice made, follow the OS
   Dropping the third makes the toggle the only way to get dark mode; dropping
   the second means a dark-OS customer cannot choose light. */

.iai-checkout,
.iai-pm-scope {
  color-scheme: light;
}

[data-theme="dark"] .iai-checkout,
[data-theme="dark"] .iai-pm-scope,
[data-theme="dark"] .iai-theme-toggle {
  color-scheme: dark;
  --iai-co-ink:        var(--slate-100);
  --iai-co-ink-soft:   var(--slate-400);
  --iai-co-ink-faint:  var(--slate-500);
  --iai-co-line:       var(--slate-700);
  --iai-co-line-soft:  var(--night-line);
  --iai-co-surface:    var(--night-surface);
  --iai-co-canvas:     var(--night-canvas);
  --iai-co-accent:     var(--blue-400);
  --iai-co-accent-dim: rgba(96, 165, 250, .14);
  --iai-co-go:         var(--green-500);
  --iai-co-go-dark:    var(--green-600);
  /* A shadow of near-black over a dark ground is invisible; on dark surfaces
     depth has to come from a lighter hairline instead. */
  --iai-co-shadow:     0 0 0 1px rgba(148, 163, 184, .10), 0 8px 24px rgba(0, 0, 0, .45);
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme]) .iai-checkout,
  html:not([data-theme]) .iai-pm-scope,
  html:not([data-theme]) .iai-theme-toggle {
    color-scheme: dark;
    --iai-co-ink:        var(--slate-100);
    --iai-co-ink-soft:   var(--slate-400);
    --iai-co-ink-faint:  var(--slate-500);
    --iai-co-line:       var(--slate-700);
    --iai-co-line-soft:  var(--night-line);
    --iai-co-surface:    var(--night-surface);
    --iai-co-canvas:     var(--night-canvas);
    --iai-co-accent:     var(--blue-400);
    --iai-co-accent-dim: rgba(96, 165, 250, .14);
    --iai-co-go:         var(--green-500);
    --iai-co-go-dark:    var(--green-600);
    --iai-co-shadow:     0 0 0 1px rgba(148, 163, 184, .10), 0 8px 24px rgba(0, 0, 0, .45);
  }
}

/* The page ground behind the cards. base_app.html sets .app-content's
   background in its own inline block; (0,2,0) here outranks that (0,1,0)
   regardless of source order, so the surround follows the theme instead of
   leaving dark cards floating on a light page. */
[data-theme="dark"] .app-content { background: var(--night-page); }
@media (prefers-color-scheme: dark) {
  html:not([data-theme]) .app-content { background: var(--night-page); }
}

/* ── Theme toggle ──────────────────────────────────────────────────────── */

.iai-theme-toggle {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .4rem .75rem;
  border: 1px solid var(--iai-co-line);
  border-radius: 999px;
  background: var(--iai-co-surface);
  color: var(--iai-co-ink-soft);
  font-size: .78rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.iai-theme-toggle:hover {
  border-color: var(--iai-co-accent);
  color: var(--iai-co-accent);
}
.iai-theme-toggle:focus-visible {
  outline: 2px solid var(--iai-co-accent);
  outline-offset: 2px;
}
.iai-theme-toggle-icon { display: inline-flex; }

/* Exactly one glyph is ever shown: moon in light mode ("go dark"), sun in
   dark mode ("go light"). Keyed off the same attribute as the palette, so the
   icon can never disagree with the theme it is offering to leave. */
.iai-theme-sun { display: none; }
.iai-theme-moon { display: block; }
[data-theme="dark"] .iai-theme-sun { display: block; }
[data-theme="dark"] .iai-theme-moon { display: none; }
@media (prefers-color-scheme: dark) {
  html:not([data-theme]) .iai-theme-sun { display: block; }
  html:not([data-theme]) .iai-theme-moon { display: none; }
}


/* ============================================================================
 * Trial → paid
 * ============================================================================
 * The end of a 14-day trial is the single highest-stakes moment on the plan
 * chooser: the customer has the product, has lost access, and is deciding
 * whether to pay. It used to render as a pale amber note in the same weight as
 * every other status line, beside a Starter card whose button said "Start Free
 * Trial" and linked back to the same page. Nothing about it said "this is the
 * moment", and nothing about it led anywhere.
 *
 * Styled to carry that weight, and scoped to .trial-ended-* so it cannot leak
 * into the two calmer states (on-trial, already-paying) that share the card.
 * ========================================================================= */

.trial-ended-icon {
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  color: var(--white);
  background: linear-gradient(135deg, var(--amber-500), var(--orange-500));
  box-shadow: 0 4px 12px rgba(245, 158, 11, .35);
}

.trial-ended-title {
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--iai-co-ink, var(--slate-900));
  margin-bottom: .15rem;
}

.trial-ended-body {
  font-size: .86rem;
  line-height: 1.5;
  color: var(--iai-co-ink-soft, var(--slate-500));
}
.trial-ended-body strong { color: var(--iai-co-ink, var(--slate-900)); }

.trial-ended-cta {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .7rem 1.1rem;
  border-radius: 11px;
  background: var(--iai-co-go, var(--green-600));
  color: var(--white);
  font-size: .9rem;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(22, 163, 74, .3);
  transition: background .15s ease, box-shadow .15s ease, transform .1s ease;
}
.trial-ended-cta:hover {
  background: var(--iai-co-go-dark, var(--green-700));
  color: var(--white);
  box-shadow: 0 6px 18px rgba(22, 163, 74, .4);
  transform: translateY(-1px);
}
.trial-ended-cta:focus-visible {
  outline: 2px solid var(--green-700);
  outline-offset: 2px;
}

/* The card the banner is pointing at. Without this the customer is told to
   "continue on Starter" and then has to work out which of four lookalike
   cards that is. */
.sub-card.continuation-plan {
  border-color: var(--green-600);
  box-shadow: 0 0 0 3px rgba(22, 163, 74, .15), 0 8px 28px rgba(22, 163, 74, .18);
}
.sub-card.continuation-plan::before {
  background: linear-gradient(90deg, var(--green-600), var(--green-700));
}
.sub-badge--continue {
  background: var(--green-100);
  color: var(--green-700);
  border: 1px solid var(--green-600);
}

@media (max-width: 767.98px) {
  /* Stacked, the CTA must not sit flush against the copy or it reads as part
     of the sentence rather than the thing to press. */
  .trial-ended-cta { width: 100%; justify-content: center; margin-top: .75rem; }
}

/* ============================================================================
 * Plan chooser — dark theme
 * ============================================================================
 * subscriptions/subscribe.html styles its own cards in a page-level block with
 * fixed light colours. It shares the theme toggle with checkout, so without
 * these overrides flipping to dark would darken the page ground and leave four
 * bright white cards sitting on it — a toggle that half works is worse than
 * none.
 *
 * Overrides rather than a rewrite of that block: those rules are the page's
 * light theme and are correct as they stand. Each selector here is (0,2,0)
 * against the page's (0,1,0), so it wins on specificity regardless of load
 * order. Folding that block into a stylesheet the way signup.html's was is the
 * better end state and a separate job.
 * ========================================================================= */

[data-theme="dark"] .status-card,
[data-theme="dark"] .sub-card {
  background: var(--night-surface);
  border-color: var(--night-line);
  box-shadow: 0 0 0 1px rgba(148, 163, 184, .08), 0 8px 24px rgba(0, 0, 0, .5);
}
[data-theme="dark"] .sub-card:hover {
  box-shadow: 0 0 0 1px rgba(148, 163, 184, .16), 0 14px 36px rgba(0, 0, 0, .6);
}
[data-theme="dark"] .sub-price-num,
[data-theme="dark"] .sub-plan-name { color: var(--slate-100); }
[data-theme="dark"] .sub-plan-desc,
[data-theme="dark"] .sub-features li { color: var(--slate-400); }
[data-theme="dark"] .sub-price-per,
[data-theme="dark"] .section-label { color: var(--slate-500); }
[data-theme="dark"] .sub-divider { background: var(--night-line); }
[data-theme="dark"] .sub-features li.sub-off { color: var(--slate-600); }
[data-theme="dark"] .sub-chk--on { background: rgba(34, 197, 94, .18); color: var(--green-500); }
[data-theme="dark"] .sub-chk--off { background: var(--night-line); color: var(--slate-600); }

[data-theme="dark"] .sub-cta {
  background: var(--night-canvas);
  border-color: var(--night-line);
  color: var(--slate-100);
}
[data-theme="dark"] .sub-cta-icon { background: var(--slate-700); }
[data-theme="dark"] .sub-cta--disabled {
  background: var(--night-canvas);
  border-color: var(--night-line);
  color: var(--slate-600);
}

/* The featured (Business) card is already a dark gradient in light mode, so it
   needs no recolour — only a rim so it does not merge into the page ground. */
[data-theme="dark"] .sub-card--featured {
  box-shadow: 0 0 0 1px rgba(148, 163, 184, .18), 0 14px 40px rgba(0, 0, 0, .55);
}

[data-theme="dark"] .trial-ended-body { color: var(--slate-400); }
[data-theme="dark"] .trial-ended-title { color: var(--slate-100); }
[data-theme="dark"] .trial-ended-body strong { color: var(--slate-100); }
[data-theme="dark"] .sub-badge--continue {
  background: rgba(34, 197, 94, .16);
  color: var(--green-500);
  border-color: var(--green-600);
}
[data-theme="dark"] .sub-badge--trial {
  background: rgba(96, 165, 250, .16);
  color: var(--blue-400);
  border-color: var(--night-line);
}
[data-theme="dark"] .sub-badge--current {
  background: rgba(34, 197, 94, .16);
  color: var(--green-500);
  border-color: var(--green-600);
}
