/*
 * PUBLIC ROOM — Night Shift
 *
 * Ported from public/nightshift/FPMB_NightShift_Full.html onto the brand.css tokens.
 * §2.1 calls the hero carousel and the night timeline core brand assets and says to
 * port the patterns rather than substitute a static image or a stock slider, so the
 * structures below follow the reference closely on purpose.
 *
 * Two departures from the reference, both operator rules that outrank it:
 *   no eyebrows  — the reference opens every section with a tracked-caps kicker. None
 *                  of them are here. The headline carries the section.
 *   no em dashes — in any copy a member reads.
 */

/* ------------------------------------------------------------------ skip link */

.skip { position: absolute; left: -9999px; background: var(--accent); color: var(--ink); padding: var(--sp-3) var(--sp-4); border-radius: var(--r-pill); font-weight: var(--w-bold); }
.skip:focus { left: var(--sp-4); top: var(--sp-4); z-index: 60; }

/* -------------------------------------------------------------------- starfield
   Seventy 2px dots, drifting in opacity. Fixed, so the page scrolls past the sky
   rather than dragging it along. */

/*
 * Clipped, because a star can land at left: 100%.
 *
 * They are placed at a random percentage and are two pixels wide, so the ones near the
 * right edge hang over it and widen the document. On a phone that is a page which
 * scrolls sideways for decoration nobody can even see.
 */
.stars { position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden; }
.stars i { position: absolute; width: 2px; height: 2px; border-radius: 50%; background: #fff; opacity: .25; animation: twinkle 3.4s ease-in-out infinite; }
@keyframes twinkle { 50% { opacity: .75; } }

/* The accent bloom behind a headline. Not a gradient wash; a light source. */
.glow {
    position: absolute; left: 50%; top: 30%; transform: translate(-50%, -50%);
    width: 560px; height: 560px; border-radius: 50%;
    background: radial-gradient(circle, rgba(var(--accent-rgb), 0.221), transparent 62%);
    filter: blur(6px); animation: pulse 4.5s ease-in-out infinite; pointer-events: none;
}
@keyframes pulse { 50% { transform: translate(-50%, -50%) scale(1.12); opacity: .8; } }

/* --------------------------------------------------------------------- the nav
   A floating pill, not a bar. It sits over the sky rather than cutting it off. */

.nav {
    position: fixed; top: 14px; left: 50%; transform: translateX(-50%); z-index: 40;
    display: flex; align-items: center; gap: var(--sp-5);
    background: rgba(18, 20, 26, .72); backdrop-filter: blur(14px);
    border: 1px solid var(--hairline); border-radius: var(--r-pill);
    padding: 10px 12px 10px 20px; max-width: calc(100vw - 24px);
}

.nav__mark { font-family: var(--disp); font-weight: var(--w-bold); font-size: var(--t-xs); text-transform: uppercase; letter-spacing: -.01em; white-space: nowrap; }
.nav__mark b { color: var(--accent); font-weight: var(--w-bold); }
.nav__links { display: flex; gap: var(--sp-5); }
.nav__links a { font-size: var(--t-sm); font-weight: var(--w-semi); color: var(--tx); opacity: .7; white-space: nowrap; }
.nav__links a:hover { opacity: 1; color: var(--tx); }

.nav__signin { font-size: var(--t-sm); font-weight: var(--w-semi); color: var(--tx); opacity: .7; white-space: nowrap; }
.nav__signin:hover { opacity: 1; color: var(--tx); }

/*
 * One control, not three links, so the switcher costs the nav bar a single slot at
 * every width instead of three. <details> gives the open/close and the
 * click-outside dismissal for free; this only styles the two states.
 */
.locale-switch { position: relative; font-size: var(--t-sm); }
.locale-switch summary {
    cursor: pointer; list-style: none; color: var(--tx); opacity: .7;
    font-weight: var(--w-semi); white-space: nowrap; padding: 4px 2px;
}
.locale-switch summary:hover, .locale-switch[open] summary { opacity: 1; }
.locale-switch summary::-webkit-details-marker { display: none; }
.locale-switch__menu {
    position: absolute; top: calc(100% + 8px); right: 0; z-index: 50;
    background: var(--ink-2); border: 1px solid var(--hairline); border-radius: var(--r-card);
    padding: 6px; display: flex; flex-direction: column; gap: 2px; min-width: 9em;
}
.locale-switch__menu a {
    display: block; padding: 7px 10px; border-radius: var(--r-pill);
    font-size: var(--t-sm); color: var(--tx-2); white-space: nowrap;
}
.locale-switch__menu a:hover { background: rgba(255, 255, 255, .06); color: var(--tx); }
.locale-switch__menu a[aria-current] { color: var(--accent); }

/*
 * The price never breaks across two lines.
 *
 * The bar is capped at the viewport width, so on a narrow phone the button was the
 * thing that gave, and "Start for $25" came apart mid phrase inside a pill built for
 * one line. A call to action that wraps reads as a mistake wherever it happens.
 */
.nav .btn { white-space: nowrap; flex: 0 0 auto; }

/*
 * What a narrow screen drops, in order.
 *
 * The section links go first: they are places to browse and every one of them is
 * reachable from the page underneath. Then the wordmark, because the shield says the
 * same thing in a fifth of the room. Sign in and the price stay at every width, since
 * one is how a member gets back in and the other is why anybody is here.
 */
@media (max-width: 720px) {
    .nav__links { display: none; }
    .nav { gap: var(--sp-4); padding-left: 14px; }

    /*
     * The wordmark goes at the same width as the links, not at 420.
     *
     * 420 was picked for the narrowest phones, which is the wrong reading: an ordinary
     * iPhone is about 430 CSS pixels, so the name stayed on exactly the devices that
     * needed the room, and adding sign in back made the bar tighter than before.
     *
     * The shield says the same thing in a fifth of the space and is still a link home.
     * What is left is the shield, sign in and the price, which is around 220 pixels and
     * fits the narrowest phone made.
     */
    .nav .nav__word { display: none; }

    /*
     * And the shield grows into the space the name left.
     *
     * 1.6em is right for a mark sitting against a wordmark, where the text carries the
     * brand and the shield is punctuation. Alone in a bar this tall it came out
     * seventeen pixels wide and read as nothing at all: the first report of this was
     * simply "no shield", from a phone where it was rendering perfectly and was just
     * too small to see.
     *
     * Fixed pixels rather than em, because it is no longer being sized off anything.
     */
    .nav .mark__shield { height: 28px; }
}

/* ------------------------------------------------------------------- the hero */

.hero { position: relative; z-index: 1; padding: 120px 0 26px; text-align: center; }
.hero h1 { margin: 0 auto 14px; max-width: 900px; padding: 0 var(--sp-5); }
.hero__sub { font-size: clamp(15px, 1.5vw, 18px); max-width: 520px; margin: 0 auto; padding: 0 var(--sp-5); color: var(--tx-2); }
.hero__ctas { display: flex; gap: var(--sp-3); justify-content: center; margin-top: 26px; flex-wrap: wrap; padding: 0 var(--sp-5); }

/* The three facts under the CTA. Divided, never ticked. */
.herofacts { display: flex; gap: 0 var(--sp-4); list-style: none; margin: var(--sp-5) 0 0; padding: 0 var(--sp-5); justify-content: center; flex-wrap: wrap; font-size: var(--t-xs); color: var(--tx-3); }
.herofacts li + li { border-left: 1px solid var(--hairline-2); padding-left: var(--sp-4); }
@media (max-width: 560px) { .herofacts { flex-direction: column; align-items: center; gap: 6px; } .herofacts li + li { border-left: 0; padding-left: 0; } }

/* ====================================================================== SLIDER
   Four beats, each a live UI vignette rather than a screenshot. The active card is
   full opacity and full scale; its neighbours sit back. Animations are keyed off a
   .is-playing class the script stamps on activation, so a card restarts every time
   it comes round rather than playing once on load. */

/*
 * The rail is clipped to the screen.
 *
 * The track is four slides in a flex row, translated sideways to bring each one to the
 * middle, and nothing was cutting it off. So the document was always about four slides
 * wide however narrow the screen: the layout looked correct because the extra width was
 * off to the right where nobody scrolls, and the moment somebody zoomed out it appeared
 * as a page sitting in a column with half the width empty beside it.
 *
 * clip rather than hidden, because hidden on one axis makes the element a scroll
 * container on the other, and this one contains a sticky nothing but sits inside a page
 * whose anchors need to keep working.
 */
.slider { position: relative; margin-top: 48px; padding-bottom: 24px; z-index: 2; overflow-x: clip; }
.track { display: flex; gap: 26px; will-change: transform; transition: transform var(--dur-slow) var(--ease-travel); }

.slide {
    flex: 0 0 var(--slide-w, 720px);
    height: min(56vh, 470px);
    border-radius: var(--r-slide);
    position: relative; overflow: hidden; text-align: left;
    background: var(--grad-slide);
    border: 1px solid rgba(255, 255, 255, .08);
    opacity: .32; transform: scale(.94);
    transition: opacity .6s ease, transform var(--dur-slow) var(--ease-travel);
}
.slide.is-active { opacity: 1; transform: scale(1); box-shadow: var(--lift-dark); }

/* Slide titles are the body voice, per the type system. Display would shout here. */
.slide__t {
    position: absolute; top: 24px; left: 0; right: 0; text-align: center; z-index: 5;
    font-family: var(--body); font-weight: var(--w-semi);
    font-size: clamp(16px, 1.9vw, 22px); color: #EDEBF5; padding: 0 var(--sp-5);
}

/* An app window inside a vignette. 16px, because that is what an app window is. */
.win { position: absolute; border-radius: var(--r-window); box-shadow: 0 24px 60px rgba(0, 0, 0, .5); overflow: hidden; }
.win__tb { height: 26px; display: flex; align-items: center; gap: 5px; padding: 0 11px; }
.win__tb i { width: 8px; height: 8px; border-radius: 50%; }
.win__tb i:nth-child(1) { background: #FF5F57; }
.win__tb i:nth-child(2) { background: #FEBC2E; }
.win__tb i:nth-child(3) { background: #28C840; }
.win--light { background: #F4F3F7; color: #444444; }
.win--light .win__tb { background: #E7E5EE; }

/* Labelled cursors. Accent is the AI, amber is you. That is the whole story of the
   product told in two colours, so the labels are never dropped. */
.cur { position: absolute; z-index: 8; pointer-events: none; filter: drop-shadow(0 4px 10px rgba(0, 0, 0, .4)); }
.cur__tag {
    position: absolute; left: 16px; top: 14px; background: var(--ink); color: var(--accent);
    font-weight: var(--w-bold); font-size: var(--t-xs); border-radius: 9px; padding: 5px 10px; white-space: nowrap;
}
.cur__tag--you { color: var(--hot); }

.ripple { position: absolute; width: 34px; height: 34px; border: 2px solid var(--accent); border-radius: 50%; opacity: 0; z-index: 7; }

/*
 * Vignette parts hide themselves ONLY once the slider has declared it is going to
 * animate them. Default is visible.
 *
 * The earlier version hid them unconditionally and let the keyframes bring them back,
 * which meant anyone with reduced motion turned on, or anyone whose JS failed to run,
 * got four empty cards. A decoration that hides content when it cannot play is not a
 * decoration, it is a broken page.
 */
.slider.is-live .anim { opacity: 0; }
@keyframes enter { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes rip { 0% { opacity: .9; transform: scale(.4); } 100% { opacity: 0; transform: scale(1.6); } }
@keyframes flip { from { opacity: 0; transform: scale(.7); } to { opacity: 1; transform: none; } }

/* --- beat 1: it answers ------------------------------------------------- */
.s1 .phone { width: 225px; left: 7%; top: 82px; background: #1D1D1D; }
.s1 .phone .win__tb { background: rgba(255, 255, 255, .06); }
.s1 .pbody { padding: 15px; text-align: center; }
.s1 .ring { font-family: var(--mono); font-size: 11px; letter-spacing: var(--track-data); color: var(--hot); }
.s1 .caller { font-family: var(--disp); font-weight: var(--w-bold); font-size: 14px; margin: 8px 0 2px; color: #fff; text-transform: uppercase; }
.s1 .num { font-size: var(--t-xs); color: var(--tx-3); }
.s1 .pulse { width: 52px; height: 52px; border-radius: 50%; background: radial-gradient(circle, var(--hot), #B26A00); margin: 12px auto 8px; position: relative; }
.s1 .pulse::after { content: ""; position: absolute; inset: -8px; border-radius: 50%; border: 2px solid var(--hot); animation: ringp 1.1s ease-out infinite; }
@keyframes ringp { from { transform: scale(.7); opacity: .9; } to { transform: scale(1.5); opacity: 0; } }
.s1 .ans { display: inline-block; background: #2ECC71; color: #06230F; font-weight: var(--w-bold); font-size: 12.5px; border-radius: var(--r-pill); padding: 8px 18px; margin-top: 4px; }
.s1 .answered { position: absolute; inset: 26px 0 0 0; background: #1D1D1D; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 0 12px; text-align: center; }
.s1 .answered b { font-family: var(--mono); font-size: 11px; letter-spacing: var(--track-data); color: var(--accent); }
.s1 .answered span { font-size: 11.5px; color: var(--tx-2); }
.s1 .wave { display: flex; align-items: flex-end; gap: 3px; height: 32px; }
.s1 .wave i { width: 5px; background: linear-gradient(180deg, var(--accent), #A33D00); border-radius: 3px; animation: wv .9s ease-in-out infinite; }
.s1 .wave i:nth-child(2n) { animation-delay: .12s; }
.s1 .wave i:nth-child(3n) { animation-delay: .24s; }
@keyframes wv { 0%, 100% { height: 22%; } 50% { height: 100%; } }
.s1 .chat { width: 245px; right: 6%; top: 66px; }
.s1 .cbody { padding: 12px; display: flex; flex-direction: column; gap: 7px; }
.s1 .bub { border-radius: 11px; padding: 7px 10px; font-size: 12.5px; max-width: 88%; background: #E4E1EC; }
.s1 .bub--me { background: var(--ink); color: var(--tx); margin-left: auto; }

.is-playing.s1 .phone { animation: enter .5s .2s both; }
.is-playing.s1 .chat { animation: enter .5s .45s both; }
.is-playing.s1 .b1 { animation: enter .4s .7s both; }
.is-playing.s1 .b2 { animation: enter .4s 1.5s both; }
.is-playing.s1 .b3 { animation: enter .4s 2.6s both; }
.is-playing.s1 .cur1 { animation: cur1move 1.6s 2.2s cubic-bezier(.3, .7, .3, 1) both; }
@keyframes cur1move { 0% { opacity: 0; left: 70%; top: 78%; } 25% { opacity: 1; } 100% { opacity: 1; left: 20%; top: 64%; } }
.is-playing.s1 .rip1 { animation: rip .5s 3.8s both; }
.is-playing.s1 .answered { animation: enter .3s 4.1s both; }

/* --- beat 2: it books --------------------------------------------------- */
.s2 .cal { width: 300px; left: 50%; top: 80px; transform: translateX(-58%); }
.s2 .calb { padding: 14px; }
.s2 .h { font-weight: var(--w-bold); font-size: var(--t-sm); margin-bottom: 9px; color: #444444; }
.s2 .grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.s2 .cell { height: 34px; border-radius: 8px; background: #E7E5EE; font-family: var(--mono); font-size: 9.5px; display: flex; align-items: center; justify-content: center; color: #939393; }
.is-playing.s2 .cell--target { animation: fillcell .01s 2.7s both; }
@keyframes fillcell { to { background: var(--accent); color: var(--accent-ink); font-weight: var(--w-bold); } }
.s2 .toast { width: 238px; right: 6%; bottom: 40px; background: #fff; color: #2A2735; border-radius: 14px; padding: 12px 14px; font-size: 12.5px; }
.s2 .toast b { display: flex; align-items: center; gap: 7px; font-size: var(--t-sm); }
.s2 .toast span { color: #939393; font-size: 11.5px; }
.s2 .ck { width: 18px; height: 18px; border-radius: 50%; background: var(--accent); color: var(--accent-ink); display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: var(--w-black); }
.is-playing.s2 .cal { animation: enter .5s .2s both; }
.is-playing.s2 .cur2 { animation: cur2move 1.8s .9s cubic-bezier(.3, .7, .3, 1) both; }
@keyframes cur2move { 0% { opacity: 0; left: 12%; top: 22%; } 25% { opacity: 1; } 100% { opacity: 1; left: 45%; top: 50%; } }
.is-playing.s2 .rip2 { animation: rip .5s 2.6s both; }
.is-playing.s2 .toast { animation: toastin .55s 3s var(--ease-arrive) both; }
@keyframes toastin { from { opacity: 0; transform: translateY(24px) scale(.9); } to { opacity: 1; transform: none; } }

/* --- beat 3: it follows up ---------------------------------------------- */
.s3 .crm { width: 308px; left: 50%; top: 76px; transform: translateX(-50%); }
.s3 .crmb { padding: 12px; display: flex; flex-direction: column; gap: 8px; }
.s3 .row { display: flex; justify-content: space-between; align-items: center; background: #fff; border: 1px solid #E7E5EE; border-radius: 11px; padding: 9px 11px; font-size: 12.5px; }
.s3 .who { font-weight: var(--w-semi); color: #444444; }
.s3 .who span { display: block; font-family: var(--mono); font-size: 9.5px; color: #939393; font-weight: var(--w-med); }
.s3 .st { font-family: var(--mono); font-weight: var(--w-semi); font-size: 9.5px; letter-spacing: .06em; border-radius: var(--r-pill); padding: 4px 9px; background: #ECEAF2; color: #939393; position: relative; }
.s3 .st b { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; border-radius: var(--r-pill); background: var(--accent); color: var(--accent-ink); opacity: 0; }
.is-playing.s3 .r1 .st b { animation: flip .3s 1.4s both; }
.is-playing.s3 .r2 .st b { animation: flip .3s 2.2s both; }
.is-playing.s3 .r3 .st b { animation: flip .3s 3s both; }
.s3 .fly { position: absolute; background: var(--ink); color: var(--tx); border: 1px solid rgba(255, 255, 255, .14); border-radius: 11px; padding: 8px 11px; font-size: 11.5px; max-width: 190px; }
.is-playing.s3 .fly1 { animation: flyout 1.2s 1.2s ease both; }
.is-playing.s3 .fly2 { animation: flyout 1.2s 2s ease both; }
@keyframes flyout { 0% { opacity: 0; transform: translate(0, 0); } 20% { opacity: 1; } 100% { opacity: 0; transform: translate(120px, -46px); } }
.s3 .cash { position: absolute; right: 9%; bottom: 44px; font-family: var(--disp); font-weight: var(--w-black); font-size: 25px; color: var(--accent); text-shadow: 0 0 26px rgba(var(--accent-rgb), 0.55); }
.is-playing.s3 .crm { animation: enter .5s .2s both; }
.is-playing.s3 .cash { animation: cashin .6s 3.4s var(--ease-arrive) both; }
@keyframes cashin { from { opacity: 0; transform: translateY(18px) scale(.8); } to { opacity: 1; transform: none; } }

/* --- beat 4: we build it with you --------------------------------------- */
.s4 .bld { width: 312px; left: 50%; top: 74px; transform: translateX(-50%); }
.s4 .bb { padding: 13px; }
.s4 .fh { font-weight: var(--w-bold); font-size: var(--t-sm); color: #444444; margin-bottom: 9px; display: flex; justify-content: space-between; align-items: center; }
.s4 .live { font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em; border-radius: var(--r-pill); padding: 4px 10px; background: #ECEAF2; color: #939393; position: relative; }
.s4 .live b { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 5px; border-radius: var(--r-pill); background: var(--accent); color: var(--accent-ink); opacity: 0; }
.s4 .live b::before { content: "●"; font-size: 8px; }
.s4 .fld { display: flex; gap: 8px; align-items: center; background: #fff; border: 1px solid #E7E5EE; border-radius: 10px; padding: 8px 10px; font-size: var(--t-xs); margin-bottom: 7px; color: #444444; }
.s4 .fld u { text-decoration: none; font-family: var(--mono); font-size: 9px; letter-spacing: .08em; color: #939393; min-width: 56px; }
.s4 .chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 9px 0 11px; }
.s4 .schip { font-family: var(--mono); font-size: 9.5px; background: #FFE7D6; color: #7A2D00; border-radius: var(--r-pill); padding: 4px 9px; }
.s4 .appr { display: inline-block; background: var(--ink); color: var(--tx); font-weight: var(--w-bold); font-size: var(--t-xs); border-radius: var(--r-pill); padding: 9px 16px; }
.s4 .evnote { position: absolute; right: 7%; bottom: 46px; background: var(--ink); border: 1px solid rgba(255, 255, 255, .14); color: var(--tx); border-radius: var(--r-chip); padding: 9px 12px; font-size: 11.5px; max-width: 180px; }
.is-playing.s4 .bld { animation: enter .5s .2s both; }
.is-playing.s4 .f1 { animation: enter .35s .6s both; }
.is-playing.s4 .f2 { animation: enter .35s 1s both; }
.is-playing.s4 .f3 { animation: enter .35s 1.4s both; }
.is-playing.s4 .c1 { animation: flip .3s 1.9s both; }
.is-playing.s4 .c2 { animation: flip .3s 2.1s both; }
.is-playing.s4 .c3 { animation: flip .3s 2.3s both; }
.is-playing.s4 .c4 { animation: flip .3s 2.5s both; }
.is-playing.s4 .cur4 { animation: cur4move 1.5s 2.6s cubic-bezier(.3, .7, .3, 1) both; }
@keyframes cur4move { 0% { opacity: 0; left: 76%; top: 24%; } 25% { opacity: 1; } 100% { opacity: 1; left: 44%; top: 72%; } }
.is-playing.s4 .rip4 { animation: rip .5s 4s both; }
.is-playing.s4 .live b { animation: flip .35s 4.3s both; }
.is-playing.s4 .evnote { animation: enter .4s 4.6s both; }

/* --- carousel controls -------------------------------------------------- */
.ctrls { display: flex; align-items: center; justify-content: center; gap: 18px; margin-top: 24px; }
.arrow { width: 44px; height: 44px; border-radius: 50%; border: 1.5px solid var(--hairline-2); background: transparent; color: var(--tx); font-size: 17px; cursor: pointer; transition: border-color var(--dur-fast), color var(--dur-fast); }
.arrow:hover { border-color: var(--accent); color: var(--accent); }
.dots { display: flex; gap: 8px; }
.dot { width: 34px; height: 5px; border-radius: var(--r-pill); background: rgba(255, 255, 255, .14); cursor: pointer; overflow: hidden; position: relative; border: 0; padding: 0; }
.dot i { position: absolute; inset: 0; width: 0; background: var(--accent); border-radius: var(--r-pill); }
.dot.is-on i { animation: prog var(--dur-slide) linear forwards; }
@keyframes prog { to { width: 100%; } }

/* ------------------------------------------------------------------ marquee */

.marq { background: var(--accent); color: var(--ink); overflow: hidden; padding: 13px 0; white-space: nowrap; position: relative; z-index: 2; margin-top: 46px; }
.marq__track { display: inline-block; animation: marq 26s linear infinite; font-family: var(--disp); font-weight: var(--w-bold); font-size: var(--t-sm); letter-spacing: .04em; text-transform: uppercase; }
.marq__track span { margin: 0 22px; }
@keyframes marq { to { transform: translateX(-50%); } }

/* ============================================================ NIGHT TIMELINE
   The clock sticks while the events scroll past it, and it reads whatever event is
   currently in view. The rail fills behind them. */

.night { position: relative; z-index: 1; padding: 120px 20px; }
.night__wrap { max-width: 1040px; margin: 0 auto; display: grid; grid-template-columns: 300px 1fr; gap: 60px; }
@media (max-width: 820px) { .night__wrap { grid-template-columns: 1fr; gap: 20px; } }

.clockbox { position: sticky; top: 22vh; height: max-content; }
@media (max-width: 820px) { .clockbox { position: static; } }
.clock { font-family: var(--disp); font-weight: var(--w-black); font-size: clamp(44px, 5vw, 64px); color: var(--accent); text-shadow: 0 0 40px rgba(var(--accent-rgb), 0.438); font-variant-numeric: tabular-nums; }
.clock small { display: block; font-family: var(--mono); font-weight: var(--w-semi); font-size: var(--t-xs); letter-spacing: .24em; color: var(--tx-3); text-shadow: none; margin-top: 6px; }
.youare { margin-top: 18px; font-size: 14px; color: var(--tx-2); max-width: 240px; }
.youare b { color: var(--tx); }

.events { position: relative; padding-left: 34px; }
.nightrail { position: absolute; left: 8px; top: 0; bottom: 0; width: 2px; background: rgba(255, 255, 255, .1); }
.nightrail i { position: absolute; left: 0; top: 0; width: 2px; height: 0; background: var(--accent); box-shadow: 0 0 12px rgba(var(--accent-rgb), 0.66); }

.ev { position: relative; margin-bottom: 16vh; opacity: .22; transform: translateY(20px); transition: opacity .5s ease, transform .5s ease; }
.ev.is-on { opacity: 1; transform: none; }
.ev::before { content: ""; position: absolute; left: -32px; top: 8px; width: 12px; height: 12px; border-radius: 50%; background: var(--ink); border: 2px solid var(--hairline-2); transition: background .3s, border-color .3s, box-shadow .3s; }
.ev.is-on::before { background: var(--accent); border-color: var(--accent); box-shadow: 0 0 16px rgba(var(--accent-rgb), 0.75); }
.ev__t { font-family: var(--mono); font-weight: var(--w-semi); font-size: var(--t-xs); letter-spacing: .14em; color: var(--accent); }
.ev h3 { margin: 8px 0; }
.ev p { color: #A9ADB5; font-size: var(--t-base); max-width: 440px; }

.evnote { display: inline-block; margin-top: 12px; background: var(--ink-2); border: 1px solid var(--hairline); border-radius: var(--r-chip); padding: 10px 14px; font-size: var(--t-sm); }
.evnote b { color: var(--accent); }
.evnote--hot b { color: var(--hot); }
.sms { background: var(--ink-2); border: 1px solid var(--hairline); border-radius: 14px; padding: 12px 14px; margin-top: 12px; max-width: 380px; font-size: 13.5px; }
.sms__from { font-family: var(--mono); font-size: 10px; letter-spacing: .1em; color: var(--tx-3); margin-bottom: 4px; }

/* ================================================================= LIGHT ROOM
   The morning. A rounded slab of paper dropped into the night. */

.day { background: var(--paper); color: var(--ptx); border-radius: var(--r-light); margin: 0 12px; position: relative; z-index: 2; padding: 120px 22px; }
.day__wrap { max-width: 1040px; margin: 0 auto; }
.day h2 { color: var(--ptx); margin: 0 0 14px; }
.day h2 .hl { background: linear-gradient(120deg, var(--accent), #FF9A3C); color: var(--ptx); padding: 0 10px; border-radius: 10px; text-shadow: none; }
.day .lead { color: var(--ptx-2); font-size: var(--t-md); max-width: 560px; }

.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 44px; }
@media (max-width: 820px) { .grid3 { grid-template-columns: 1fr; } }
.fc { background: var(--paper-card); border: 1.5px solid var(--paper-line); border-radius: var(--r-card); padding: 24px; transition: transform .2s ease, box-shadow .2s ease; }
.fc:hover { transform: translateY(-6px); box-shadow: var(--lift); }
.fc h3 { font-size: var(--t-base); color: var(--ptx); margin-bottom: 6px; }
.fc p { font-size: 14px; color: #6B6E62; }

.counts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-top: 44px; }
@media (max-width: 720px) { .counts { grid-template-columns: 1fr; } }
.count { background: var(--ink); color: var(--tx); border-radius: var(--r-card); padding: 26px; text-align: center; }
.count b { font-family: var(--disp); font-weight: var(--w-black); font-size: clamp(30px, 4vw, 44px); color: var(--accent); display: block; font-variant-numeric: tabular-nums; }
.count span { font-size: var(--t-sm); color: var(--tx-3); }

/* ------------------------------------------------------------------- plans */

.plans { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: 44px; }
@media (max-width: 920px) { .plans { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .plans { grid-template-columns: 1fr; } }
.plan { background: var(--paper-card); border: 1.5px solid var(--paper-line); border-radius: var(--r-card); padding: 22px; display: flex; flex-direction: column; transition: transform .2s ease; }
.plan:hover { transform: translateY(-6px); }
.plan--pop { background: var(--ink); color: var(--tx); border-color: var(--ink); }
.plan h4:not(.plan__name) { font-size: 14px; color: var(--ptx); }
.plan--pop h4:not(.plan__name) { color: var(--tx); }
.plan__pr { font-family: var(--disp); font-weight: var(--w-black); font-size: 32px; margin: 8px 0 2px; color: var(--ptx); }
.plan--pop .plan__pr { color: var(--accent); }
.plan__pr small { font-size: var(--t-xs); font-weight: var(--w-med); font-family: var(--body); opacity: .6; }

/* The monthly, tucked under the one-time figure it belongs to. Quiet, because it is
   the smaller number, but on the card because it is part of the price. */
.plan__sub { font-size: var(--t-xs); color: var(--ptx-3); margin: 0 0 4px; }
.plan--pop .plan__sub { color: var(--tx-3); }

/* What this level has not opened yet, same wording as the ladder on /packages, in the
   quiet caption voice the card already uses for its recurring line. */
.plan__rooms {
    margin: 0 0 14px; padding-top: 12px; border-top: 1px solid var(--paper-line);
    font-size: var(--t-xs); color: var(--ptx-3);
}
.plan--pop .plan__rooms { color: var(--tx-3); border-top-color: var(--ink-3); }
.plan ul { list-style: none; padding: 0; margin: 14px 0 18px; font-size: 13.5px; flex: 1 1 auto; min-height: 0; }
.plan__rooms, .plan .go { flex: 0 0 auto; }
.plan li { padding: 5px 0 5px 18px; position: relative; opacity: .85; }
.plan li::before { content: "\25B8"; position: absolute; left: 0; color: var(--accent-dim); }
.plan--pop li::before { color: var(--accent); }
.plan .go { text-align: center; border-radius: var(--r-pill); padding: 11px; font-weight: var(--w-bold); font-size: 14px; background: #EFEDE2; color: var(--ptx); }
.plan--pop .go { background: var(--accent); color: var(--ink); }
.fine { font-size: 12.5px; color: var(--ptx-3); margin-top: 14px; max-width: var(--measure); }

/* -------------------------------------------------------------- the closer */

.final { position: relative; z-index: 1; text-align: center; padding: 150px 22px 160px; overflow: hidden; }
.final .glow { top: 64%; }
.final h2 { max-width: 800px; margin: 0 auto 18px; }
.final__inner { position: relative; z-index: 2; }

/* ------------------------------------------------------------------ footer */

.foot { position: relative; z-index: 2; border-top: 1px solid var(--hairline); padding: 44px 22px 30px; }
.foot__grid { max-width: 1040px; margin: 0 auto; display: grid; grid-template-columns: 2fr repeat(3, 1fr); gap: 30px; }
@media (max-width: 780px) { .foot__grid { grid-template-columns: 1fr 1fr; } }
.foot__h { font-size: var(--t-xs); color: var(--tx); margin-bottom: 12px; }
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.foot a { color: var(--tx-3); font-size: var(--t-sm); }
.foot a:hover { color: var(--accent); }
.foot__line { color: var(--tx-3); font-size: var(--t-sm); margin-top: 14px; max-width: 34ch; }
.foot__base { max-width: 1040px; margin: 30px auto 0; padding-top: 18px; border-top: 1px solid var(--hairline); color: var(--tx-3); font-size: var(--t-xs); }

/* ----------------------------------------------------------------- reveals */

.rv { opacity: 0; transform: translateY(30px); transition: opacity .7s ease, transform .7s cubic-bezier(.2, .7, .2, 1); }
.rv.is-in { opacity: 1; transform: none; }
.d1 { transition-delay: .08s; } .d2 { transition-delay: .16s; } .d3 { transition-delay: .24s; }

/* ================================================== forms, auth and checkout
   Same tokens, quieter. These pages are a person typing, not a person deciding. */

/*
 * Interior pages, the doorway and checkout. Display type comes down from its landing
 * page scale: a person on these screens has already decided, and a 68px headline over
 * a payment form reads as a page still trying to sell them something.
 */
.pagehead { position: relative; z-index: 1; padding: 140px 0 0; }
.pagehead h1 { max-width: 18ch; font-size: clamp(26px, 4vw, 44px); }
.pagehead + .section h2,
.section h2 { font-size: clamp(19px, 2.4vw, 28px); }
.pagehead .lead { margin-top: 18px; }

/*
 * The one page whose headline is allowed to be the loudest thing on it.
 *
 * Every other page head is set small and ranged left, because it is a signpost above the
 * content. This one is the content: it is the whole pricing argument in two lines, and a
 * visitor who reads nothing else should still leave knowing there is one product and that
 * how deep you go is up to you. So it gets the full display size, set across the measure
 * rather than boxed to 18 characters, with the half of the sentence that is the actual
 * news carrying the accent.
 */
.pagehead--display h1 {
    max-width: none;
    /*
     * Sized off the column, not the window.
     *
     * Both lines are deliberately the same length, so one size fills them both. Measuring
     * it against the viewport gets that wrong the moment the column stops growing with
     * the window: past that point the type keeps getting bigger against a measure that
     * does not, and the second line falls in half. Against the column itself the ratio
     * holds at every width, and the break stays where the copy puts it.
     */
    font-size: clamp(22px, 4.55cqi, 68px);
    text-transform: uppercase;
    line-height: 1.02;
    letter-spacing: -.025em;
}
.pagehead--display .wrap { container-type: inline-size; }
.pagehead--display h1 span { color: var(--accent); }
/*
 * The standard lead is capped at a comfortable reading measure, which is right for a
 * paragraph and wrong for this one: it is a single sentence sitting directly under a
 * two-line headline, and breaking it in half gives the eye a third line to read where
 * there should be one. The column is the cap here.
 */
.pagehead--centred .section__lead { margin-left: auto; margin-right: auto; }
.pagehead--display .section__lead { max-width: none; }
.section { position: relative; z-index: 1; padding: var(--sp-8) 0; }
.section__lead { color: var(--tx-2); font-size: var(--t-md); max-width: 50ch; margin-top: 14px; }
/* The mark sits with the wordmark, sized off it rather than in pixels, so the two stay
   in proportion at every breakpoint. Height drives it and width follows, because the
   shield is taller than it is wide and a square box would letterbox it. */
.nav__mark { display: inline-flex; align-items: center; gap: .5em; }
.mark__shield { height: 1.6em; width: auto; flex: none; }

.pageaction { margin-top: var(--sp-7); }
.pageaction--minor { margin-top: var(--sp-4); color: var(--tx-2); font-size: var(--t-sm); }

.form { max-width: 460px; margin-top: var(--sp-6); }
.form--inline { display: flex; gap: var(--sp-3); align-items: flex-end; max-width: 640px; }
.form--inline .field { flex: 1; margin-bottom: 0; }
.field { margin-bottom: var(--sp-5); }

/* Same shape as admin.css's .tick, kept in its own stylesheet because public pages
   and the member backoffice never load each other's CSS. Used where a person must
   read something before what happens next depends on it, rather than a preference
   toggle -- the guidelines acknowledgment at checkout, not a settings switch. */
.tick { display: flex; align-items: flex-start; gap: var(--sp-3); padding: var(--sp-3) 0; cursor: pointer; font-size: var(--t-sm); color: var(--tx-2); line-height: 1.45; margin-bottom: var(--sp-4); }
.tick input { flex: none; margin-top: 3px; width: 16px; height: 16px; accent-color: var(--accent); }
.tick:hover { color: var(--tx); }

/* An invited registration's acknowledgment: the plan in a scrolling panel, then the
   two statements. Bordered because it is the one part of this form that is a record. */
.ack { border-top: 1px solid var(--hairline); margin-top: var(--sp-6); padding-top: var(--sp-6); }
.ack__h { font-size: var(--t-lg); margin: 0 0 var(--sp-3); }
.ack__intro { color: var(--tx-2); margin: 0 0 var(--sp-5); max-width: 60ch; }
.planbox { max-height: 26rem; overflow-y: auto; border: 1px solid var(--hairline); border-radius: 12px; padding: var(--sp-5); background: var(--ink-2); }
.planbox:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ack__links { display: flex; gap: var(--sp-3); flex-wrap: wrap; font-size: var(--t-sm); margin: var(--sp-3) 0 var(--sp-5); }
.tick input:checked + span { color: var(--tx); }
.field--split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
@media (max-width: 520px) { .field--split { grid-template-columns: 1fr; } }
.field label { display: block; font-size: var(--t-sm); font-weight: var(--w-semi); margin-bottom: 6px; }
.field input, .field select, .field textarea {
    width: 100%; padding: 13px 16px; background: var(--ink-3); border: 1px solid var(--hairline-2);
    border-radius: var(--r-chip); color: var(--tx); font: inherit; font-size: var(--t-base);
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--accent); outline: none; }
.field input::placeholder { color: var(--tx-3); }
.fieldlabel { font-size: var(--t-xs); color: var(--tx-3); margin-bottom: 4px; }
.field__optional { color: var(--tx-3); font-weight: var(--w-med); }
.blockhead { font-size: var(--t-md); margin-bottom: var(--sp-4); }

.line { display: flex; justify-content: space-between; gap: var(--sp-5); padding: var(--sp-3) 0; border-bottom: 1px solid var(--hairline); font-size: var(--t-base); }
.line--total { border-bottom: 0; font-weight: var(--w-bold); }
.line--total .money { font-size: var(--t-lg); color: var(--accent); }

.notice { border: 1px solid var(--hairline); border-left: 3px solid var(--accent); background: var(--ink-2); border-radius: 0 var(--r-chip) var(--r-chip) 0; padding: var(--sp-4); margin-bottom: var(--sp-5); font-size: var(--t-sm); color: var(--tx-2); }
.alarm { border: 1px solid var(--danger); border-left-width: 3px; background: rgba(var(--danger-rgb), .09); border-radius: 0 var(--r-chip) var(--r-chip) 0; padding: var(--sp-4); margin-bottom: var(--sp-5); }
.draft-note { border: 1px solid var(--hairline); border-left: 3px solid var(--hot); background: var(--ink-2); border-radius: 0 var(--r-chip) var(--r-chip) 0; padding: var(--sp-4); margin-bottom: var(--sp-6); }
.draft-note p { font-size: var(--t-sm); color: var(--tx-2); }

.wrap--narrow h2 { margin-top: var(--sp-7); font-size: var(--t-xl); }
.wrap--narrow p { margin-bottom: var(--sp-4); color: var(--tx-2); }

/* ===================================================== the packages page
   Four tiers as product plans. The plan cards on the home page are a summary;
   these carry the full cumulative feature list, so they sit on ink rather than
   in the light room and get room to breathe. */

/* Four cards that are genuinely one table.
   align-items: start was stopping them stretching, so each box ended wherever its
   own copy ran out and the row read as four unrelated things. */
.tiers { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: auto; gap: 14px; margin-top: 44px; }
@media (max-width: 1040px) { .tiers { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .tiers { grid-template-columns: 1fr; } }

/*
 * Four cards that read as one table.
 *
 * Equal height is the easy half and not the half that shows. What an eye comparing four
 * prices notices is one card's price sitting a line lower than its neighbour's, and that
 * comes from a band above it wrapping to two lines instead of one.
 *
 * So the bands are made to match and the list absorbs the difference. The list is the one
 * band that can afford to: it is a list, and a gap under the last item reads as nothing at
 * all, whereas a gap under a price reads as a mistake.
 *
 * Tried subgrid first, which is the right tool and would align every band without any of
 * the below. It reported as supported and then sized each card's rows from its own content
 * anyway, so this is the version that demonstrably works.
 */
.tier {
    background: var(--ink-2);
    border: 1px solid var(--hairline);
    border-radius: var(--r-card);
    padding: var(--sp-6) var(--sp-5);
    display: flex; flex-direction: column; gap: var(--sp-4);
}

/*
 * Room for two lines, in em so it tracks the type rather than a pixel guess.
 *
 * The first card has no "already set up X?" sentence, because there is nothing below it
 * to have set up, so its breakdown is one line while the other three are two. Left alone
 * that pushes everything under it up by a line on one card out of four.
 */
/*
 * The names are deliberately different sizes, so their band has to be one height.
 *
 * Each step name is sized to fill its own card, which is what makes the row look
 * designed rather than defaulted. The cost is that "MY SELF" at its fill size has a
 * taller line box than "MY WORDS" at its, and everything underneath inherits the
 * difference: four prices that should be a column end up on four different lines.
 *
 * So the band is fixed at the tallest name's line box and the names sit on its floor.
 * Measured in cqi like the names themselves, and the cards are all the same width, so
 * one value is the same number of pixels in each of them. The tallest is MY SELF at
 * 17.18cqi against a .95 line height.
 */
.tier__name {
    min-height: 16.4cqi;
    display: flex;
    align-items: flex-end;
}

/*
 * Measured at four across, which is the tightest the cards ever get before the grid
 * drops to two. That is the worst case for wrapping, so a band sized for it is a band
 * that holds at every wider layout too: the copy needs fewer lines as the cards grow
 * and the minimum takes over.
 *
 * The alternative is a pixel guess that happens to look right on the screen it was
 * written on, which is how a pricing table ends up misaligned on somebody else's.
 */
.tier__summary   { min-height: 7.8em; }
.tier__breakdown { min-height: 7.6em; }

/* The slack goes here, which pins the rooms line and the button to the bottom of every
   card in the row no matter how many things a level opens. */
/*
 * Grows into the slack, but starts from its own content.
 *
 * With a zero basis the card's natural height is worked out as though the list were not
 * there, so the grid row can end up shorter than the longest list needs; that list then
 * refuses to shrink and shoves the rooms line and the button down in that one card. From
 * content, the row is sized honestly by the tallest card and every list absorbs whatever
 * is left over, which is what puts the buttons on one line.
 */
.tier__list { flex: 1 1 auto; min-height: 0; }

/*
 * Everything below the list keeps its natural height.
 *
 * The card's height is set by the grid row, and the row comes out a few pixels short of
 * what the longest card wants: the name band is measured in container-query units, which
 * cannot be resolved while the browser is still working out how wide the card is, so the
 * intrinsic pass undercounts it. Those few pixels have to come off something. Left to
 * itself the browser took them off the button, which is the one band where three pixels
 * are visible as a button that does not match the three beside it. Pinned here, the list
 * gives them up instead, inside a gap where nothing can be seen to move.
 */
.tier__rooms,
.tier__go { flex: 0 0 auto; }
}

/* The one people start with. One accent edge on the page, not four. */
.tier--first { border-color: var(--accent); background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.102), transparent 55%); }

/*
 * Already theirs. Quieter than "first", not louder: a card with nothing left to do on
 * it should recede next to the one still asking for a decision, not compete with it.
 */
.tier--owned { opacity: .74; }
.tier__total--owned { color: var(--accent-dim); }
.tier__go--owned { min-height: 0; }

.tier__head { display: flex; flex-direction: column; gap: var(--sp-2); }
.tier__summary { color: var(--tx-2); font-size: var(--t-sm); }

/*
 * The role line sits UNDER the name, deliberately.
 *
 * Above it is where .tier__brand already is, and two tracked-caps lines stacked over
 * a headline is the eyebrow pattern this site does not use. So this one reads as a
 * caption to the name rather than a label above it: sentence case, no tracking, and
 * the accent it borrows is the same one the noun in the name already carries, which
 * ties the two lines together instead of introducing a third colour.
 */
.tier__role, .plan__role {
    font-size: var(--t-sm);
    font-weight: var(--w-bold);
}

/*
 * Same ground rule as the name above it: the packages cards are ink so plain accent
 * reads, the home cards are paper where it does not, and --accent-ptx is the version
 * that survives there. The one dark card in the home row goes back to the dark
 * treatment, exactly as .plan--pop .plan__name span does.
 */
.tier__role            { color: var(--accent); }
.plan__role            { color: var(--accent-ptx); }
.plan--pop .plan__role { color: var(--accent); }

/*
 * The caption sits under the number, not beside it.
 *
 * Beside it, the caption gets whatever width the number leaves over, so "$25" and
 * "$1,625" hand it two different amounts of room and it wraps to a different number of
 * lines in each card. That alone threw the four cards out of step by up to two lines,
 * and no amount of minimum height below it could put them back.
 */
.tier__price { display: flex; flex-direction: column; gap: 4px; margin-top: var(--sp-3); }
.tier__total {
    font-family: var(--disp); font-weight: var(--w-black);
    font-size: clamp(26px, 3vw, 34px); letter-spacing: -.04em; line-height: 1;
    font-variant-numeric: tabular-nums;
}
.tier--first .tier__total { color: var(--accent); }
.tier__unit { font-size: var(--t-xs); color: var(--tx-3); }
.tier__monthly { font-size: var(--t-sm); color: var(--tx-2); }

/* The number actually charged on day one, said out loud rather than in a footnote. */
.tier__breakdown { font-size: var(--t-xs); color: var(--tx-3); line-height: 1.5; }

.tier__carries { font-size: var(--t-xs); color: var(--tx-3); padding-top: var(--sp-3); border-top: 1px solid var(--hairline); }

.tier__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); font-size: var(--t-sm); color: var(--tx-2); }
.tier__list li { padding-left: 18px; position: relative; }
.tier__list li::before { content: "\25B8"; position: absolute; left: 0; color: var(--accent-dim); }

/* --------------------------------------------------------------- the catch
   Naming the hard part is a brand pillar, so it gets a rule of its own rather
   than being buried in a paragraph. */

.catch { border-left: 2px solid var(--hot); padding-left: var(--sp-5); margin-top: var(--sp-8); max-width: 60ch; }
.catch p { font-size: var(--t-md); line-height: 1.5; color: var(--tx); }

.field__hint { font-size: var(--t-xs); color: var(--tx-3); margin-top: 6px; }

/* ================================================== CHECKOUT AND THE DOORWAY
 *
 * The quietest surfaces on the platform, deliberately. A person here has already
 * decided; the job is to take their money without making them wonder what they just
 * agreed to. So: one accent action per screen, the real number stated with its cents,
 * and no motion at all.
 */

/* ------------------------------------------------------------- radio cards
   A whole card is the hit target, not a 14px circle beside a label. The native
   input stays in the DOM for keyboard and screen readers and is drawn as a ring
   on the card itself. */

.choice {
    display: flex; align-items: center; gap: var(--sp-4);
    background: var(--ink-2);
    border: 1.5px solid var(--hairline);
    border-radius: var(--r-card);
    padding: var(--sp-5);
    margin-bottom: var(--sp-3);
    cursor: pointer;
    transition: border-color var(--dur-fast), background var(--dur-fast);
}

.choice:hover { border-color: var(--hairline-2); }

.choice input {
    appearance: none; -webkit-appearance: none;
    width: 20px; height: 20px; flex: 0 0 auto; margin: 0;
    border: 2px solid var(--hairline-2); border-radius: 50%;
    background: transparent; cursor: pointer;
    transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
}

.choice input:checked { border-color: var(--accent); box-shadow: inset 0 0 0 4px var(--accent); }

/* :has lets the card react to its own input. Where it is unsupported the card simply
   does not light up, which is a missing flourish rather than a broken form. */
.choice:has(input:checked) { border-color: var(--accent); background: rgba(var(--accent-rgb), 0.085); }
.choice:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 3px; }

.choice--tight { padding: var(--sp-4) var(--sp-5); }

.choice__body { flex: 1; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.choice__title { font-weight: var(--w-bold); font-size: var(--t-md); }
.choice__desc { color: var(--tx-2); font-size: var(--t-sm); }

.choice__price { text-align: right; flex: 0 0 auto; display: flex; flex-direction: column; gap: 2px; }
.choice__amount {
    font-family: var(--disp); font-weight: var(--w-black);
    font-size: var(--t-xl); letter-spacing: -.03em; line-height: 1;
    font-variant-numeric: tabular-nums;
}
.choice:has(input:checked) .choice__amount { color: var(--accent); }
.choice__unit { font-family: var(--mono); font-size: var(--t-xs); color: var(--tx-3); }

@media (max-width: 560px) {
    .choice { flex-wrap: wrap; }
    .choice__price { text-align: left; width: 100%; flex-direction: row; align-items: baseline; gap: var(--sp-2); }
}

.form--wide { max-width: 720px; }
.subline { color: var(--tx-2); font-size: var(--t-sm); margin-top: var(--sp-4); max-width: 60ch; }

/* --------------------------------------------------------------- receipts
   Cents always. This is the one place on the platform where a rounded price
   would be a lie about what is being charged. */

.receipt {
    background: var(--ink-2);
    border: 1px solid var(--hairline);
    border-radius: var(--r-card);
    padding: var(--sp-6);
    margin-top: var(--sp-5);
    max-width: 480px;
}

.receipt--light { background: var(--ink-3); }
.receipt__after { color: var(--tx-3); font-size: var(--t-sm); margin-top: var(--sp-4); }

/* ------------------------------------------------- the earning opt-in step
   §2.3 step 6, and the legal disclosure point the public site deliberately
   omits. It is a wall of plain text on purpose, and neither answer is
   pre-selected or styled to look like the expected one. */

.planbox {
    background: var(--ink-2);
    border: 1px solid var(--hairline);
    border-radius: var(--r-card);
    padding: var(--sp-3) var(--sp-5);
    margin: var(--sp-4) 0 var(--sp-6);
    max-width: 560px;
}

.planrow {
    display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-4);
    padding: var(--sp-3) 0;
    border-bottom: 1px solid var(--hairline);
    font-size: var(--t-sm);
}
.planrow:last-child { border-bottom: 0; }

/* Two buttons of equal weight. Declining is a real choice (C5), so it is not
   dressed as the smaller one. */
.decision { display: flex; gap: var(--sp-3); flex-wrap: wrap; margin-top: var(--sp-6); }

/* --------------------------------------------------------- the doorway */

/*
 * Scoped through .wrap on purpose, and not with !important.
 *
 * `.wrap--narrow p` sets body copy to the muted colour and scores 0,1,1. A bare
 * `.field__error` scores 0,1,0 and loses, so every validation message on every narrow
 * page rendered in exactly the same grey as the hint text underneath it. The error was
 * always there and never looked like one.
 *
 * That is what made a failed signup read as "the form did nothing": the message was
 * below the fold AND the same colour as the help text when you got to it.
 */
.wrap .form__error,
.wrap .field__error {
    color: var(--danger);
    font-size: var(--t-sm);
    margin-top: 6px;
}

.form__error {
    border: 1px solid var(--danger);
    border-left-width: 3px;
    background: rgba(var(--danger-rgb), .07);
    border-radius: 0 var(--r-chip) var(--r-chip) 0;
    padding: var(--sp-3) var(--sp-4);
    margin: 0 0 var(--sp-5);
    color: var(--tx);
}

/* Six digits, spaced out, in the data voice. Nobody mistypes their code twice. */
.input--code {
    font-family: var(--mono);
    font-size: 28px;
    font-weight: var(--w-semi);
    letter-spacing: .32em;
    text-align: center;
    padding: var(--sp-4);
}

.sponsor-lock {
    background: var(--ink-3);
    border: 1px solid var(--hairline);
    border-radius: var(--r-chip);
    padding: var(--sp-3) var(--sp-4);
    margin-bottom: var(--sp-5);
    font-size: var(--t-sm);
}
.sponsor-lock b { color: var(--accent); }

.linkbutton {
    background: none; border: 0; padding: 0;
    color: var(--accent); font: inherit; font-size: var(--t-sm);
    cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
}

/* Only ever rendered when CI_ENVIRONMENT is development. Amber so nobody ships
   a build with it showing and mistakes it for a real message. */
.dev-banner {
    border: 1px dashed var(--hot);
    border-radius: var(--r-chip);
    background: rgba(var(--hot-rgb), .07);
    color: var(--hot);
    padding: var(--sp-3) var(--sp-4);
    margin-bottom: var(--sp-5);
    font-family: var(--mono);
    font-size: var(--t-sm);
}

/* The summary above a form that came back with problems. Links jump to the field. */
.wrap .form__error p { margin: 0; color: var(--danger); }
.form__error ul { margin: var(--sp-2) 0 0; padding-left: 1.1em; }
.form__error li + li { margin-top: 3px; }
.form__error a { color: var(--danger); text-decoration: underline; text-underline-offset: 2px; }
.form__error a:hover { color: var(--tx); }

/* A field jumped to from that summary should be obvious once you land on it. */
.field :target { outline: 2px solid var(--danger); outline-offset: 3px; border-radius: var(--r-chip); }

/* One button per pricing card. The subgrid above is what lines them up now; this
   rule set the card to flex a second time, 230 lines after it was already set to
   grid, and the later one silently won. */
.tier__go { display: block; text-align: center; margin-top: var(--sp-2); }

/* ------------------------------------------------- the four steps, named
   "Go E1U" above in small bold grey, then the step: MY in white, the noun
   in accent. The noun is what the eye should land on, so it is the only accent.

   Each title fills its line exactly, at every width, and that is arithmetic
   rather than a guess. A string set in a given face has a fixed width in ems:
   "MY WORDS" in Unbounded 900 is 7.406em, "MY SELF" only 5.645em. Divide the
   container width by that number and you get the font size at which the string
   is precisely as wide as its box. So the rule is one calc and the only thing
   that changes per step is how wide its own name happens to be.

   cqi and not vw, because a card is a column of a grid that reflows from four
   across to two to one. Its width and the window's width are different stories,
   and only the card's own width can promise the line will not break.

   The 97 is three percent of headroom for a fallback face or subpixel rounding.
   nowrap is the backstop, not the mechanism: if a name ever grows a third word
   the answer is a new measurement here, and the overflow will say so loudly.

   To re-measure after a font change: render the name at font-size 100px in the
   real face and divide the resulting pixel width by 100. */

.tier, .plan { container-type: inline-size; }

.tier__brand, .plan__brand {
    font-family: var(--mono);
    font-weight: var(--w-bold);
    font-size: var(--t-xs);
    letter-spacing: .2em;
    text-transform: uppercase;
    margin-bottom: 4px;
}

.tier__brand { color: var(--tx-3); }
.plan__brand { color: var(--ptx-3); }
.plan--pop .plan__brand { color: var(--tx-3); }

.tier__name, .plan__name {
    font-family: var(--disp);
    font-weight: var(--w-black);
    text-transform: uppercase;
    line-height: .95;
    letter-spacing: -.02em;
    white-space: nowrap;
    font-size: var(--name-fit, 13.1cqi);
}

/*
 * MY stays quiet, the noun carries the colour. Which colour depends on the ground
 * it is standing on.
 *
 * The packages cards are ink, so it is white and accent as the operator specified.
 * Three of the four home cards are paper, where white is very nearly invisible and
 * accent on near-white is barely a colour at all. The brand already answers this: --ptx
 * is the ink used for text on paper, and --accent-ptx exists precisely because accent does
 * not survive there. Same idea, same hierarchy, legible on both grounds.
 */
.tier__name        { color: var(--tx); }
.tier__name span   { color: var(--accent); }

.plan__name        { color: var(--ptx); }
.plan__name span   { color: var(--accent-ptx); }

/* The one dark card in that row goes back to the dark treatment. */
.plan--pop .plan__name      { color: var(--tx); }
.plan--pop .plan__name span { color: var(--accent); }

/* One number per step, not a division done at render time.
   97 divided by the name's width in ems, which is the font size, expressed as a
   percentage of the card, at which the string is exactly as wide as its box.
   Worked out here rather than in a calc() because a stylesheet that computes the
   answer is one more thing that can be dropped as invalid and fall silently back
   to whatever came before it, which is precisely what happened. */
.tier--t1, .plan--t1 { --name-fit: 13.10cqi; }   /* MY WORDS, 7.406em */
.tier--t2, .plan--t2 { --name-fit: 15.19cqi; }   /* MY VOICE, 6.384em */
.tier--t3, .plan--t3 { --name-fit: 14.02cqi; }   /* MY REACH, 6.919em */
.tier--t4, .plan--t4 { --name-fit: 17.18cqi; }   /* MY SELF,  5.645em */

/* ------------------------------------------------- paying in bitcoin
   Three facts in the order somebody with a wallet open needs them: how much,
   where to, how long. Everything else on the page is subordinate. */

.paystate { margin-bottom: var(--sp-6); }

/* One block visible at a time, chosen by the server's answer. Hidden by default so
   a page that never gets its state, because script is off or a poll failed, still
   shows the state it was rendered with rather than all four at once. */
.paystate__banner { display: none; padding: var(--sp-5); border-radius: var(--r-card); border: 1px solid var(--hairline); border-left-width: 3px; background: var(--ink-2); font-size: var(--t-sm); }
.paystate[data-state="waiting"] [data-when="waiting"],
.paystate[data-state="seen"]    [data-when="seen"],
.paystate[data-state="paid"]    [data-when="paid"],
.paystate[data-state="expired"] [data-when="expired"] { display: block; }

.paystate__banner { border-left-color: var(--hot); }
.paystate__banner--seen { border-left-color: var(--accent); }
.paystate__banner--paid { border-left-color: var(--accent); background: rgba(var(--accent-rgb), 0.119); }
.paystate__banner--expired { border-left-color: var(--danger); background: rgba(var(--danger-rgb), .06); }

.paystate__clock { display: block; margin-top: var(--sp-2); font-family: var(--mono); color: var(--tx-3); font-size: var(--t-xs); }
.paystate__banner form { margin-top: var(--sp-4); }

/* One centred column. The order down the page is the order somebody does it in:
   scan or copy, check the amount, check the address. */
.pay { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--sp-5); }

.pay__qr { display: block; width: 260px; height: 260px; border-radius: var(--r-chip); background: #fff; padding: 10px; }
.pay__hint { margin: 0; font-size: var(--t-xs); color: var(--tx-3); }

.pay__amount, .pay__address { width: 100%; }

/* Prose stays narrow even when it is centred. Centred text that runs the full width
   of a card is the hardest kind to read, because the eye loses where the next line
   starts on every single line rather than once. */
.pay__note { font-size: var(--t-xs); color: var(--tx-3); max-width: 48ch; margin: var(--sp-3) auto 0; }

.pay .fieldlabel { margin-bottom: 4px; }
.pay .btn { margin-top: var(--sp-4); }

/* The other-coin button sits UNDER Copy the address rather than beside it. Buttons here
   are inline-block, so without this they pair up on one row and read as two equal
   choices -- and they are not. Copying the address is what somebody on this page came to
   do; this is the way out for somebody who cannot use it. */
.pay__other { display: block; width: fit-content; margin-left: auto; margin-right: auto; }

.pagehead--centred { text-align: center; }

/* The h1 needs the auto margins too, not just the centred text.
   .pagehead h1 caps itself at 18ch so a long headline breaks somewhere sensible, which
   makes it a block narrower than the column it sits in. text-align only centres the
   words INSIDE that block, and the block itself stayed hard against the left -- so on
   every centred page the headline sat a few dozen pixels left of the lead underneath
   it, close enough to read as sloppy rather than as a bug. */
.pagehead--centred h1 { margin-left: auto; margin-right: auto; }
.pagehead--centred .lead { margin-left: auto; margin-right: auto; }

/* An address is one long word. It wraps anywhere rather than pushing the page
   sideways, and it is never truncated: this is the screen where the whole string
   matters more than the layout. */
.keyline { font-family: var(--mono); font-size: var(--t-sm); color: var(--tx); overflow-wrap: anywhere; letter-spacing: .02em; }
.keyline--big { font-size: var(--t-md); font-weight: var(--w-semi); }

/* What is on the order, itemised and centred with the rest of the payment column.
   Each item is a name, its price, and one line saying what kind of charge it is,
/* What is on the order: name, what kind of charge it is, price.
   A receipt line, which is a shape people already know how to read. The block is
   centred on the page and its rows are not, because a price column only works if
   the figures line up under each other. */
.bought { list-style: none; margin: var(--sp-6) auto 0; padding: 0; max-width: 34rem; text-align: left; }

.bought__item {
    display: grid;
    grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
    align-items: baseline;
    gap: var(--sp-3) var(--sp-4);
    padding: var(--sp-4) 0;
    border-bottom: 1px solid var(--hairline);
}
.bought__item:first-child { border-top: 1px solid var(--hairline); }

/* Placed explicitly rather than left to source order.
   The two layouts want different orders from the same markup: wide reads name,
   description, price across; narrow wants the name and its price together on one
   line with the description underneath. Auto placement can only give one of those,
   and it silently gave a third thing: the price on a row of its own. */
.bought__what  { grid-column: 1; font-size: var(--t-base); color: var(--tx-2); }
.bought__what strong { color: var(--tx); font-weight: var(--w-bold); }
.bought__note  { grid-column: 2; font-size: var(--t-xs); color: var(--tx-3); }

/* Tabular figures, or the decimal points wander between rows and the column stops
   reading as a column. */
.bought__price { grid-column: 3; font-weight: var(--w-bold); color: var(--tx); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Narrow: the name and the price keep each other company on one line and the
   description drops underneath, rather than three things fighting over 320px. */
@media (max-width: 560px) {
    .bought__item { grid-template-columns: minmax(0, 1fr) auto; }
    .bought__what  { grid-column: 1; grid-row: 1; }
    .bought__price { grid-column: 2; grid-row: 1; }
    .bought__note  { grid-column: 1 / -1; grid-row: 2; }
}

.bought__total {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: var(--sp-4);
    max-width: 34rem; margin: var(--sp-5) auto 0;
    text-align: left;
    font-size: var(--t-md); color: var(--tx-2);
}
.bought__total .money { font-family: var(--disp); font-weight: var(--w-black); font-size: var(--t-xl); color: var(--accent); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------- the workspace, then the setups
   The product first, at the size of a product, then the four depths of setup under
   it. One accent edge on the page belongs to the workspace, because that is the thing
   somebody is actually subscribing to. */

.workspace-card {
    display: grid;
    grid-template-columns: 1.3fr 1fr;
    gap: var(--sp-7);
    align-items: start;
    background: linear-gradient(160deg, var(--ink-2), var(--ink));
    border: 1px solid rgba(var(--accent-rgb), 0.425);
    border-radius: var(--r-card);
    padding: var(--sp-6) var(--sp-7);
    container-type: inline-size;
}
@media (max-width: 820px) { .workspace-card { grid-template-columns: 1fr; gap: var(--sp-5); padding: var(--sp-5); } }

/* Sized off the card like the step names, so the product reads as the biggest thing
   on the page at any width without a media query per breakpoint. */
/* Set exactly like the step names: brand above in grey, first word white, second
   accent, and sized to fill its own column on one line.

   "AI WORKSPACE" is 9.947em wide in Unbounded 900, so 97cqi divided by that is the
   size at which it is as wide as the box. Measured the same way as the four step
   names, and worth keeping in step with them: this card and those four are one
   family and a different sizing rule would show. */
.workspace-card__name {
    font-family: var(--disp); font-weight: var(--w-black); text-transform: uppercase;
    line-height: .98; letter-spacing: -.02em; color: var(--tx);
    white-space: nowrap;
    font-size: 9.75cqi;
    margin-bottom: var(--sp-4);
}
.workspace-card__name span { color: var(--accent); }

.workspace-card__lead  { color: var(--tx-2); font-size: var(--t-base); max-width: 52ch; }
.workspace-card__pause {
    margin-top: var(--sp-5); padding-top: var(--sp-4);
    border-top: 1px dashed var(--hairline);
    color: var(--tx-3); font-size: var(--t-sm); max-width: 52ch;
}

.workspace-card__figure {
    font-family: var(--disp); font-weight: var(--w-black);
    font-size: clamp(34px, 9cqi, 52px); color: var(--accent); line-height: 1;
}
.workspace-card__figure small { font-family: var(--body); font-weight: var(--w-med); font-size: var(--t-sm); color: var(--tx-3); }

/* The workspace's list is the same list as a setup card's. It used a class that
   only exists in the member stylesheet, which this page does not load, so it fell
   back to browser default bullets. */
.workspace-card .tier__list { margin-top: var(--sp-4); }

/*
 * The setup levels sit right under the workspace box, not a screen below it.
 *
 * Two sections' worth of padding plus this margin put nearly two hundred pixels between
 * the product and the four ways to set it up, which reads as two unrelated pages stacked.
 * They are one argument: here is the thing, here is how deep we build it. Closing the gap
 * is what makes the second half read as the answer to the first.
 */
.setup-head { margin-top: 20px; text-align: center; }

/* Centred under a centred page head, so the whole column reads on one axis. */
.setup-head__lead { margin-left: auto; margin-right: auto; text-align: center; max-width: 66ch; }
.section--flush-bottom { padding-bottom: 0; }
.section--flush-top { padding-top: 0; }
.setup-head__lead { margin-bottom: var(--sp-6); }

/* What this level has not opened yet. Named rather than hidden, so a visitor can see
   the product goes further than the part they are looking at. */
.tier__rooms {
    margin-top: var(--sp-4); padding-top: var(--sp-4);
    border-top: 1px solid var(--hairline);
    font-family: var(--mono); font-size: var(--t-xs); letter-spacing: .06em;
    color: var(--hot);
    /* "Still locked: Voice · Reach · Studio" wraps to two lines and "Every room open"
       does not, which was the last thing knocking the buttons out of line. */
    min-height: 4.6em;
}

/*
 * The brand line sits directly under the wordmark and above the line about who runs
 * the place, so it reads as what the company says about itself before the aside about
 * how it is run. Slightly heavier than the line below it and no larger: it is a
 * tagline, not a heading, and the wordmark above is already doing the shouting.
 */
.foot__line--brand {
    font-weight: var(--w-bold);
    margin-bottom: var(--sp-2);
}

/* ==================================================== the AI Profit System funnel
 *
 * Built to the design handoff of 28 August 2026, options 2a and 2b. Values here are
 * measured from that prototype rather than chosen, which is why they are oddly
 * specific: 13.5px, 12.5px, 4px 6px 4px 14px. Rounding them is a change, not a
 * tidy-up.
 *
 * Everything is prefixed fp-- "Future Proof" -- because these two surfaces present
 * unbranded. Go E1U is named as the platform being joined, not as the publisher.
 */

.fp { max-width: 1180px; margin: 0 auto; color: var(--tx); }

.fp__head {
    padding: 26px 44px;
    border-bottom: 1px solid var(--hairline);
    display: flex;
    align-items: center;
    /* One child, so it sits where the wordmark's opposite number used to. */
    justify-content: flex-end;
    gap: var(--sp-4);
}

.fp__shared { font-family: var(--mono); font-size: 12px; color: var(--tx-3); }

.fp__body { padding: 60px 44px 56px; display: grid; gap: 34px; justify-items: center; }

.fp__stale { margin: 0; color: var(--hot); font-size: var(--t-sm); text-align: center; }

/*
 * The two-line headline. One sentence broken where it turns, the second line in the
 * accent. Sized so the first line holds on one line at desktop width -- the break is
 * authored, and a copy edit that makes the container wrap it has broken the rule.
 */
.fp__h1 {
    font-family: var(--disp);
    font-weight: 900;
    text-transform: uppercase;
    font-size: 56px;
    letter-spacing: -.03em;
    line-height: 1.04;
    text-wrap: balance;
    max-width: 17ch;
    margin: 0 auto;
    text-align: center;
}
.fp__h1 em { display: block; font-style: normal; color: var(--accent); }

.fp__sub {
    font-size: 19px;
    line-height: 1.6;
    color: var(--tx-2);
    max-width: 56ch;
    margin: 0 auto;
    text-align: center;
    text-wrap: pretty;
}

/* ------------------------------------------------------------------ the video */

.fp__video {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: var(--ink-2);
    border: 1px solid var(--hairline);
    border-radius: 20px;
    overflow: hidden;
}

.fp__video video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* A warm rise from the top edge, so the panel is not a black hole when the frame is
   dark or the file has not arrived. */
.fp__bloom {
    position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(120% 90% at 50% 0%, rgba(var(--accent-rgb), .10), transparent 62%);
}

.fp__time {
    position: absolute; top: 18px; right: 20px;
    font-family: var(--mono); font-size: 12px; color: var(--tx-2);
    background: rgba(11, 12, 16, .72);
    padding: 6px 11px; border-radius: var(--r-pill);
    font-variant-numeric: tabular-nums;
}

.fp__playwrap { position: absolute; inset: 0; display: grid; place-items: center; }

.fp__play {
    width: 84px; height: 84px; border-radius: var(--r-pill);
    background: var(--accent); color: var(--accent-ink);
    border: none; cursor: pointer; padding: 0;
    display: grid; place-items: center;
    transition: background var(--dur-fast) var(--ease-travel);
}
.fp__play:hover { background: var(--accent-dim); }

/*
 * After unmute the control moves to the bottom left, into the space the sound prompt
 * has just vacated, and shrinks to a transport button. In the middle it is an
 * invitation; once someone is listening it would only be covering the speaker.
 * The wrap stops catching clicks so only the button itself is a target.
 */
.fp__video.is-sound .fp__playwrap { place-items: end start; padding: 0 0 22px 20px; pointer-events: none; }
.fp__video.is-sound .fp__play {
    width: 52px; height: 52px; pointer-events: auto;
    animation: fp-play-settle var(--dur-fast) var(--ease-travel);
}
.fp__video.is-sound .fp__play svg { width: 15px; height: 16px; }

@keyframes fp-play-settle { from { opacity: 0; transform: scale(.8); } to { opacity: 1; transform: none; } }

.fp__missing {
    position: absolute; inset: 0; margin: 0;
    display: grid; place-items: center;
    padding: var(--sp-5); text-align: center;
    font-family: var(--mono); font-size: 13px; color: var(--tx-3);
}

.fp__prompt {
    position: absolute; left: 20px; bottom: 22px;
    display: flex; align-items: center; gap: 6px;
    background: rgba(11, 12, 16, .86);
    border: 1px solid var(--hairline-2);
    border-radius: var(--r-pill);
    padding: 4px 6px 4px 14px;
}

.fp__prompt-on {
    background: none; border: none; cursor: pointer;
    color: var(--tx); font-weight: 600; font-size: 13.5px;
    padding: 6px 4px; display: flex; align-items: center; gap: 8px;
}
.fp__prompt-on:hover { color: var(--accent); }

.fp__prompt-x {
    width: 26px; height: 26px; border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .09); border: none;
    color: var(--tx-2); cursor: pointer; font-size: 14px; line-height: 1;
}
.fp__prompt-x:hover { color: var(--tx); }

.fp__bar { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: rgba(255, 255, 255, .09); }
.fp__bar i { display: block; height: 3px; width: 0; background: var(--accent); }

/* ------------------------------------------------------------- the three states */

.fp__act { display: flex; align-items: center; justify-content: center; gap: 22px; flex-wrap: wrap; }

.fp__fine {
    font-family: var(--mono); font-size: 12.5px; color: var(--tx-3);
    max-width: 34ch; line-height: 1.5; margin: 0;
}

.fp__card {
    width: 100%;
    background: var(--ink-2);
    border: 1px solid var(--hairline);
    border-radius: 20px;
}

.fp__form {
    padding: 32px 34px;
    display: grid; grid-template-columns: 1fr 1fr; gap: 30px; align-items: end;
}

.fp__form-say { display: grid; gap: 14px; }
.fp__form-fields { display: grid; gap: 12px; }

.fp__card-h {
    font-family: var(--disp); font-weight: 700; text-transform: uppercase;
    font-size: 20px; letter-spacing: -.02em; line-height: 1.1;
    margin: 0; text-wrap: balance;
}
.fp__card-b { margin: 0; font-size: 16px; line-height: 1.6; color: var(--tx-2); max-width: 40ch; }

.fp__form-fields input {
    background: var(--ink-3);
    border: 1px solid var(--hairline);
    color: var(--tx);
    font: inherit;
    font-size: 16px;
    font-weight: 400;
    padding: 15px 20px;
    border-radius: var(--r-pill);
    width: 100%;
}
.fp__form-fields input::placeholder { color: var(--tx-3); }
.fp__form-fields input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-color: var(--accent); }

/* Off screen rather than absent: a bot fills what it can read, and aria-hidden is
   what tells a screen reader to skip it. */
.fp__trap, .fp__sr { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); }

.fp__error { margin: 0; color: var(--danger); font-size: var(--t-sm); }

.fp__done { padding: 34px; display: grid; gap: 18px; justify-items: start; }

.fp__done-h {
    font-family: var(--disp); font-weight: 900; text-transform: uppercase;
    font-size: 30px; letter-spacing: -.03em; line-height: 1.04;
    margin: 0; text-wrap: balance;
}
.fp__done-h em { display: block; font-style: normal; color: var(--accent); }
.fp__done-b { margin: 0; font-size: 17px; color: var(--tx-2); max-width: 50ch; line-height: 1.6; }

/*
 * The primary button. Its label is Orange Ink, never white -- white on orange is the
 * mistake the spec calls out by name. White appears only on hover, over the deeper
 * orange.
 */
.fp-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 10px;
    background: var(--accent); color: var(--accent-ink);
    font-weight: 700; font-size: 16px;
    padding: 15px 28px;
    border: 1px solid var(--accent); border-radius: var(--r-pill);
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease-travel), transform var(--dur-fast) var(--ease-travel);
}
.fp-btn:hover { background: var(--accent-dim); border-color: var(--accent-dim); color: #fff; transform: translateY(-1px); }
.fp-btn--full { width: 100%; }

/* -------------------------------------------------------------------- mobile */

@media (max-width: 720px) {
    .fp__head { padding: 18px 20px; }
    .fp__body { padding: 34px 20px 40px; gap: 24px; }
    .fp__h1 { font-size: 29px; max-width: none; }
    .fp__sub { font-size: 16px; }

    /* Taller frame. The prompt and the moved control share the bottom corner. */
    .fp__video { aspect-ratio: 9 / 13; }
    .fp__play { width: 66px; height: 66px; }
    .fp__video.is-sound .fp__playwrap { padding: 0 0 20px 14px; }
    .fp__video.is-sound .fp__play { width: 46px; height: 46px; }
    .fp__prompt { left: 14px; right: 14px; bottom: 20px; justify-content: space-between; }

    .fp__form { grid-template-columns: 1fr; padding: 24px 22px; gap: 14px; }
    .fp__done { padding: 24px 22px; }
    .fp__done-h { font-size: 19px; font-weight: 700; }
    .fp-btn { width: 100%; padding: 17px 28px; font-size: 16.5px; }
    .fp__act { flex-direction: column; gap: 16px; }
}

/* -------------------------------------------- the series (handoff 2c and 2d) */

.fp--series .fp__head { padding: 22px 40px; }

.fps { display: grid; grid-template-columns: 340px 1fr; align-items: stretch; }

.fps__rail { border-right: 1px solid var(--hairline); padding: 28px 0 34px; }

.fps__progress {
    font-family: var(--mono); font-size: 11.5px; color: var(--tx-3);
    margin: 0 28px 18px; line-height: 1.5;
}

.fps__step {
    width: 100%; text-align: left;
    display: flex; gap: 14px; align-items: flex-start;
    padding: 16px 28px;
    border: none; border-left: 2px solid transparent;
    background: transparent; cursor: pointer;
    font: inherit; color: inherit;
}
.fps__step:hover { background: var(--ink-2); }

/* A mouse click focuses the row, and the default ring on top of the selected state
   reads as an error box. Keyboard focus still gets a ring, and a clearer one. */
.fps__step:focus { outline: none; }
.fps__step:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Selected carries the rule and the raised ground. Locked is dimmed but still a
   row somebody can select, because seeing what is behind the lock is the point. */
.fps__step.is-on { border-left-color: var(--accent); background: var(--ink-3); }
.fps__step.is-locked .fps__step-title { color: var(--tx-3); }

.fps__icon { width: 22px; flex: none; margin-top: 1px; }
.fps__step-text { flex: 1; display: grid; gap: 5px; }

.fps__step-title {
    font-family: var(--disp); font-weight: 700; text-transform: uppercase;
    font-size: 13px; letter-spacing: -.01em; line-height: 1.2;
}
.fps__step-meta { font-family: var(--mono); font-size: 11.5px; color: var(--tx-3); }

.fps__detail { padding: 40px 40px 48px; }
.fps__pane { display: grid; gap: 26px; align-content: start; }

.fps__title {
    font-family: var(--disp); font-weight: 900; text-transform: uppercase;
    font-size: 36px; letter-spacing: -.03em; line-height: 1.04;
    text-wrap: balance; margin: 0; max-width: 22ch;
}
.fps__title.is-locked { color: var(--tx-3); }

.fps__line { margin: 0; font-size: 18px; line-height: 1.62; color: var(--tx-2); max-width: 58ch; text-wrap: pretty; }

.fps__video {
    position: relative; aspect-ratio: 16 / 9;
    background: var(--ink-2); border: 1px solid var(--hairline);
    border-radius: 20px; overflow: hidden;
}
.fps__video video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.fps__playwrap {
    position: absolute; inset: 0;
    display: grid; place-items: center; align-content: center; gap: 16px;
    padding: 20px;
}
.fps__missing {
    margin: 0; text-align: center;
    font-family: var(--mono); font-size: 13px; color: var(--tx-3);
}

/* A still control on a step with no file yet: the shape is right, and it does not
   pretend to be pressable. */
.fp__play--still {
    width: 74px; height: 74px; border-radius: var(--r-pill);
    background: var(--accent); color: var(--accent-ink);
    display: grid; place-items: center; opacity: .35;
}

/* Dashed, and carrying no video source at all. */
.fps__locked {
    aspect-ratio: 16 / 9;
    background: var(--ink-2);
    border: 1px dashed var(--hairline-2);
    border-radius: 20px;
    display: grid; place-items: center; gap: 14px;
    padding: 20px;
    align-content: center; justify-items: center;
}
.fps__locked-why {
    margin: 0; font-family: var(--mono); font-size: 13px; color: var(--tx-3);
    text-align: center; max-width: 34ch; line-height: 1.6;
}

.fps__do { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.fps__do .fp-btn { text-decoration: none; }

/* ------------------------------------------------------ the cost card, step three */

.fps__cost { background: var(--ink-2); border: 1px solid var(--hairline); border-radius: 20px; overflow: hidden; }

.fps__cost-h {
    font-family: var(--disp); font-weight: 700; text-transform: uppercase;
    font-size: 16px; letter-spacing: -.02em; line-height: 1.1;
    margin: 0; padding: 22px 26px 16px;
}

.fps__row { display: flex; align-items: baseline; gap: 20px; padding: 14px 26px; border-top: 1px solid var(--hairline); }
.fps__row-what { flex: 1; display: grid; gap: 3px; }
.fps__row-label { font-weight: 600; font-size: 15.5px; color: var(--tx); }
.fps__row-sub { font-size: 13.5px; color: var(--tx-3); }

.fps__row-amt, .fps__total-amt, .fps__then-amt {
    font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.fps__row-amt { font-size: 14px; color: var(--tx-2); }

.fps__row--total { border-top: 1px solid var(--hairline-2); background: var(--ink-3); padding: 18px 26px; }
.fps__total-label {
    flex: 1; font-family: var(--disp); font-weight: 700;
    text-transform: uppercase; font-size: 14px; letter-spacing: -.01em;
}
.fps__total-amt { font-size: 20px; font-weight: 600; color: var(--accent); }

.fps__row--then { border-top: 0; background: var(--ink-3); padding: 14px 26px 18px; }
.fps__then-label { flex: 1; font-size: 15px; color: var(--tx-2); }
.fps__then-amt { font-size: 15px; color: var(--tx-2); }

/* A count, never a figure. */
.fps__claim {
    margin: 0; font-family: var(--disp); font-weight: 700; text-transform: uppercase;
    font-size: 22px; letter-spacing: -.02em; line-height: 1.1;
    text-wrap: balance; max-width: 24ch;
}

/* The honest catch. Amber rule, and on mobile it drops the card and keeps the rule,
   because the rule is the part carrying the meaning. */
.fps__catch {
    background: var(--ink-2);
    border: 1px solid var(--hairline);
    border-left: 3px solid var(--hot);
    border-radius: 0 12px 12px 0;
    padding: 18px 22px;
    display: grid; gap: 8px;
}
.fps__catch p { margin: 0; font-size: 16px; line-height: 1.6; color: var(--tx-2); max-width: 56ch; }
.fps__catch-h {
    font-family: var(--disp); font-weight: 700; text-transform: uppercase;
    font-size: 15px; letter-spacing: -.01em; line-height: 1.15; color: var(--tx) !important;
}

/* --------------------------------------------------------- the offer, step five */

.fps__offer-h {
    margin: 0; font-family: var(--disp); font-weight: 900; text-transform: uppercase;
    font-size: 26px; letter-spacing: -.03em; line-height: 1.04;
    text-wrap: balance; max-width: 26ch;
}
.fps__offer-h em { display: block; font-style: normal; color: var(--accent); }

.fps__cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.fps__col {
    background: var(--ink-2); border: 1px solid var(--hairline); border-radius: 20px;
    padding: 22px 20px; display: grid; gap: 14px; align-content: start;
}
.fps__col-h {
    font-family: var(--mono); font-size: 11.5px; text-transform: uppercase;
    letter-spacing: .04em; color: var(--tx-3);
}
.fps__col-h.is-accent { color: var(--accent); }
.fps__col-i { font-size: 14.5px; line-height: 1.5; color: var(--tx); }
.fps__col:last-child .fps__col-i { color: var(--tx-2); }

/* -------------------------------------------------------------------- mobile */

@media (max-width: 860px) {
    .fp--series .fp__head { padding: 18px 20px; }
    .fps { grid-template-columns: 1fr; }

    /*
     * An accordion. Each step is its own card, the rail rows become the headers, and
     * the pane that belongs to a row follows it rather than sitting in a column that
     * no longer exists.
     */
    .fps__rail { border-right: 0; padding: 18px 16px 8px; display: grid; gap: 10px; }
    .fps__progress { margin: 0 4px 4px; }

    .fps__step {
        border: 1px solid var(--hairline);
        border-left: 1px solid var(--hairline);
        border-radius: 20px;
        padding: 16px 18px;
    }
    .fps__step.is-on { border-color: var(--hairline-2); border-left-color: var(--hairline-2); }
    .fps__step.is-locked { border-style: dashed; }

    .fps__detail { padding: 8px 16px 34px; }
    .fps__pane { gap: 20px; }
    .fps__title { font-size: 24px; }
    .fps__line { font-size: 16px; }

    .fps__cols { grid-template-columns: 1fr; }
    /* Only the middle column on a phone: what actually becomes theirs. */
    .fps__col:first-child, .fps__col:last-child { display: none; }

    .fps__catch { background: none; border: 0; border-left: 3px solid var(--hot); border-radius: 0; padding: 0 0 0 14px; }
    .fps__claim { font-size: 19px; }
    .fps__do .fp-btn { width: 100%; }
}

/* ---------------------------------------------------------------- the rail chooser

   One decision, so the options are the only things on the page that look pressable.
   Each is a full-width button rather than a card with a button inside it: the whole
   row is the target, which is what a thumb expects and what a card with a small
   button in the corner quietly is not. */
.rail { display: flex; flex-direction: column; gap: var(--sp-4); max-width: 34rem; margin: 0 auto; }

.rail__pick {
    display: grid; grid-template-columns: 1fr auto; gap: 4px var(--sp-4);
    width: 100%; text-align: left; cursor: pointer;
    padding: var(--sp-5); border-radius: var(--r-card);
    border: 1px solid var(--hairline); background: var(--ink-2); color: var(--tx);
    font: inherit;
    transition: border-color .15s ease, transform .15s ease;
}
.rail__pick:hover { border-color: var(--accent); }
.rail__pick:active { transform: translateY(1px); }
.rail__pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.rail__coin { font-size: var(--t-lg); font-weight: var(--w-semi); }

/* The stablecoins, sharing one explanation. The group is inset and the cards inside it
   are compact, so the two together read as one option with a currency to pick rather
   than as two unrelated things that happen to say the same thing. */
.rail__group { display: flex; flex-direction: column; gap: 10px; }
.rail__groupwhy { margin: var(--sp-2) 0 2px; padding: 0 var(--sp-5); color: var(--tx-2); font-size: var(--t-sm); }
.rail__pick--compact { padding: var(--sp-4) var(--sp-5); align-items: center; }
.rail__pick--compact .rail__coin { font-size: var(--t-md); }
.rail__pick--compact .rail__go { grid-row: 1; }
.rail__why { grid-column: 1; color: var(--tx-2); font-size: var(--t-sm); }

/* The verb sits beside the coin rather than under the explanation, so the eye can run
   down the left column comparing options without the calls to action interrupting. */
.rail__go { grid-column: 2; grid-row: 1 / span 2; align-self: center; color: var(--accent); font-size: var(--t-sm); font-weight: var(--w-semi); white-space: nowrap; }

/* On a narrow screen the call to action stops sharing a row with the explanation and
   goes under it. Side by side, the description was being squeezed into a column two or
   three words wide while the words "Pay with this" sat in the space it needed. */
@media (max-width: 560px) {
    .rail__pick,
    .rail__pick--compact { grid-template-columns: 1fr; }
    .rail__go,
    .rail__pick--compact .rail__go { grid-column: 1; grid-row: auto; align-self: start; margin-top: 6px; }
    .rail__groupwhy { padding: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .rail__pick { transition: none; }
    .rail__pick:active { transform: none; }
}

/* ------------------------------------------------------------------- the warnings

   TWO WEIGHTS, ON PURPOSE. One of these mistakes is recoverable and the other is not,
   and giving them matching treatment would tell somebody they are the same size of
   problem. The grave one gets the danger colour and a tinted ground; the other is a
   plain note. If both ever looked alike, the loud one would stop being loud. */
.warn {
    max-width: 34rem; margin: var(--sp-5) auto 0;
    padding: var(--sp-5); border-radius: var(--r-card);
    border: 1px solid var(--hairline); border-left-width: 3px; border-left-color: var(--hot);
    background: var(--ink-2); font-size: var(--t-sm); color: var(--tx-2);
}
.warn p { margin: 0; }
.warn__head { color: var(--tx); font-weight: var(--w-semi); margin-bottom: 6px !important; }

.warn--grave {
    border-left-color: var(--danger);
    background: rgba(var(--danger-rgb), .06);
}
.warn--grave .warn__head { color: var(--danger); }

.pay__note--wide { max-width: 34rem; }

/* The payment column is one width all the way down. The waiting panel used to run the
   full wrap while the warnings above it stopped at 34rem, which made the page look like
   two columns of different widths stacked rather than one. */
.paystate--sol { max-width: 34rem; margin-left: auto; margin-right: auto; margin-top: var(--sp-6); }

/* Coin above, network under it, in the accent so it is not read as a subtitle. The
   single most expensive misreading on this page is the network, so it is never left
   to be inferred from the coin's name. */
/* The dollar figure under a quoted coin amount. A number of SOL means nothing on its
   own, and this is the price they actually agreed to. */
.sol__worth { margin-top: 8px; color: var(--tx-2); font-size: var(--t-sm); }

.sol__network {
    margin-top: 8px; color: var(--accent);
    font-size: var(--t-md); font-weight: var(--w-semi); letter-spacing: .06em;
    text-transform: uppercase;
}
