/**
 * plans.css — OPUS-F2 (2026-08-13)
 * The /plans tier-checkout door — the one surface where a stranger decides to pay.
 *
 * WHY THIS FILE EXISTS
 *   These rules previously lived in an inline @once <style> block inside
 *   resources/views/plans/index.blade.php, emitted into <body> (the block sits
 *   inside @section('content'), and the layout yields content in the body).
 *   That made the money page's styling uncacheable, unreviewable next to its
 *   siblings, and invisible to any sheet-level audit. It is now a real asset.
 *
 * WHAT CHANGED IN THE PIXELS
 *   The page painted in the ALIVE room's palette (deep-space navy ground,
 *   periwinkle #6366f1 CTAs) while its own header and footer paint in the
 *   PLATFORM room (graphite ground, gold #f59e0b). Measured on live
 *   2026-08-13: the Register button in the header rendered rgb(245,158,11)
 *   directly above CTAs rendering linear-gradient(#6366f1,#818cf8). Two rooms,
 *   one viewport. Every colour, space, radius and type size below now resolves
 *   through --nsk-* (W4-U5 estate kit, app scope), so the money page speaks the
 *   same language as the chrome wrapped around it and follows the live
 *   Gold/Silver x Dark/Light theme system instead of hard-coded literals.
 *
 * LOAD ORDER
 *   <link css/ui-kit.css>  then  <link css/pages/plans.css>
 *   both pushed to @stack('styles'), which sits in <head> AFTER
 *   css/design-system.css — the adoption contract ui-kit.css documents.
 *
 * SCOPE
 *   Every selector is a descendant of .ns-plans-page. This sheet cannot reach
 *   the shell, the nav, the footer, or any other page. No element selectors,
 *   no bare * , no !important except the [hidden] guard documented at its rule.
 *
 * NOT TOUCHED: markup semantics, checkout wiring (/api/checkout/session),
 * prices (config/pricing.php is the only price source), copy.
 */

/* ============================================================
 * LOCAL TOKEN BRIDGE
 * The page keeps its --nsp-* names so the blade's class contract is
 * unchanged, but every one of them is now a view onto a kit token.
 * The second fallback in each var() is the pre-kit literal, so this
 * sheet still renders correctly if ui-kit.css ever fails to load.
 * ============================================================ */
.ns-plans-page {
    --nsp-ground:      var(--nsk-bg, var(--ns-bg-primary, #1a1a1a));
    --nsp-card:        var(--nsk-surface, var(--ns-bg-secondary, #2d2d2d));
    --nsp-card-2:      var(--nsk-inset, var(--ns-bg-surface, #262626));
    --nsp-border:      var(--nsk-bd, var(--ns-border, #404040));
    --nsp-border-soft: var(--nsk-bd-soft, var(--ns-border-subtle, #333333));
    --nsp-text:        var(--nsk-ink, var(--ns-text-primary, #ffffff));
    /* --nsk-faint is deliberately NOT bridged here: at this page's surface
       colours it lands under WCAG AA, and nothing on a money page is minor
       enough to be unreadable. Secondary text stops at --nsp-muted. */
    --nsp-muted:       var(--nsk-sub, var(--ns-text-secondary, #a0a0a0));

    /* the room's interactive voice — gold in app scope, and the same token
       the header's Register button already resolves to */
    --nsp-accent:      var(--nsk-accent, var(--ns-accent, #f59e0b));
    --nsp-accent-hover:var(--nsk-accent-hover, var(--ns-accent-hover, #d97706));
    --nsp-on-accent:   var(--nsk-on-accent, var(--ns-accent-text, #000));
    --nsp-accent-soft: var(--nsk-accent-subtle, rgba(245, 158, 11, 0.1));

    /* affirmation voice — the free rung and every feature tick */
    --nsp-ok:          var(--nsk-ok, var(--ns-success, #10b981));
    --nsp-ok-bg:       var(--nsk-ok-bg, rgba(16, 185, 129, 0.1));
    --nsp-err:         var(--nsk-err, var(--ns-error, #ef4444));
    --nsp-err-bg:      var(--nsk-err-bg, rgba(239, 68, 68, 0.1));

    --nsp-radius-card: var(--nsk-radius-xl, 16px);
    --nsp-radius-act:  var(--nsk-radius-lg, 12px);
    --nsp-radius-full: var(--nsk-radius-full, 999px);

    --nsp-font:        var(--nsk-font-display, var(--ns-font-sans, 'Nunito', sans-serif));
    --nsp-motion:      var(--nsk-motion-base, 200ms ease);
    --nsp-shadow-pop:  var(--nsk-shadow-pop, 0 10px 30px rgba(0, 0, 0, 0.4));
}

/* ============================================================
 * BOX-SIZING GUARD
 * The estate kit ships no box-sizing reset by design (it is additive and
 * refuses to touch anything it does not own). Bootstrap's reboot supplies
 * one today, but this page must not inherit its 375 correctness from a
 * sheet it does not control: a single padded element under content-box
 * is what sends a phone viewport scrolling sideways. Scoped to this page,
 * so it changes nothing anywhere else.
 * ============================================================ */
.ns-plans-page,
.ns-plans-page *,
.ns-plans-page *::before,
.ns-plans-page *::after {
    box-sizing: border-box;
}

/* The resume and error banners are toggled by public/js/pages/plans-checkout.js
   through the `hidden` attribute alone. .ns-plans-resume carries display:flex,
   which outranks the UA [hidden] rule — today it stays hidden only because
   Bootstrap's reboot happens to declare [hidden]{display:none!important}.
   The money page should not depend on another sheet's !important to avoid
   greeting a first-time visitor with "Picking up where you left off…", so the
   guard is stated here, scoped to this page. */
.ns-plans-page [hidden] {
    display: none !important;
}

/* ============================================================
 * PAGE GROUND
 * ============================================================ */
.ns-plans-page {
    background:
        radial-gradient(120% 60% at 50% 0%, var(--nsp-accent-soft), transparent 60%),
        var(--nsp-ground);
    color: var(--nsp-text);
    font-family: var(--nsp-font);
    min-height: 100vh;
}

.ns-plans-shell {
    max-width: 1240px;
    margin: 0 auto;
    padding: 0 var(--nsk-space-4, 1rem);
}

/* ============================================================
 * HERO
 * ============================================================ */
.ns-plans-hero {
    padding: var(--nsk-space-8, 3rem) 0 var(--nsk-space-5, 1.5rem);
    text-align: center;
}

.ns-plans-title {
    font-family: var(--nsp-font);
    font-size: clamp(1.75rem, 4.5vw, 3.25rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: var(--nsk-leading-tight, 1.25);
    max-width: 860px;
    margin: 0 auto;
    /* long unbroken words in a clamped headline are a 375 overflow source */
    overflow-wrap: break-word;
}

.ns-plans-subtitle {
    color: var(--nsp-muted);
    font-size: var(--nsk-text-base, 1rem);
    line-height: var(--nsk-leading-normal, 1.5);
    max-width: 640px;
    margin: var(--nsk-space-4, 1rem) auto 0;
}

/* ============================================================
 * BILLING-CYCLE TOGGLE
 * ============================================================ */
.ns-plans-toggle {
    display: inline-flex;
    gap: var(--nsk-space-1, 0.25rem);
    margin: var(--nsk-space-6, 2rem) auto 0;
    padding: var(--nsk-space-1, 0.25rem);
    border: 1px solid var(--nsp-border);
    border-radius: var(--nsp-radius-full);
    background: var(--nsp-card-2);
}

.ns-plans-toggle button {
    border: 0;
    background: transparent;
    color: var(--nsp-muted);
    font-family: inherit;
    font-weight: 700;
    font-size: var(--nsk-text-sm, 0.875rem);
    /* min-height holds the estate's 44px touch target even if the type ramp
       or padding is retuned later */
    min-height: var(--nsk-touch, 44px);
    padding: var(--nsk-space-2, 0.5rem) var(--nsk-space-5, 1.5rem);
    border-radius: var(--nsp-radius-full);
    cursor: pointer;
    transition: background var(--nsp-motion), color var(--nsp-motion);
}

.ns-plans-toggle button:hover {
    color: var(--nsp-text);
}

.ns-plans-toggle button.is-active {
    background: var(--nsp-accent);
    color: var(--nsp-on-accent);
}

/* ============================================================
 * TIER GRID
 * ============================================================ */
.ns-plans-grid {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--nsk-space-4, 1rem);
    margin-top: var(--nsk-space-6, 2rem);
}

.ns-plans-card {
    grid-column: span 12;
    display: flex;
    flex-direction: column;
    background: var(--nsp-card);
    border: 1px solid var(--nsp-border);
    border-radius: var(--nsp-radius-card);
    /* the badge on the free card is absolutely positioned onto this top edge —
       the extra top padding is what keeps it from sitting on the heading */
    padding: var(--nsk-space-6, 2rem) var(--nsk-space-5, 1.5rem) var(--nsk-space-5, 1.5rem);
    position: relative;
    transition: border-color var(--nsp-motion), transform var(--nsp-motion),
        box-shadow var(--nsp-motion);
}

@media (min-width: 700px) {
    .ns-plans-card { grid-column: span 6; }
}

@media (min-width: 1200px) {
    .ns-plans-card { grid-column: span 4; }
}

.ns-plans-card:hover {
    border-color: var(--nsk-bd-strong, var(--ns-border-strong, #525252));
}

/* The rung this account is already on — quiet, not celebratory. */
.ns-plans-card--current {
    border-color: var(--nsp-accent);
    box-shadow: 0 0 0 1px var(--nsp-accent-soft);
}

/* The free rung carries the page's own headline promise ("Start free"), so it
   is the one card allowed to speak in the affirmation voice. */
.ns-plans-card--free {
    border-color: color-mix(in srgb, var(--nsp-ok) 45%, transparent);
}

.ns-plans-name {
    font-family: var(--nsp-font);
    font-size: var(--nsk-text-lg, 1.25rem);
    font-weight: 800;
    line-height: var(--nsk-leading-tight, 1.25);
    margin: 0;
}

.ns-plans-tagline {
    color: var(--nsp-muted);
    font-size: var(--nsk-text-sm, 0.875rem);
    line-height: var(--nsk-leading-normal, 1.5);
    margin: var(--nsk-space-1, 0.25rem) 0 0;
}

/* The two reserved-height lines below exist ONLY to keep price baselines
   agreeing across a row. Below 700px the grid is a single column, where the
   reservation buys nothing and shows up as a hole under a one-line tagline —
   so it starts at the breakpoint where the cards actually sit side by side. */
@media (min-width: 700px) {
    .ns-plans-tagline { min-height: 2.6em; }
    .ns-plans-price-note { min-height: 1.2em; }
}

/* ============================================================
 * PRICE
 * Every figure here renders from config/pricing.php. Nothing in this
 * sheet may imply a number the config does not carry.
 * ============================================================ */
.ns-plans-price {
    margin-top: var(--nsk-space-5, 1.5rem);
    font-size: var(--nsk-text-2xl, 2rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--nsp-text);
}

.ns-plans-price small {
    font-size: var(--nsk-text-sm, 0.875rem);
    color: var(--nsp-muted);
    font-weight: 600;
    letter-spacing: 0;
}

/* "Custom" is a word, not a figure — at the numeral's size it shouted louder
   than every real price on the page. It sits on the ramp one step down. */
.ns-plans-price:not(:has(span)) {
    font-size: var(--nsk-text-xl, 1.5rem);
}

/* Muted, not faint. --nsk-faint (#6b7280) on the card surface (#2d2d2d)
   measures ~2.9:1 — under AA, and this line carries "Billed monthly" and
   "Free — no credit card", which are billing terms a buyer must be able to
   read. --nsk-sub (#a0a0a0) on the same surface measures ~5.3:1. */
.ns-plans-price-note {
    color: var(--nsp-muted);
    font-size: var(--nsk-text-sm, 0.875rem);
    margin-top: var(--nsk-space-2, 0.5rem);
}

/* ============================================================
 * FEATURES
 * ============================================================ */
.ns-plans-list {
    list-style: none;
    margin: var(--nsk-space-5, 1.5rem) 0;
    padding: 0;
    display: grid;
    gap: var(--nsk-space-3, 0.75rem);
    /* grows so the action block bottom-aligns across a row */
    flex-grow: 1;
}

.ns-plans-list li {
    display: flex;
    gap: var(--nsk-space-2, 0.5rem);
    align-items: flex-start;
    color: var(--nsk-text, var(--ns-text-primary, #ffffff));
    font-size: var(--nsk-text-sm, 0.875rem);
    line-height: var(--nsk-leading-normal, 1.5);
}

.ns-plans-list i {
    color: var(--nsp-ok);
    margin-top: 0.2em;
    flex-shrink: 0;
}

/* ============================================================
 * ACTIONS
 * The rungs are a ladder: every tier's action carries the same weight,
 * because the page must not imply a recommendation it has not earned.
 * Only "Talk to sales" is quieter, and only because it is a different
 * kind of act — a conversation, not a purchase.
 * ============================================================ */
.ns-plans-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--nsk-space-2, 0.5rem);
    width: 100%;
    min-height: var(--nsk-touch, 44px);
    padding: var(--nsk-space-3, 0.75rem) var(--nsk-space-4, 1rem);
    border-radius: var(--nsp-radius-act);
    font-family: inherit;
    font-weight: 700;
    font-size: var(--nsk-text-base, 1rem);
    text-align: center;
    text-decoration: none;
    border: 1px solid transparent;
    cursor: pointer;
    transition: background var(--nsp-motion), border-color var(--nsp-motion),
        color var(--nsp-motion), transform var(--nsp-motion),
        box-shadow var(--nsp-motion);
}

.ns-plans-cta-primary {
    background: var(--nsp-accent);
    border-color: var(--nsp-accent);
    color: var(--nsp-on-accent);
}

.ns-plans-cta-primary:hover,
.ns-plans-cta-primary:focus {
    background: var(--nsp-accent-hover);
    border-color: var(--nsp-accent-hover);
    color: var(--nsp-on-accent);
    transform: translateY(-1px);
    box-shadow: var(--nsp-shadow-pop);
}

.ns-plans-cta-secondary {
    background: transparent;
    border-color: var(--nsk-bd-strong, var(--ns-border-strong, #525252));
    color: var(--nsp-text);
}

.ns-plans-cta-secondary:hover,
.ns-plans-cta-secondary:focus {
    background: var(--nsk-surface-2, var(--ns-bg-tertiary, #3d3d3d));
    border-color: var(--nsp-accent);
    color: var(--nsp-text);
}

/* The estate's one focus ring. The pre-kit sheet declared no focus styling at
   all, which left a keyboard buyer with no idea which plan they were on. */
.ns-plans-cta:focus-visible,
.ns-plans-toggle button:focus-visible,
.ns-plans-resume a:focus-visible {
    outline: 2px solid var(--nsk-focus, var(--ns-accent, #f59e0b));
    outline-offset: 2px;
}

.ns-plans-cta:active {
    transform: translateY(0) scale(0.99);
}

.ns-plans-cta[disabled] {
    opacity: 0.65;
    cursor: wait;
    transform: none;
    box-shadow: none;
}

/* ============================================================
 * CHIPS, BADGES, NOTES
 * ============================================================ */
.ns-plans-current-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--nsk-space-2, 0.5rem);
    width: 100%;
    min-height: var(--nsk-touch, 44px);
    padding: var(--nsk-space-3, 0.75rem) var(--nsk-space-4, 1rem);
    border-radius: var(--nsp-radius-act);
    font-weight: 700;
    font-size: var(--nsk-text-sm, 0.875rem);
    background: var(--nsp-accent-soft);
    border: 1px solid color-mix(in srgb, var(--nsp-accent) 40%, transparent);
    color: var(--nsp-accent);
}

/* Same AA reasoning as .ns-plans-price-note — this line is the free rung's
   reassurance, so it has to survive being read. */
.ns-plans-free-note {
    color: var(--nsp-muted);
    font-size: var(--nsk-text-sm, 0.875rem);
    line-height: var(--nsk-leading-normal, 1.5);
    margin: var(--nsk-space-3, 0.75rem) 0 0;
    text-align: center;
}

.ns-plans-badge {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -50%);
    /* the badge is nearly card-width at 375; keeping it inside the card's
       padding box is what stops it reading as a sticker across the border */
    max-width: calc(100% - var(--nsk-space-8, 3rem));
    padding: var(--nsk-space-1, 0.25rem) var(--nsk-space-3, 0.75rem);
    border-radius: var(--nsp-radius-full);
    font-size: var(--nsk-label-size, 11px);
    font-weight: var(--nsk-label-weight, 600);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    background: var(--nsp-ok-bg);
    border: 1px solid color-mix(in srgb, var(--nsp-ok) 45%, transparent);
    color: var(--nsp-ok);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ============================================================
 * BANNERS
 * ============================================================ */
.ns-plans-error {
    margin: var(--nsk-space-5, 1.5rem) auto 0;
    max-width: 720px;
    padding: var(--nsk-space-3, 0.75rem) var(--nsk-space-4, 1rem);
    border-radius: var(--nsp-radius-act);
    border: 1px solid color-mix(in srgb, var(--nsp-err) 45%, transparent);
    background: var(--nsp-err-bg);
    color: var(--nsp-err);
    font-size: var(--nsk-text-sm, 0.875rem);
    line-height: var(--nsk-leading-normal, 1.5);
}

.ns-plans-error a {
    color: inherit;
    text-decoration: underline;
}

.ns-plans-resume {
    margin: var(--nsk-space-5, 1.5rem) auto 0;
    max-width: 720px;
    padding: var(--nsk-space-3, 0.75rem) var(--nsk-space-4, 1rem);
    border-radius: var(--nsp-radius-act);
    border: 1px solid color-mix(in srgb, var(--nsp-accent) 45%, transparent);
    background: var(--nsp-accent-soft);
    color: var(--nsp-text);
    font-size: var(--nsk-text-sm, 0.875rem);
    display: flex;
    justify-content: space-between;
    gap: var(--nsk-space-4, 1rem);
    flex-wrap: wrap;
    align-items: center;
}

.ns-plans-resume a {
    color: var(--nsp-accent);
    text-decoration: underline;
    border-radius: var(--nsk-radius-sm, 4px);
}

/* ============================================================
 * TRUST BAND
 * ============================================================ */
.ns-plans-trust {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--nsk-space-4, 1rem);
    margin: var(--nsk-space-8, 3rem) 0 var(--nsk-space-10, 4rem);
}

/* Same surface as the tier cards, not the darker inset: it keeps one card
   anatomy on the page, and it lifts this band's body copy from 4.82:1 to
   5.25:1 — the lowest-contrast text on the page sits here. */
.ns-plans-trust-item {
    grid-column: span 12;
    background: var(--nsp-card);
    border: 1px solid var(--nsp-border-soft);
    border-radius: var(--nsp-radius-card);
    padding: var(--nsk-space-5, 1.5rem);
    text-align: center;
}

@media (min-width: 700px) {
    .ns-plans-trust-item { grid-column: span 4; }
}

.ns-plans-trust-item i {
    color: var(--nsp-accent);
    font-size: var(--nsk-text-lg, 1.25rem);
    margin-bottom: var(--nsk-space-3, 0.75rem);
    display: block;
}

.ns-plans-trust-item strong {
    display: block;
    margin-bottom: var(--nsk-space-2, 0.5rem);
    font-size: var(--nsk-text-base, 1rem);
    color: var(--nsp-text);
}

.ns-plans-trust-item span {
    color: var(--nsp-muted);
    font-size: var(--nsk-text-sm, 0.875rem);
    line-height: var(--nsk-leading-normal, 1.5);
    display: block;
}

/* ============================================================
 * ALPINE
 * The yearly figure is cloaked until Alpine binds, so a slow parse can
 * never paint two prices on one card at once.
 * ============================================================ */
.ns-plans-page [x-cloak] {
    display: none !important;
}

/* ============================================================
 * 375-FIRST GUARD
 * Six stacked rungs is an inherently long phone page; this tightens the
 * rhythm without taking the air out of the cards.
 * ============================================================ */
@media (max-width: 479px) {
    .ns-plans-hero {
        padding: var(--nsk-space-6, 2rem) 0 var(--nsk-space-4, 1rem);
    }

    .ns-plans-card {
        padding: var(--nsk-space-5, 1.5rem) var(--nsk-space-4, 1rem) var(--nsk-space-4, 1rem);
    }

    .ns-plans-list {
        margin: var(--nsk-space-4, 1rem) 0;
        gap: var(--nsk-space-2, 0.5rem);
    }

    .ns-plans-trust {
        margin: var(--nsk-space-6, 2rem) 0 var(--nsk-space-8, 3rem);
    }

    .ns-plans-trust-item {
        padding: var(--nsk-space-4, 1rem);
    }

    /* the two-word cycle labels do not need 1.5rem of side padding on a phone */
    .ns-plans-toggle button {
        padding: var(--nsk-space-2, 0.5rem) var(--nsk-space-4, 1rem);
    }
}

/* ============================================================
 * REDUCED MOTION
 * ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .ns-plans-card,
    .ns-plans-cta,
    .ns-plans-toggle button {
        transition: none;
    }

    .ns-plans-cta-primary:hover,
    .ns-plans-cta-primary:focus,
    .ns-plans-cta:active {
        transform: none;
    }
}
