/* ============================================================
   PLANS & PRICING PAGE — page-specific chrome only.
   Structural port of `plans.jsx` + `plan-options.jsx` (couple-website-markup
   repo). Base layout is inline in `templates/pages/plans.php` (matching the
   reference's own inline-style-heavy JSX — same "chrome is inline" note the
   shared `.plan-nav*`/`.plan-block*`/`.compare-*` responsive rules in
   styles.css already carry). Everything below is the piece that isn't:
   named-class base recipes and the no-JS toggle mechanism.

   NO-JS TERM/TICKET TOGGLE (03_PAGE_DATA_CONTRACTS.md §1.3): the reference
   swaps price/features/CTA via React state. This port uses a real
   `role="radiogroup"` of radio inputs + `:has()` to show the matching
   `.plan-option-panel` — works with JS disabled, same "native control
   first" rule as the FAQ accordion's `<details>`. Panel ids are option ids
   (`1mo`/`3mo`/`6mo`/`1`/`5`), scoped by each `.plan-block` so the same
   option id in two different plans' toggles never collides.
   ============================================================ */

/* ---------- STICKY PLAN NAV ---------- */
/* SC-37 (2026-10-02): `cursor: pointer` is inline on the design's tab
   (`plans.jsx:162`) — Safari showed the arrow on v3's (brief PLANS-0bzhk). */
.plan-nav-item { color: var(--fg-heading); cursor: pointer; transition: background 200ms ease, padding 240ms ease, gap 240ms ease; }
.plan-nav-item .sub { color: var(--ink-500); }
.plan-nav-item.is-active { background: var(--couple-purple); }
.plan-nav-item.is-active .label { color: #fff; }
/* SC-37 (brief PLANS-10ryh): the selected tab's price line is GOLD, not white
   (`plans.jsx:174`: `color: isActive ? 'var(--couple-yellow)' : 'var(--ink-500)'`). */
.plan-nav-item.is-active .sub { color: var(--couple-yellow); }
.plan-nav-wrap.is-stuck .plan-nav { box-shadow: var(--shadow-elevated); }

/* "Compact on stuck" pill morph — ported verbatim from `Plans & Pricing.html`'s
   own page-local <style> block (not the shared design-system styles.css,
   same "page-local chrome" convention Sign In's own CSS follows). Toggled
   by public/assets/js/plans.js alongside the `.is-stuck` class it already
   applies on scroll. */
.plan-nav-wrap { transition: padding 240ms cubic-bezier(.2,.8,.2,1), background 240ms ease, box-shadow 240ms ease, backdrop-filter 240ms ease; }
.plan-nav { transition: max-width 240ms cubic-bezier(.2,.8,.2,1), padding 240ms ease, box-shadow 240ms ease, border-radius 240ms ease; }
.plan-nav-item .label { transition: font-size 200ms ease; }
.plan-nav-item .sub { transition: opacity 180ms ease, max-height 240ms ease, margin 240ms ease; }
.plan-nav-dot {
  display: none;
  width: 10px;
  height: 10px;
  border-radius: 999px;
  flex: none;
}
.plan-nav-wrap.is-stuck.compact .plan-nav-item {
  flex-direction: row !important;
  gap: 12px;
  padding: 12px 14px;
}
.plan-nav-wrap.is-stuck.compact .plan-nav-dot { display: block; }
.plan-nav-wrap.is-stuck.compact .plan-nav-item.is-active .plan-nav-dot { background: var(--couple-yellow) !important; }
.plan-nav-wrap.is-stuck.compact .plan-nav-item .sub {
  opacity: 0;
  max-height: 0;
  margin: 0;
  overflow: hidden;
}

/* ---------- SEGMENTED TOGGLE (term / ticket quantity) ---------- */
.seg-toggle {
  display: inline-flex;
  gap: 0;
  background: #fff;
  border: var(--border-hairline) solid var(--ink-100);
  border-radius: var(--r-pill);
  padding: 4px;
  box-shadow: var(--shadow-subtle);
  max-width: 100%;
  /* SC-37 (brief PLANS-0a4ab): one row above 1100 — the design's inline
     styles declare no wrap (`plan-options.jsx:33-43`); only its ≤1100 block
     adds `flex-wrap: wrap` (the Plans page `<style>`), and with the 14px /
     16px-padding step below the three terms fit on one line down to 641. v3
     wrapped at 1060–1101 and on iPad landscape where the design did not. */
  flex-wrap: nowrap;
}
.seg-toggle-radio {
  /* Visually hidden but still focusable/operable — a real radio, not
     display:none, so keyboard + assistive-tech semantics stay intact. */
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}
.seg-toggle-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  border-radius: var(--r-pill);
  cursor: pointer;
  font: 700 16px var(--font-display);
  letter-spacing: -0.1px;
  white-space: nowrap;
  color: var(--fg-heading);
  transition: background 160ms ease, color 160ms ease;
}
.seg-toggle-item:hover { background: var(--lavender-hover); }
.seg-toggle-radio:checked + .seg-toggle-item {
  background: var(--couple-purple);
  color: #fff;
}
/* SC-37 (brief PLANS-034jz): NO darker hover on the selected option — the
   design's active segment is `var(--couple-purple)` inline and never changes
   (`plan-options.jsx:66`). The pointer sits on the option just clicked, so
   v3's `:checked + :hover` rule was what the comparison measured. The
   lavender hover on an UNSELECTED option stays: the design's inline styles
   cannot express a hover at all, and this one is an affordance, not a colour
   the comparison flagged — recorded, not changed. */
.seg-toggle-save {
  font: 700 12px/1 var(--font-display);
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--couple-purple);
}
.seg-toggle-radio:checked + .seg-toggle-item .seg-toggle-save { color: var(--couple-yellow); }
.seg-toggle-radio:focus-visible + .seg-toggle-item { outline: 2px solid var(--couple-purple); outline-offset: 2px; }

/* Option panels — only the one matching the checked radio in this plan's
   toggle renders. `:has()` support: all current evergreen browsers. */
.plan-option-panel { display: none; }
.plan-block:has(.seg-toggle-radio[value="1mo"]:checked) .plan-option-panel[data-panel="1mo"],
.plan-block:has(.seg-toggle-radio[value="3mo"]:checked) .plan-option-panel[data-panel="3mo"],
.plan-block:has(.seg-toggle-radio[value="6mo"]:checked) .plan-option-panel[data-panel="6mo"],
.plan-block:has(.seg-toggle-radio[value="1"]:checked) .plan-option-panel[data-panel="1"],
.plan-block:has(.seg-toggle-radio[value="5"]:checked) .plan-option-panel[data-panel="5"] {
  display: block;
}

/* ---------- PRICE / FEATURES / CTA ---------- */
.plan-price-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 24px 0 0;
  flex-wrap: wrap;
}
/* SC-37 (brief PLANS-18x27): the price's ink is the heading's — the design's
   span sets `color: var(--fg-heading)` inline (`plans.jsx:316`); the
   `grad-purple` class it used to wear is gone from `render_plan_price_block()`. */
.plan-price { font: var(--type-h1); letter-spacing: -0.8px; color: var(--fg-heading); }
.plan-price-unit { font: 500 20px/1 var(--font-body); color: var(--ink-500); }
/* FF-47 (2026-09-28) - the catalog price a claimed discount replaces, struck,
   before the price the member pays. No design exists for a discounted Plans
   state; this is the one rule it needed. One step below the price, in the
   unit's ink, so the figure that reads first is the one that is charged. */
.plan-price-was {
  font: 500 28px/1 var(--font-body);
  color: var(--ink-500);
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}
.plan-unit-note {
  font: 700 20px/1 var(--font-display);
  color: var(--couple-purple);
  letter-spacing: -0.2px;
  margin: 12px 0 0;
}
.plan-features-block { margin: 32px 0 0; }
/* SC-37 (brief PLANS-1d124): 20px under "What's included" — inline on the
   design's eyebrow (`plans.jsx:328`, `marginBottom: 20`); v3 had none, so
   the first bullet sat 5px under the label. */
.plan-features-block > .eyebrow--heading { margin-bottom: 20px; }
.plan-feature-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 14px; }
.plan-feature { display: flex; align-items: flex-start; gap: 14px; font: var(--type-body-sm); color: var(--ink-700); }
.plan-feature-check {
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--couple-purple);
  display: grid; place-items: center;
  flex-shrink: 0;
  margin-top: 2px;
}
.plan-cta-block { margin-top: 40px; }
.plan-fine-print { font: var(--type-body-sm); color: var(--ink-500); margin: 16px 0 0; max-width: 460px; }
.plan-mockup-img { display: block; width: 100%; height: auto; }

/* ---------- TOP-UPS (Couple Coins banner) ----------
   SC-37 (2026-10-02, brief PLANS-1msul and its 10 rows, 0wgkj, 07ulg, 1nclj,
   0xd1o, 0wauy, 0cwxm, 0dr6a, 0rus8): the design's coin bar is a WHITE card
   with a hairline border, a 22px radius and dark text; a purple-gradient
   medallion carrying the coin glyph; the title and price on the
   `--fs-display-sm` ramp (30 ↔ 20) with line-height 1 and -0.5px tracking;
   the price BESIDE "Buy coins" (a 24px gap, centred). v3 had invented a purple
   gradient card with white text, a translucent medallion, a fixed 24px price
   stacked above the button. Every rule below is the Plans page's own
   `<style>` block (`Plans & Pricing.html:25-50`), verbatim but for the glyph
   sizing, which the design sets inline on the SVG (`plan-options.jsx:113`,
   Lesson 2). */
.coinbar {
  display: flex;
  align-items: center;
  gap: 28px;
  background: #fff;
  border: var(--border-hairline) solid var(--ink-100);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
  padding: 28px 40px;
}
.coinbar-medallion {
  width: calc(80 * var(--el-px));
  height: calc(80 * var(--el-px));
  border-radius: var(--r-circle);
  background: var(--grad-cta-purple);
  box-shadow: var(--shadow-cta);
  display: grid;
  place-items: center;
  flex: none;
}
.coinbar-medallion .cc-coin {
  height: calc(42 * var(--el-px));
  width: auto;
  color: #fff;
}
.coinbar-text { flex: 1; min-width: 0; }
.coinbar-title {
  font: 700 var(--fs-display-sm)/1 var(--font-display);
  color: var(--fg-heading);
  letter-spacing: -0.5px;
}
.coinbar-sub { font: var(--type-body-sm); color: var(--ink-700); margin: 10px 0 0; max-width: 560px; }
.coinbar-buy { display: flex; align-items: center; gap: 24px; flex: none; }
.coinbar-price {
  font: 700 var(--fs-display-sm)/1 var(--font-display);
  color: var(--fg-heading);
  letter-spacing: -0.5px;
}

/* ---------- COMPARE TABLE ---------- */
.compare-cell { border-top: none; border-bottom: none; }
.compare-scroll::-webkit-scrollbar { height: 6px; }
.plan-compare-check {
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-grid; place-items: center;
}
.plan-compare-dash { width: 26px; height: 2px; background: var(--ink-200); display: inline-block; border-radius: 4px; }

/* ---------- PLANS FAQ (native <details>, same recipe as faq.css) ---------- */
.plans-faq-item {
  border-radius: var(--r-card-sm);
  border: var(--border-hairline) solid var(--ink-100);
  background: #fff;
  overflow: hidden;
  transition: background 200ms ease, border-color 200ms ease;
}
.plans-faq-item:hover { border-color: var(--lavender-border); }
.plans-faq-item[open] { background: var(--lavender); border-color: var(--lavender-border); }
.plans-faq-q {
  width: 100%;
  display: flex; align-items: center; gap: 20px;
  padding: 20px 24px;
  background: transparent; border: 0; cursor: pointer;
  text-align: left;
  list-style: none;
}
.plans-faq-q::-webkit-details-marker { display: none; }
.plans-faq-q::marker { content: ""; }
.plans-faq-q-text {
  flex: 1;
  font: 700 20px/1.4 var(--font-display);
  color: var(--fg-heading);
  letter-spacing: -0.2px;
}
.plans-faq-item[open] .plans-faq-q-text { color: var(--couple-purple-dark); }
.plans-faq-q-icon {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--lavender-hover);
  color: var(--couple-purple);
  display: grid; place-items: center;
  flex-shrink: 0;
  transition: background 200ms ease, color 200ms ease, transform 240ms ease;
}
.plans-faq-item[open] .plans-faq-q-icon { background: var(--couple-purple); color: #fff; transform: rotate(45deg); }
.plans-faq-a { padding: 0 24px 24px; font: var(--type-body); color: var(--couple-purple-dark); }
.plans-faq-a p { margin: 0 0 16px; }
.plans-faq-a p:last-child { margin-bottom: 0; }

/* ============================================================
   RESPONSIVE — follows the project's 1100/900/768/640 cadence. The
   shared `.plan-nav*`/`.plan-block*`/`.compare-section` breakpoints
   already live in styles.css (Batch 0 port); only this page's own
   classes need rules here.
   ============================================================ */
/* SC-37 (2026-10-02, brief PLANS-17573): the design's phone step for the tab
   label is `.plan-nav-item span:first-child { font-size: 14px !important }`
   (`styles.css:980`) — a POSITIONAL selector, and in v3's tab the first span is
   the compact-mode accent dot (`plans.php`), always in the markup so there is
   no layout shift when `plans.js` attaches. So the design's rule landed on the
   dot and the label stayed at its inline 16px, which is why v3's tab bar was
   26px taller on phones. The `.sub` is still the last child, so its 12px step
   applies as written. Same value, named selector. */
@media (max-width: 640px) {
  .plan-nav-item .label { font-size: 14px !important; }
}
/* SC-37 (2026-10-02): the design's own tiers for the pieces this file owns —
   the coin-bar section's padding, the coin bar's stack, and the term / ticket
   toggles (brief PLANS-1oo4b, 1gl34, 1610a, 1641d, 00823 and their rows). All
   from the Plans page's `<style>` block (`Plans & Pricing.html:62-128`). The
   `!important` on `.topups-section` is the design's own ladder convention: it
   has to beat the `.section` ladder in `styles.css`, which is `!important`
   too (RESPONSIVE_DESIGN_REVIEW.md §2-L). The toggle rules need none — v3's
   toggle has no inline styles, and every tier rule here sits BELOW the base
   rule it beats at equal specificity (§2-A). */
@media (max-width: 1100px) {
  .topups-section { padding: 16px 56px 48px !important; }
  .seg-toggle { flex-wrap: wrap; }
  /* Mobile Review S5 — the design's ≥44px touch floor on the option pills;
     14px labels (v3 kept 16px, which is why its toggles ran ~50px wider). */
  .seg-toggle-item { padding: 12px 16px; font-size: 14px; min-height: 44px; }
  .seg-toggle-save { font-size: 12px; }
}
@media (max-width: 900px) {
  .topups-section { padding: 8px 48px 40px !important; }
  /* The coin bar restacks from ≤900 (Ryan's go, 2026-09-30 — the brief's
     "pull the latest prototype" note): medallion, text, then a row with the
     price at the left and Buy coins at the right. The card keeps its 28/40
     padding here; ≤640 tightens it to 24. */
  .coinbar { flex-direction: column; align-items: flex-start; gap: 20px; }
  .coinbar-buy { width: 100%; justify-content: space-between; }
}
@media (max-width: 640px) {
  .topups-section { padding: 8px 20px 32px !important; }
  .coinbar { padding: 24px; border-radius: var(--r-card); }

  /* The reference drops decorative device shots on narrow screens so the
     plan details and purchase CTA retain the full viewport width. */
  .plan-mockup-col { display: none !important; }
  /* FF-47: at 28px the struck price pushed the unit onto a line of its own at
     390 (rendered 2026-09-28); at the unit's own 20px the row stays one line
     — was, now, per — as the undiscounted row is. */
  .plan-price-was { font-size: 20px; }

  /* The toggles become a stacked list on a phone (brief PLANS-00823 and its
     16 rows): column, every option a full-width row with its SAVE label at the
     right, 16px corners on the group and 12px on each row. v3 kept the 999px
     pill and wrapped it into two lines. */
  .seg-toggle {
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    width: 100%;
    max-width: 380px;
    border-radius: var(--r-card-sm);
  }
  .seg-toggle-item { width: 100%; justify-content: space-between; border-radius: var(--r-input); }

  .plans-faq-q { padding: 18px 20px; gap: 14px; }
  /* SC-37 (brief PLANS-1xzpl): the FAQ questions keep 20px / 28px on a phone —
     the design's span is `700 20px/1.4` inline at every width (`plans.jsx:607`);
     the 18px step that used to sit here was v3's own. */
  .plans-faq-a { padding: 0 20px 22px; }
}
@media (max-width: 420px) {
  .seg-toggle-item { padding: 12px 14px; font-size: 14px; gap: 8px; }
  .seg-toggle-save { font-size: 12px; }
}
