@import '_content/Blazored.Toast/Blazored.Toast.bundle.scp.css';
@import '_content/CueFlect.WebClient.Consoles/CueFlect.WebClient.Consoles.83yilbifms.bundle.scp.css';
@import '_content/CueFlect.WebClient.Shared/CueFlect.WebClient.Shared.za66sk7crq.bundle.scp.css';

/* /Account/AccountHome.razor.rz.scp.css */
.acct-grid[b-hwhus0vlci] {
    display: grid;
    grid-template-columns: minmax(0, 24rem) minmax(0, 1fr);
    align-items: start;
    gap: var(--space-4);
}

@media (max-width: 58rem) {
    .acct-grid[b-hwhus0vlci] {
        grid-template-columns: 1fr;
    }
}

.acct-next[b-hwhus0vlci] {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    padding: 0;
}

.acct-next a[b-hwhus0vlci] {
    color: var(--text-secondary);
    font-size: var(--text-sm);
}

.acct-next a:hover[b-hwhus0vlci] {
    color: var(--text-primary);
}

/*
    The account id, separated from the plan facts above rather than listed among them.

    It is not plan data and it does not arrive with the plan — it is on screen while those rows are still
    a skeleton — so it gets its own list and its own gap. A hairline was the alternative and it would have
    been the second rule inside one panel, which is what makes a panel read as two.
*/
.acct-id[b-hwhus0vlci] {
    margin-block-start: var(--space-4);
}

.acct-id__value[b-hwhus0vlci] {
    /* One click takes the whole id — see the markup for why that is the affordance that matters here. */
    user-select: all;
}

.acct-id__note[b-hwhus0vlci] {
    margin-block-start: var(--space-2);
}
/* /Account/Billing.razor.rz.scp.css */
/* A count belongs under its heading, and both belong on the same edge — the desktop's GridView numeric
   columns do the same, and a right-aligned figure under a left-aligned label reads as a misprint. */
.num[b-fmzo4szxai] {
    text-align: end;
}
/* /Account/DataRights.razor.rz.scp.css */
.data-actions[b-z28y89nwxu] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

/*
    The destructive trigger, in outline rather than fill.

    ::deep because the element is CfButton's, so it carries CfButton's scope and not this page's — the class
    on the wrapper above is what makes the selector specific, ::deep is what makes it apply at all.

    Deliberately short of CfButtonVariant.Danger. That variant is the filled red reserved for the button
    inside the dialog, the one that actually deletes; this one only opens the dialog, and a page where both
    steps shout equally has stopped distinguishing them. What it must not be is what it was — visually
    identical to "Download my data" one panel above, which is the single pair on this page a misread would
    cost the most.
*/
.data-actions--danger[b-z28y89nwxu]  .cf-btn {
    border-color: var(--danger-fill);
    color: var(--danger-text);
}

.data-actions--danger[b-z28y89nwxu]  .cf-btn:hover:not(:disabled):not([aria-disabled="true"]) {
    background-color: var(--danger-wash);
    border-color: var(--danger-text);
    color: var(--danger-text);
}

.data-choice[b-z28y89nwxu] {
    display: flex;
    align-items: start;
    gap: var(--space-3);
    color: var(--text-secondary);
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
    margin-block-start: var(--space-4);
    max-width: var(--measure);
}

.data-choice input[b-z28y89nwxu] {
    /* Nudged onto the first line's optical centre — a checkbox baseline-aligned against wrapped text sits
       high enough to read as belonging to the line above. */
    margin-block-start: 0.15em;
}
/* /Account/Devices.razor.rz.scp.css */
/* Nothing page-specific: the table, the chips and the notes are all component or global vocabulary.
   The file exists so a later addition has an obvious home rather than reaching for app.css. */
/* /Account/RetainedRecords.razor.rz.scp.css */
.retained[b-1418pm8u6q] {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin: var(--space-4) 0 0;
    max-width: var(--measure);
    padding: 0;
}

.retained li[b-1418pm8u6q] {
    display: flex;
    flex-direction: column;
    gap: var(--space-05);
    border-inline-start: 2px solid var(--stroke);
    padding-inline-start: var(--space-3);
}

.retained__what[b-1418pm8u6q] {
    color: var(--text-primary);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
}

.retained__more[b-1418pm8u6q] {
    margin-block-start: var(--space-4);
    max-width: var(--measure);
}
/* /Account/Subscription.razor.rz.scp.css */
.sub-actions[b-90l6cp4nwc] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}
/* /Marketing/Content/ArticleView.razor.rz.scp.css */
/*
    The reading surface.

    THE PAGE IS ANSWER, INDEX, EXPANSION — see ArticleView.razor for why that order was chosen. What the
    styling has to do is make the first of the three unmistakably the emission: the answer sits on lit glass
    at a larger size and full text contrast, with the cool half of the mark's ramp down its leading edge,
    where the separated answer lines leave the prism. Everything below it is the same claim at reading
    contrast.

    GAP, NOT MARGIN CHAINS. DESIGN.md's third scoped-CSS trap: `> * + *` attaches the scope attribute to the
    last compound selector, so a flow rule skips any child rendered by a component — which here is most of
    the page.
*/

.doc[b-cdgbyi4a34] {
    display: flex;
    flex-direction: column;
    gap: var(--space-12);
}

.doc__article[b-cdgbyi4a34] {
    display: flex;
    flex-direction: column;
    gap: var(--space-8);
}

/* ── The reading rule ───────────────────────────────────────────────────────────────────────────────────

   CSS-only, driven by animation-timeline: scroll(). No script and no inline style, so it survives M10-U11's
   CSP on both axes. It is the spectrum token — the one place in this system where both ramps meet on a
   single line — so completing the article is completing the refraction.

   THE TRACK ONLY EXISTS WHERE THE TIMELINE DOES. Without @supports, a browser with no scroll-driven
   animation would paint an empty groove that never fills, which reads as a broken control rather than as an
   absent one. */

.doc__progress[b-cdgbyi4a34] {
    display: none;
}

@supports (animation-timeline: scroll()) {
    .doc__progress[b-cdgbyi4a34] {
        display: block;
        block-size: 2px;
        border-radius: var(--radius-pill);
        background-color: var(--surface-inset);
        overflow: hidden;
        position: sticky;
        inset-block-start: var(--header-height);
        z-index: 1;
    }

    .doc__progress-fill[b-cdgbyi4a34] {
        display: block;
        block-size: 100%;
        background-image: var(--rule-spectrum);
        transform-origin: 0 50%;
        animation: doc-progress-b-cdgbyi4a34 linear both;
        animation-timeline: scroll();
    }
}

@keyframes doc-progress-b-cdgbyi4a34 {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
}

/* ── Masthead ───────────────────────────────────────────────────────────────────────────────────────── */

.doc__masthead[b-cdgbyi4a34] {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    max-width: var(--measure);
}

.doc__kind[b-cdgbyi4a34] {
    color: var(--text-muted);
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0;
}

.doc__dot[b-cdgbyi4a34] {
    color: var(--stroke-strong);
}

.doc__title[b-cdgbyi4a34] {
    color: var(--text-primary);
    margin: 0;
}

/* ── The emission ───────────────────────────────────────────────────────────────────────────────────────

   The one moment on the page that is not reading contrast. The leading edge carries the COOL ramp only:
   warm is where the wave enters, cool is where the answer leaves, and this block is the leaving. */

.doc__answer[b-cdgbyi4a34] {
    background-color: var(--glass);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--stroke);
    border-radius: var(--radius-md);
    box-shadow: var(--elev-1);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    max-width: var(--measure);
    padding: var(--space-6);
    position: relative;
    overflow: hidden;
}

.doc__answer[b-cdgbyi4a34]::before {
    background-image: linear-gradient(180deg, var(--spectrum-cool) 0%, var(--spectrum-cool-lo) 55%, transparent 100%);
    content: "";
    inline-size: 2px;
    inset-block: 0;
    inset-inline-start: 0;
    position: absolute;
}

.doc__answer-text[b-cdgbyi4a34] {
    color: var(--text-primary);
    font-size: var(--text-lg);
    line-height: var(--leading-normal);
    margin: 0;
    text-wrap: pretty;
}

.doc__tags[b-cdgbyi4a34] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.doc__pending[b-cdgbyi4a34] {
    max-width: var(--measure);
}

/* ── The index ──────────────────────────────────────────────────────────────────────────────────────────

   Compact and inline rather than a persistent rail. The structure's own logic: the answer, then what is
   about to be expanded, then the expansion. A rail would put the contents beside the prose permanently,
   which is a different surface and a different argument. */

.doc__index[b-cdgbyi4a34] {
    border-block: 1px solid var(--stroke);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    max-width: var(--measure);
    padding-block: var(--space-5);
}

.doc__index-heading[b-cdgbyi4a34] {
    color: var(--text-muted);
    margin: 0;
}

.doc__index-list[b-cdgbyi4a34] {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

/*
    The row, not the words, is the target.

    Measured at 375px: the bare line box is 23px, one pixel under WCAG 2.2's 2.5.8 minimum of 24 — and these
    are list links rather than links inside a sentence, so the inline exception does not apply to them. The
    padding also makes the whole row hittable rather than just the glyphs, which is what a contents list is
    for on a phone.
*/
.doc__index-item a[b-cdgbyi4a34] {
    align-items: baseline;
    color: var(--text-secondary);
    display: flex;
    gap: var(--space-3);
    min-block-size: 24px;
    padding-block: var(--space-1);
    text-decoration: none;
    transition: color var(--motion-fast) var(--ease-out);
}

.doc__index-item a:hover[b-cdgbyi4a34] {
    color: var(--text-primary);
}

/* Tabular figures so a two-digit ordinal does not shift the titles beside it — the same rule the rest of
   this system applies to anything measured. */
.doc__index-num[b-cdgbyi4a34] {
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    font-variant-numeric: tabular-nums;
}

.doc__body[b-cdgbyi4a34] {
    /* .prose already sets the measure, the leading and the flow. Nothing to add but the seam. */
    margin: 0;
}

/* ── Related ────────────────────────────────────────────────────────────────────────────────────────── */

.doc__more[b-cdgbyi4a34] {
    border-block-start: 1px solid var(--stroke);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    max-width: var(--measure);
    padding-block-start: var(--space-8);
}

.doc__more h2[b-cdgbyi4a34] {
    color: var(--text-muted);
    margin: 0;
}

.doc__more-list[b-cdgbyi4a34] {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    list-style: none;
    margin: 0;
    padding: 0;
}

.doc__more-link[b-cdgbyi4a34] {
    border-radius: var(--radius-sm);
    color: inherit;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-3);
    text-decoration: none;
    transition: background-color var(--motion-fast) var(--ease-out);
}

.doc__more-link:hover[b-cdgbyi4a34] {
    background-color: var(--overlay-01);
}

.doc__more-title[b-cdgbyi4a34] {
    color: var(--text-primary);
    font-weight: var(--weight-semibold);
}

.doc__more-link:hover .doc__more-title[b-cdgbyi4a34] {
    color: var(--accent);
}

.doc__more-blurb[b-cdgbyi4a34] {
    color: var(--text-secondary);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
}

/*
    Reduced motion.

    Required of every stylesheet declaring @keyframes, and not satisfied by a global duration reset: this
    animation is driven by a SCROLL timeline rather than by time, so zeroing durations leaves it running.
    Removing the timeline is what actually stops it, and the track then holds its start state — an empty
    2px groove — so it is hidden outright rather than left as a rule that never fills.
*/
@media (prefers-reduced-motion: reduce) {
    .doc__progress[b-cdgbyi4a34] {
        display: none;
    }
}
/* /Marketing/Content/LocaleHome.razor.rz.scp.css */
/*
    The library hub.

    FOUR SECTIONS DOWN THE PAGE, NOT FOUR CARDS ACROSS IT. Home.razor's own comment records the refusal and
    this page is where it would be easiest to forget: four sections with a title, a sentence and a few items
    is the exact shape a card grid wants to be. A column keeps each section's blurb a real sentence and each
    item's blurb a real sentence, which is what a reader deciding where to start actually needs.

    The item lists are `.entries`, global, shared with the section index.
*/

.library[b-2na6tmwg8g] {
    display: flex;
    flex-direction: column;
    gap: var(--space-16);
}

.library__masthead[b-2na6tmwg8g] {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    max-width: var(--measure);
}

.library__lede[b-2na6tmwg8g] {
    color: var(--text-secondary);
    font-size: var(--text-lg);
    line-height: var(--leading-normal);
    margin: 0;
    text-wrap: pretty;
}

.library__section[b-2na6tmwg8g] {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

.library__head[b-2na6tmwg8g] {
    border-block-end: 1px solid var(--stroke);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    max-width: var(--measure);
    padding-block-end: var(--space-4);
}

.library__section-title[b-2na6tmwg8g] {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-stretch: var(--display-stretch);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: var(--leading-tight);
    margin: 0;
}

.library__section-title a[b-2na6tmwg8g] {
    color: var(--text-primary);
    text-decoration: none;
    transition: color var(--motion-fast) var(--ease-out);
}

.library__section-title a:hover[b-2na6tmwg8g] {
    color: var(--accent);
}

.library__section-lede[b-2na6tmwg8g] {
    color: var(--text-secondary);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    margin: 0;
    text-wrap: pretty;
}

/* Named rather than hidden — see the component. A section that disappears when it empties makes the
   library look like a different shape than it is. */
.library__none[b-2na6tmwg8g] {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: 0;
    padding-inline: var(--space-4);
}

.library__all[b-2na6tmwg8g] {
    margin: 0;
    padding-inline: var(--space-4);
}

.library__all a[b-2na6tmwg8g] {
    color: var(--accent);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    text-decoration: none;
}

.library__all a:hover[b-2na6tmwg8g] {
    text-decoration: underline;
    text-underline-offset: 0.2em;
}
/* /Marketing/Content/SectionView.razor.rz.scp.css */
/*
    One section's index.

    The listing itself is `.entries`, which is global — the library hub renders the same shape, and a
    scoped copy in each would be two places to change one rhythm. What is scoped here is the masthead, which
    only this page has.
*/

.section[b-vq3vpksd3u] {
    display: flex;
    flex-direction: column;
    gap: var(--space-10);
}

.section__masthead[b-vq3vpksd3u] {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    max-width: var(--measure);
}

.section__eyebrow[b-vq3vpksd3u] {
    color: var(--text-muted);
    margin: 0;
}

/* The way back up. A breadcrumb of one, because the hierarchy is one deep: an article's section, and the
   library. Rendering a full trail for two levels is furniture. */
.section__up[b-vq3vpksd3u] {
    color: inherit;
    text-decoration: none;
    transition: color var(--motion-fast) var(--ease-out);
}

.section__up:hover[b-vq3vpksd3u] {
    color: var(--accent);
}

.section__title[b-vq3vpksd3u] {
    color: var(--text-primary);
    margin: 0;
}

.section__lede[b-vq3vpksd3u] {
    color: var(--text-secondary);
    font-size: var(--text-lg);
    line-height: var(--leading-normal);
    margin: 0;
    text-wrap: pretty;
}
/* /Marketing/EmailUnsubscribe.razor.rz.scp.css */
/*
    Stopping marketing email.

    A COPY OF WaitlistUnsubscribe.razor.css RATHER THAN A SHARED CLASS, and that is Blazor's scoping rather
    than a preference: a scoped stylesheet compiles its selectors with the owning component's attribute, so
    `.unsubscribe__form` declared over there matches nothing here. The page reusing those class names without
    this file rendered as unstyled markup — present, readable, and visibly not the same product as the page
    beside it.

    The alternative is promoting the four rules to app.css, which is the right move the moment a third page
    wants them. Two pages that are deliberately near-identical do not yet justify a global class that would
    then have to be reasoned about from everywhere.

    NO PANEL, for the reason its sibling records: this page IS the one thing, reached deliberately by somebody
    who wants it over with, so it sits at measure on the page ground with nothing competing with the field.
*/
.unsubscribe[b-22hcrlw171] {
    max-width: var(--measure);
}

.unsubscribe__form[b-22hcrlw171] {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.unsubscribe__form[b-22hcrlw171]  .cf-btn {
    align-self: flex-start;
}

/* ::deep because the class lands on CfBanner's own scoped markup. */
.unsubscribe[b-22hcrlw171]  .unsubscribe__error {
    margin-bottom: var(--space-5);
}

.unsubscribe__email[b-22hcrlw171] {
    color: var(--text-primary);
    font-weight: var(--weight-semibold);
    overflow-wrap: anywhere;
}

.unsubscribe__fine[b-22hcrlw171] {
    margin: var(--space-6) 0 0;

    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    text-wrap: pretty;
}
/* /Marketing/Home.razor.rz.scp.css */
/* gap, not `> * + *` — see Pricing.razor.css: a flow rule cannot reach a child component's root, because
   the scope attribute lands on the last compound selector. */
.home[b-ogqhcvnlhk] {
    display: flex;
    flex-direction: column;
    gap: var(--space-16);
}

/* ── Hero ──────────────────────────────────────────────────────────────────────────────────────────── */

/*
    Asymmetric, and asymmetric only sideways.

    The copy column is deliberately narrower than the art column's reach: the prism sits in the second
    column but is allowed to bleed past it inline. Two equal stacked bands with a rule between them is
    what a template looks like, and the horizontal break is what keeps this from being one.

    It does NOT hang below the section any more — see .home__art for why the vertical half was withdrawn.
*/
.home__lead[b-ogqhcvnlhk] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
    align-items: center;
    column-gap: var(--space-8);
    padding-block-start: var(--space-12);
}

/* 17ch sets the claim in four lines. text-wrap: balance would even them out, but on a four-line display
   headline it produces a short orphan third line more often than not — the measure does the job. */
.home__claim[b-ogqhcvnlhk] {
    margin: 0;
    max-width: 17ch;
}

.home__sub[b-ogqhcvnlhk] {
    color: var(--text-secondary);
    font-size: var(--text-lg);
    line-height: var(--leading-normal);
    margin-block-start: var(--space-6);
    max-width: 48ch;
}

.home__actions[b-ogqhcvnlhk] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-block-start: var(--space-8);
}

/*
    Breaks its column outward, and only outward.

    THE VERTICAL BREAK IS GONE, AND ITS ABSENCE IS THE POINT. The prism used to hang below the section on
    a translate, so the rail beneath slid under its bloom rather than meeting a clean horizontal seam.
    That reads as intended only while what passes behind the rail IS bloom. `.rail` is glass — a
    translucent background over a backdrop-filter — so what showed through it was not the soft ellipse but
    the prism's solid geometry: a cyan edge crossing "How an answer is produced" and its note, which is a
    caption strip losing contrast to decoration rather than artwork layering behind a panel.

    So the horizontal break stays and the vertical one is withdrawn. `align-items: center` on the grid is
    then what places the prism — no override here, deliberately — leaving it centred in the band between
    the chrome bar and the rail.
*/
.home__art[b-ogqhcvnlhk] {
    margin-inline-end: calc(var(--space-8) * -1);
}

.home__h2[b-ogqhcvnlhk] {
    margin: 0;
}

.home__body[b-ogqhcvnlhk] {
    color: var(--text-secondary);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    margin-block-start: var(--space-4);
    max-width: var(--measure);
}

@media (max-width: 64rem) {
    .home__lead[b-ogqhcvnlhk] {
        grid-template-columns: 1fr;
        row-gap: var(--space-8);
        padding-block-start: var(--space-8);
    }

    .home__claim[b-ogqhcvnlhk] {
        max-width: 18ch;
    }

    .home__art[b-ogqhcvnlhk] {
        margin-inline-end: 0;
        /* Capped, because at one column the prism would otherwise take a whole phone screen before the
           reader has reached a single fact. */
        max-width: 22rem;
        margin-inline: auto;
    }
}

/* ── The rail ──────────────────────────────────────────────────────────────────────────────────────── */

/*
    One framed object in the desktop's panel idiom — caption strip over a sunken body — now in glass, so
    the hero's bloom shows through it. The elevation carries its own lit top edge; there is no hairline
    border, because a 1px border under a wide soft shadow is the ghost card.
*/
.rail[b-ogqhcvnlhk] {
    position: relative;
    background-color: var(--glass);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-3);
    overflow: hidden;
}

.rail__head[b-ogqhcvnlhk] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    background-color: var(--glass-strong);
    border-block-end: 1px solid var(--stroke);
    box-shadow: var(--edge-lit);
    padding: var(--space-3) var(--space-5);
}

.rail__note[b-ogqhcvnlhk] {
    color: var(--text-muted);
    font-size: var(--text-2xs);
}

.rail__track[b-ogqhcvnlhk] {
    position: relative;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    background-color: var(--glass-inset);
    list-style: none;
    margin: 0;
    padding: 0;
}

/*
    The through-line, and the light travelling along it.

    ::before is the static rule — a single accent hairline crossing the whole track at the marks' centre,
    drawn behind them so the opaque marks punch through and the run reads as four stations on one line.

    ::after is a short bright segment that sweeps that line left to right on a long loop: the signal
    actually moving through the pipeline the section is describing. Slow (7s) and thin, so it registers
    as liveness rather than as a progress bar demanding attention.
*/
.rail__track[b-ogqhcvnlhk]::before,
.rail__track[b-ogqhcvnlhk]::after {
    content: "";
    position: absolute;
    inset-block-start: calc(var(--space-5) + 1.125rem);
    pointer-events: none;
}

.rail__track[b-ogqhcvnlhk]::before {
    inset-inline: var(--space-5);
    border-block-start: 1px solid var(--accent-line);
}

.rail__track[b-ogqhcvnlhk]::after {
    inset-inline-start: var(--space-5);
    width: 22%;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--spectrum-cool-hi), transparent);
    opacity: 0.55;
    animation: rail-signal-b-ogqhcvnlhk 7s var(--ease-out) 1.2s infinite;
}

@keyframes rail-signal-b-ogqhcvnlhk {
    0% { transform: translateX(0); opacity: 0; }
    12% { opacity: 0.55; }
    /* Stops at the last mark rather than running off the edge — the pipeline ends at the overlay. */
    62% { transform: translateX(330%); opacity: 0.55; }
    76%, 100% { transform: translateX(330%); opacity: 0; }
}

/*
    The travelling signal is pure liveness — it carries no information the static through-line does not
    already carry — so under reduced motion it is removed rather than frozen. Left to the global duration
    reset it would stop at its `from` keyframe, which is a 2px bright bar parked at the first mark: a
    stationary artefact that looks like a rendering bug rather than a decision.
*/
@media (prefers-reduced-motion: reduce) {
    .rail__track[b-ogqhcvnlhk]::after {
        display: none;
    }
}

.rail__stage[b-ogqhcvnlhk] {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-5) var(--space-4);
}

/* Internal dividers, not card edges — one neutral hairline between stations. */
.rail__stage + .rail__stage[b-ogqhcvnlhk] {
    border-inline-start: 1px solid var(--stroke);
}

.rail__mark[b-ogqhcvnlhk] {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    /* Opaque, so it masks the through-line rather than sitting on top of it. */
    background-color: var(--surface-inset);
    border: 1px solid var(--accent-line);
    border-radius: var(--radius-sm);
    box-shadow: 0 0 0 var(--space-2) var(--surface-inset), var(--glow-cool);
    color: var(--accent);
}

/*
    The pivot stage. Its mark takes the spectrum — warm entering, cool leaving — because this is the point
    where the two halves of the mark actually meet, and it is the only stage whose answer to "where does
    this run?" is conditional. The glow is warm rather than cool for the same reason.
*/
.rail__stage--pivot .rail__mark[b-ogqhcvnlhk] {
    background-image: linear-gradient(135deg,
                                      var(--field-warm) 0%,
                                      transparent 55%,
                                      var(--field-cool) 100%);
    border-color: var(--spectrum-warm);
    box-shadow: 0 0 0 var(--space-2) var(--surface-inset), var(--glow-warm);
    color: var(--spectrum-warm-hi);
}

.rail__name[b-ogqhcvnlhk] {
    font-family: var(--font-display);
    font-stretch: 110%;
    font-size: var(--text-base);
    font-weight: 700;
    letter-spacing: -0.01em;
}

.rail__detail[b-ogqhcvnlhk] {
    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    flex: 1 1 auto;
}

@media (max-width: 62rem) {
    .rail__track[b-ogqhcvnlhk] {
        grid-template-columns: repeat(2, 1fr);
    }

    .rail__track[b-ogqhcvnlhk]::before,
    .rail__track[b-ogqhcvnlhk]::after {
        display: none;
    }

    .rail__stage:nth-child(n + 3)[b-ogqhcvnlhk] {
        border-block-start: 1px solid var(--stroke);
    }

    .rail__stage:nth-child(odd)[b-ogqhcvnlhk] {
        border-inline-start: 0;
    }
}

@media (max-width: 34rem) {
    .rail__track[b-ogqhcvnlhk] {
        grid-template-columns: 1fr;
    }

    /* Vertical through-line: the same device rotated, running down the marks' centre. The travelling
       segment stays off here — a 2px dot crawling down a phone screen is fidget, not signal. */
    .rail__track[b-ogqhcvnlhk]::before {
        display: block;
        inset-block: var(--space-5);
        inset-inline: calc(var(--space-4) + 1.125rem) auto;
        border-block-start: 0;
        border-inline-start: 1px solid var(--accent-line);
    }

    .rail__stage[b-ogqhcvnlhk] {
        border-inline-start: 0;
    }

    .rail__stage + .rail__stage[b-ogqhcvnlhk] {
        border-block-start: 1px solid var(--stroke);
    }
}

/* ── Split ─────────────────────────────────────────────────────────────────────────────────────────── */

.home__split[b-ogqhcvnlhk] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-12);
}

@media (max-width: 62rem) {
    .home__split[b-ogqhcvnlhk] {
        grid-template-columns: 1fr;
        gap: var(--space-10);
    }
}

/* ── Facts ─────────────────────────────────────────────────────────────────────────────────────────── */

.facts[b-ogqhcvnlhk] {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    list-style: none;
    margin: var(--space-6) 0 0;
    padding: 0;
}

.facts__item[b-ogqhcvnlhk] {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    color: var(--accent);
}

/* The exception carries the warm half of the spectrum. Colour is not doing the work alone — the copy
   says "is the part that can leave" and the glyph is a cloud, not a shield. */
.facts__item--warm[b-ogqhcvnlhk] {
    color: var(--spectrum-warm);
}

.facts__item[b-ogqhcvnlhk]  svg {
    flex-shrink: 0;
    margin-block-start: 0.2rem;
}

.facts__claim[b-ogqhcvnlhk] {
    color: var(--text-primary);
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
    margin: 0;
}

.facts__note[b-ogqhcvnlhk] {
    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    margin-block-start: var(--space-1);
}

/* ── Grounding ─────────────────────────────────────────────────────────────────────────────────────── */

/*
    ::deep — the class was passed to CfPanel, so it lands on CfPanel's scoped markup. See Pricing.razor.css.

    This block is a literal quotation of the overlay's grounding badges, so it takes the overlay's own
    frame: the deepest elevation in the set plus a teal bloom. Drawn as an ordinary inset panel it read as
    one more region of the web page; lit, it reads as a piece of the desktop app lifted onto it — which is
    exactly the claim the paragraph above it is making.
*/
.home[b-ogqhcvnlhk]  .home__chips-panel {
    margin-block-start: var(--space-6);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-3), var(--glow-cool);
}

.home__chips[b-ogqhcvnlhk] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.home__chips-note[b-ogqhcvnlhk] {
    color: var(--text-muted);
    font-size: var(--text-2xs);
    line-height: var(--leading-snug);
}

/* ── Close ─────────────────────────────────────────────────────────────────────────────────────────── */

/*
    The page's anchor. Warm, because it is where the reader leaves for the pricing page and the warm end
    of the spectrum is the entry side of the mark — the composition closes where it opened.
*/
/* Grid rather than space-between: with flex the button floated to the vertical middle of a three-line
   heading and read as unattached to it. Bottom-aligned in its own column, it sits on the copy's last
   baseline, which is where the eye finishes reading. */
.close[b-ogqhcvnlhk] {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: var(--space-8);
    background-color: var(--glass);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-3);
    overflow: hidden;
    padding: var(--space-10);
}

@media (max-width: 48rem) {
    .close[b-ogqhcvnlhk] {
        grid-template-columns: 1fr;
        align-items: start;
    }
}

.close[b-ogqhcvnlhk]::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: radial-gradient(38rem 22rem at 8% 120%, var(--field-warm) 0%, transparent 70%);
    pointer-events: none;
}

.close__copy[b-ogqhcvnlhk] {
    max-width: 46ch;
}

@media (max-width: 48rem) {
    .close[b-ogqhcvnlhk] {
        padding: var(--space-6);
    }
}
/* /Marketing/ModeComparisonTable.razor.rz.scp.css */
/* ::deep, because `mode-matrix` is passed to CfTable via CssClass and lands on ITS root — a plain rule here
   compiles to `.mode-matrix[b-thisfile]` and matches nothing. Guarded by
   ClassesPassedToChildComponentsAreStyledThroughDeep. */
[b-aqbdt6fc8b] .mode-matrix table {
    /* Seven rows of long prose in four columns. The minimum width is what makes the component's own scroll
       container do its job on a phone, rather than the cells collapsing into single characters.

       A literal rather than a custom property: EveryTokenUsedWithoutAFallbackIsDefined requires a bare
       `var(--x)` to be defined in tokens.css, and rightly — an undefined one resolves to nothing and the
       declaration is silently dropped. This is one component's layout dimension, not a value the system
       shares, so it does not belong in the token file and inventing a token to hold it would put a private
       measurement in the shared vocabulary. */
    min-width: 46rem;
}

/* The row header column: the leftmost cell names what the other three answer about, so it reads as a label
   rather than as a fourth value. */
[b-aqbdt6fc8b] .mode-matrix tbody th {
    color: var(--text-primary);
    font-weight: var(--weight-semibold);
    text-align: start;
    white-space: normal;
}

[b-aqbdt6fc8b] .mode-matrix td {
    color: var(--text-secondary);
    line-height: var(--leading-normal);
    vertical-align: top;
    white-space: normal;
}
/* /Marketing/Pricing.razor.rz.scp.css */
/*
    GAP, not `> * + *` margins, and the difference is a real defect this replaced.

    A flow rule's last compound selector is what Blazor stamps its scope attribute onto, so
    `.pricing > * + *` compiles to `.pricing > * + *[b-pricing]` — which matches only children written
    literally in THIS file. CfPageHeader and CfBanner render their own roots with their own scope, so they
    were skipped: the banner sat flush against the toggle row above it and the plan grid sat flush against
    the banner, at 0px where this rule says 2rem.

    `gap` is declared on the container and applies to every child regardless of who rendered it, so it
    cannot be defeated by scoping. Any flow spacing around child components has to work this way.
*/
.pricing[b-44pvxpr85z] {
    display: flex;
    flex-direction: column;
    gap: var(--space-8);
}

/* ── The billing-cadence control ──────────────────────────────────────────────────────────────────────── */

/*
    The `.pricing__notice` rules that used to sit here were removed with nothing else changing: the CfBanner
    they styled had already gone from the page, so `.pricing ::deep .pricing__notice` and its `.cf-banner__text`
    companion matched no markup at all. Dead ::deep rules are worse than dead ordinary ones — the scoping trap
    they document makes them read as load-bearing.
*/

.cadence__label[b-44pvxpr85z] {
    align-self: center;
}

/*
    A segmented control, drawn as one inset track with a lit pill under the selected option.

    The pill is a SEPARATE absolutely positioned element rather than a background on the active button,
    because it is the only way the movement can be animated: a background-colour swap between two elements
    cannot tween, and the slide is what tells the eye that these three are one control with one answer.
*/
.cadence[b-44pvxpr85z] {
    position: relative;
    display: inline-grid;
    grid-auto-columns: 1fr;
    grid-auto-flow: column;
    /* No gap: the pill is exactly one third of the track and moves by whole multiples of its own width,
       so any spacing between segments would slide it out from under the option it belongs to. */
    gap: 0;
    background: var(--surface-inset);
    border: 1px solid var(--stroke);
    border-radius: var(--radius-pill);
    padding: var(--space-05);
}

.cadence__pill[b-44pvxpr85z] {
    position: absolute;
    inset-block: var(--space-05);
    /* Three equal columns minus the container's own padding on both edges, divided three ways. */
    inline-size: calc((100% - (var(--space-05) * 2)) / 3);
    inset-inline-start: var(--space-05);
    background: var(--accent);
    border-radius: var(--radius-pill);
    transition: transform var(--motion-medium) var(--ease-out);
    /* No prefers-reduced-motion block: app.css already collapses every transition on the document under
       that query, so a local one would only be a second place to keep the same rule. */
}

.cadence[data-cadence="quarterly"] .cadence__pill[b-44pvxpr85z] {
    transform: translateX(100%);
}

.cadence[data-cadence="annual"] .cadence__pill[b-44pvxpr85z] {
    transform: translateX(200%);
}

.cadence__option[b-44pvxpr85z] {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Centred, because Monthly has one line and the other two carry a savings line under them. Column flex
       starts at flex-start, so without this the row is as tall as the two-line options and Monthly sits
       against the top of its pill rather than in the middle of it. */
    justify-content: center;
    gap: var(--space-05);
    /* Transparent, not `background: none`: the pill sits behind and has to show through. */
    background: transparent;
    border: 0;
    border-radius: var(--radius-pill);
    color: var(--text-secondary);
    cursor: pointer;
    font: inherit;
    font-size: var(--text-sm);
    line-height: 1.2;
    padding: var(--space-15) var(--space-4);
    transition: color var(--motion-fast) var(--ease-out);
    white-space: nowrap;
}

.cadence__option:hover[b-44pvxpr85z] {
    color: var(--text-primary);
}

/* The selected option sits ON the accent pill, so it takes the dark-on-accent pair the desktop uses for the
   same job. Selection is carried by weight and contrast as well as by the pill, so it survives greyscale. */
.cadence__option[aria-checked="true"][b-44pvxpr85z],
.cadence__option[aria-checked="true"]:hover[b-44pvxpr85z] {
    color: var(--on-accent);
    font-weight: var(--weight-semibold);
}

.cadence__save[b-44pvxpr85z] {
    font-size: var(--text-2xs);
    /* 0.85, not a muted token: on the selected segment this text sits on the accent pill, where a
       --text-muted grey would drop below contrast. Fading the inherited colour keeps the pair legible in
       both states with one declaration. */
    opacity: 0.85;
}

/* The whole control is one tab stop with a roving tabindex, so the ring belongs on the segment that has
   focus, not on the track. */
.cadence__option:focus-visible[b-44pvxpr85z] {
    outline: var(--focus-ring);
    outline-offset: var(--focus-offset);
}

/* Below the plan grid's own breakpoint the header is narrow enough that three segments and their savings
   crowd the lede. Full width and smaller padding keeps them on one row instead of wrapping mid-control. */
@media (max-width: 32rem) {
    .cadence[b-44pvxpr85z] {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        inline-size: 100%;
    }

    .cadence__option[b-44pvxpr85z] {
        padding-inline: var(--space-2);
    }
}

.pricing__body[b-44pvxpr85z] {
    color: var(--text-secondary);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    margin-block-start: var(--space-3);
    max-width: var(--measure);
}

.pricing__body em[b-44pvxpr85z] {
    color: var(--text-primary);
    font-style: normal;
    font-weight: var(--weight-semibold);
}

/* ── Plans ─────────────────────────────────────────────────────────────────────────────────────────── */

/*
    FOUR, THEN TWO, THEN ONE — the counts four cards divide into evenly.

    This was `repeat(3, 1fr)` collapsing straight to one at 58rem, which the Free card broke twice over.

    `auto-fit` with a `minmax(15rem, 1fr)` floor was tried first and is the wrong tool for a FOUR-item grid.
    It fits as many tracks as the row has room for, which between roughly 54rem and 76rem is three — and three
    tracks holding four cards leaves the last one alone on a second row with two thirds of it empty. Measured
    at 860px: Free, Local and Mixed across the top, Cloud orphaned beneath. A rule that picks the count for you
    is right when the item count is open-ended and wrong when it is fixed at four.

    WHERE THE STEPS ARE IS A MEASUREMENT, NOT A GUESS. `.plan__top` puts a 26px Archivo name beside a chip:
    "Local" is ~83px and "Answers on device" ~150px, so that row needs ~241px. CfChip sets `white-space:
    nowrap` on itself and `text-overflow: ellipsis` on its label, so a column narrower than that does not
    overflow where anyone would see it — it silently ships "Answers on devi…" on the card the page recommends.
    Four columns hold 241px until about 76rem of viewport, so that is where the first step is.

    `minmax(0, 1fr)` rather than `1fr`: a bare `1fr` track has an automatic minimum of its content, so a long
    unbreakable string could push the grid wider than the viewport and take `PageReflowsAtTwoHundredPercentZoom`
    with it. Zero as the floor means the track always yields first.

    `.plans` and `.terms` no longer share the 58rem line they were deliberately paired on, and that pairing is
    genuinely lost. It was worth losing: it existed so the page had one collapse point, and a fourth card
    changes what the cards need without changing what a two-column text list needs.
*/
.plans[b-44pvxpr85z] {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-4);
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Two by two. Never three: see above. */
@media (max-width: 76rem) {
    .plans[b-44pvxpr85z] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 44rem) {
    .plans[b-44pvxpr85z] {
        grid-template-columns: minmax(0, 1fr);
    }

}

.plans__item[b-44pvxpr85z] {
    display: flex;
}

.plans__item[b-44pvxpr85z]  .cf-panel {
    display: flex;
    flex-direction: column;
    width: 100%;
}

/* The body has to stretch too, or `.plan { height: 100% }` resolves against a box that only wraps its
   content — and the `margin-block-start: auto` that pins each card's last line to the bottom silently
   does nothing. That was measured: the three cards were equal height and their closing lines were not. */
.plans__item[b-44pvxpr85z]  .cf-panel__body {
    display: flex;
    flex: 1 1 auto;
}

/*
    The featured plan is marked with a teal HAIRLINE, not a bloom.

    It used to carry --glow-cool: a 48px teal bloom, at rest, permanently. Two things were wrong with that.
    It read as "already selected" on a page whose whole argument is that the three columns are comparable —
    and it left hover with nowhere to go, because the card was already at the top of its own intensity range.
    A 1px --accent-line at the edge still says "this is the one" and says it far more quietly.

    Local is the featured plan because it is the one where nothing leaves the machine, so it takes the cool
    end of the spectrum — the answer side of the mark.

    No scale transform and no lift at rest. A card that grows is a card the eye has to re-measure against the
    two beside it, in the one layout whose entire argument is that the columns are comparable.
*/
.plans__item[data-featured][b-44pvxpr85z]  .cf-panel {
    box-shadow: var(--elev-2), 0 0 0 1px var(--accent-line), var(--edge-lit-strong);
}

/*
    Hover is an ACCENT RING on every card, and it took two attempts to get there because both earlier ones
    were invisible and I had not looked at the pixels.

    The first swapped --elev-2 for --elev-3 and lifted a 1px top inset from 7% to 11% white: a darker shadow
    on an already dark ground plus a 4% alpha change, i.e. nothing. Only the featured card appeared to
    respond, because --glow-cool-strong happens to carry its own 1px teal ring — so the ring was doing all
    the work and the lift none of it. The second attempt added a ring in --stroke-strong; measured in a real
    browser it renders as rgba(116,125,136,0.38) against a panel edge that is already a grey hairline, and it
    disappears into it. Alpha was the wrong axis: what the eye catches here is HUE, not luminance.

    So hover uses the accent at full strength. That is the same colour the focus ring uses, which is correct
    — both mean "the pointer or the keyboard is on this". A hovered plain card briefly outshining the resting
    featured card is fine: hover follows the pointer, so it reads as "you are pointing at this" rather than
    as a recommendation.
*/
.plans__item[b-44pvxpr85z]  .cf-panel {
    transition: transform var(--motion-medium) var(--ease-out),
                box-shadow var(--motion-medium) var(--ease-out);
}

.plans__item:hover[b-44pvxpr85z]  .cf-panel {
    transform: translateY(-3px);
    box-shadow: var(--elev-3), 0 0 0 1px var(--accent), var(--glow-cool), var(--edge-lit-strong);
}

/* The featured card keeps a stronger bloom under the same ring, so hovering it is still distinguishable
   from hovering its neighbours. */
.plans__item[data-featured]:hover[b-44pvxpr85z]  .cf-panel {
    box-shadow: var(--elev-3), 0 0 0 1px var(--accent), var(--glow-cool-strong), var(--edge-lit-strong);
}

/*
    THE PLAN THE VISITOR IS ALREADY ON, in --success rather than in the accent.

    This is the one card on the page where a ring at rest is correct. The note above records that the featured
    card's permanent bloom was removed because it "read as already selected" on a grid whose argument is that
    the columns are comparable — and that is exactly what this ring means, so the objection does not apply. It
    is a different hue from both neighbours for the same reason: --accent-line at rest says "this is the one we
    recommend", --success says "this is the one you have", and full --accent on hover says "your pointer is
    here". Three states, three colours, none of them borrowed.

    THE ORDER OF THE NEXT THREE RULES IS THE POINT. `box-shadow` is a single property, so the featured rule and
    this one cannot both apply — whichever loses is not dimmed, it is absent. A visitor on the Local plan would
    have got one ring and silently lost the other depending on which rule was written last, and the same is
    true of hover, which overwrites the whole shadow. So every combination is named rather than left to the
    cascade: current, current-and-featured, and each of those hovered.
*/
.plans__item[data-current][b-44pvxpr85z]  .cf-panel {
    box-shadow: var(--elev-2), 0 0 0 1px var(--success), var(--edge-lit-strong);
}

.plans__item[data-current][data-featured][b-44pvxpr85z]  .cf-panel {
    /* Both facts, and the success ring is the outer one so "yours" reads before "recommended". */
    box-shadow: var(--elev-2), 0 0 0 1px var(--accent-line), 0 0 0 2px var(--success), var(--edge-lit-strong);
}

/* Hover keeps the success ring rather than replacing it: the pointer moving over a card must not make it
   stop being the plan the visitor is on. The accent moves to the outside, where hover has always spoken. */
.plans__item[data-current]:hover[b-44pvxpr85z]  .cf-panel,
.plans__item[data-current][data-featured]:hover[b-44pvxpr85z]  .cf-panel {
    box-shadow: var(--elev-3), 0 0 0 1px var(--success), 0 0 0 2px var(--accent), var(--glow-cool),
                var(--edge-lit-strong);
}

.plan[b-44pvxpr85z] {
    display: flex;
    flex-direction: column;
    height: 100%;
}

/*
    Fixed height, because only one card carries a chip. A 26px chip beside a bare 22px h2 pushed the
    featured card's whole column down ~5px, so the price rules and the PERMITTED MODES captions did not
    line up across the three — in the one layout whose entire argument is that the columns are comparable.
*/
.plan__top[b-44pvxpr85z] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    min-height: 1.875rem;
}

.plan__name[b-44pvxpr85z] {
    font-family: var(--font-display);
    font-stretch: var(--display-stretch);
    font-size: var(--text-2xl);
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1;
    margin: 0;
}

/*
    THREE LINES RESERVED, not two, because a fourth column made the longest summary need three.

    The old 2.6em was about two lines at the three-card width. At four cards the column is 264px inside the
    panel and Local's sentence runs to three, so its PERMITTED MODES caption — and everything under it — sat
    20px below the same caption on its neighbours, in the one layout whose entire argument is that the columns
    are comparable. Expressed in the element's own line height rather than as a pixel figure, so it stays
    correct if the type scale moves.
*/
.plan__summary[b-44pvxpr85z] {
    color: var(--text-secondary);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    margin-block-start: var(--space-2);
    min-height: calc(3 * var(--leading-snug) * 1em);
}


/*
    The price block: a stack on the left, the savings chip on the right.

    THE CARD MUST NOT CHANGE HEIGHT WHEN THE CADENCE DOES. A control that makes the whole grid jump reads as
    broken rather than as responsive. That is handled structurally — `.plan__was` is always in the markup and
    reserves its own line — rather than by a min-height here, which was the first attempt: a measured pixel
    figure is a guess about the type scale, and this one was measurably below the block's natural height, so
    it reserved nothing at all while looking like it did.
*/
/*
    A GRID OF TWO ROWS, not one flex row, and the second row is why.

    This was `display: flex` with the amount stack and the savings chip as its two children, and the charge
    line living inside the stack. That held while the grid was three cards wide. At four the stack is about
    184px once the chip and its gap are taken out, and "Billed every 3 months — <total>" does not fit in that
    — so the line wrapped, the card grew 19.6px, and it grew on exactly the two cadences the control switches
    TO. The whole grid jumped the moment anyone used the control, which is the defect the note above says this
    block exists to prevent; it was caught by the browser walk rather than by reading, which is the point of
    having one.

    The charge line now spans both columns, so it is bounded by the card rather than by whatever the chip left
    over, and it fits on one line at every width this grid produces. That is a structural fix rather than a
    reserved second line: an empty line held open on the monthly cadence would cost every visitor who never
    touches the control 20px of nothing, on the view the page opens in.
*/
.plan__price[b-44pvxpr85z] {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: start;
    gap: var(--space-2);
    border-block: 1px solid var(--stroke);
    margin-block: var(--space-4);
    padding-block: var(--space-3);
}

.plan__stack[b-44pvxpr85z] {
    display: flex;
    flex-direction: column;
}

/* The price that no longer applies. Struck AND muted: the strike alone survives neither greyscale nor a
   reader that ignores <s>, which is why the markup carries a visually-hidden gloss beside it.

   `min-height: 1em` with `line-height: 1` is exactly one line box of this element's own font, so the empty
   monthly form reserves the same space the discounted form fills. Font-relative, so it stays correct if the
   type scale moves — which a pixel figure would not. */
.plan__was[b-44pvxpr85z] {
    margin: 0 0 var(--space-1);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    font-variant-numeric: tabular-nums;
    line-height: 1;
    min-height: 1em;
}

/*
    THE UNIT SITS UNDER THE AMOUNT, NOT BESIDE IT, AND THAT IS A HEIGHT DECISION BEFORE IT IS A TASTE ONE.

    Baseline-aligned on one row is the nicer setting and it is what this was. It survives only while the amount
    is short: the column beside the savings chip is about 184px on a four-card grid, "$15.20" is ~114px of that
    at --text-3xl mono, and "per month" then has ~62px to live in — so on the DISCOUNTED cadences, where the
    per-month figure gains two characters, the unit wrapped inside its own span and the card grew 21.69px.
    Flex does not wrap here, so nothing moved; the text simply became two lines and the grid jumped.

    Stacking makes the height a fact about the type scale rather than about the width: one amount line plus one
    unit line, on every cadence, at every card width, whatever the amount happens to be. The alternative was a
    reserved second line or a nowrap that overflows, and both are a measurement pretending to be a rule.
*/
.plan__headline[b-44pvxpr85z] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    margin: 0;
}

.plan__amount[b-44pvxpr85z] {
    font-family: var(--font-mono);
    font-size: var(--text-3xl);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

/*
    "Free" IS A WORD IN THE PRICE SLOT, AND IT IS SET AS ONE.

    `.plan__amount` is the mono, tabular-nums face, which is right for a figure and wrong for this: mono with
    tabular figures is the convention for a NUMBER, so a word in it reads as code rather than as a price. It
    takes the display face the plan names use, at the same optical size, so the four headlines still sit on one
    line across the row.

    `font-stretch` and the tight tracking come with that face — the same treatment `.plan__name` gets — which
    is what stops it looking like a different page's typography dropped into the card.
*/
.plan__amount--word[b-44pvxpr85z] {
    font-family: var(--font-display);
    font-stretch: var(--display-stretch);
    font-variant-numeric: normal;
    font-weight: 800;
    letter-spacing: -0.03em;
}

/* The placeholder reads as absent rather than as zero. A dash at full contrast would look like a real
   value of "nothing".

   IT IS NEVER APPLIED TO THE FREE CARD, and that is a markup decision rather than a selector one: the Free
   card omits `data-placeholder` entirely. Muting the word "Free" to --text-muted at 60% would render it near
   2.4:1 — a contrast failure on the single most important word on that card, and one an automated scan would
   report as a colour bug rather than as the missing price it actually is. */
.plan__price[data-placeholder="true"] .plan__amount[b-44pvxpr85z] {
    color: var(--text-muted);
    opacity: 0.6;
}

/* The line height and the reserved minimum are stated together on purpose: the Free card renders this span
   EMPTY, and an empty box only holds the same room as a filled one if both are told what a line is. Left to
   the inherited leading and an `em` minimum they differed by 7.7px, which is the whole point of reserving it. */
.plan__cadence[b-44pvxpr85z] {
    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    min-height: calc(var(--leading-snug) * 1em);
}

/* What is actually charged. Small, but never absent on a discounted cadence: the headline above it is a
   DERIVED per-month figure, so this line is the only place the real transaction appears.

   Spanning both columns is what keeps it on one line at every card width — see the note on `.plan__price`. */
.plan__charge[b-44pvxpr85z] {
    grid-column: 1 / -1;
    margin: var(--space-2) 0 0;
    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
}

/* ::deep, because `plan__saving` is handed to CfChip through CssClass and so lands on the CHIP's scoped
   markup, not on anything written in this file. Passing the class makes the selector specific; ::deep is
   what makes it apply. Same pairing the plan panels above need, and the same silent no-op without it. */
.plan__price[b-44pvxpr85z]  .plan__saving {
    /* Pinned to the top of the block rather than centred, so it aligns with the struck price it explains. */
    flex-shrink: 0;
}
/*
    THE RESERVATIONS COME OFF IN ONE COLUMN, because there is nothing left to reserve them against.

    The summary's three lines and the unit's empty line exist so four cards side by side put their captions
    and prices on the same rules. Stacked, there is no neighbour to line up with and the reservations are just
    gaps — a two-line summary holding a third line open, and a blank line under the word "Free", which on a
    phone is most of a thumb's worth of nothing.

    IT SITS HERE, BELOW BOTH RULES, RATHER THAN BESIDE THE GRID BREAKPOINTS ABOVE. A media query adds no
    specificity, so where this block was first written — before `.plan__summary` and `.plan__cadence` are
    declared — the later declarations simply won and it did nothing at all. Measured: `min-height` still
    resolved to 58.8px at 375px wide, with the query matching.
*/
@media (max-width: 44rem) {
    .plan__summary[b-44pvxpr85z],
    .plan__cadence[b-44pvxpr85z] {
        min-height: 0;
    }
}

/* Space above each caption, because a caption is a heading and these follow a list. Without it "Cloud" and
   the INCLUDED heading under it read as one block, and on the Free card three headings ran together. */
.plan__caption[b-44pvxpr85z] {
    display: block;
    margin-block-start: var(--space-3);
}

.plan__modes[b-44pvxpr85z] {
    display: flex;
    flex-direction: column;
    gap: var(--space-15);
    list-style: none;
    margin: var(--space-2) 0 0;
    padding: 0;
}

.plan__modes li[b-44pvxpr85z] {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-secondary);
    font-size: var(--text-xs);
}

.plan__modes[b-44pvxpr85z]  svg {
    color: var(--accent);
    flex-shrink: 0;
}

/*
    ── The call to action ────────────────────────────────────────────────────────────────────────────────

    THE AUTO MARGIN MOVED HERE FROM `.plan__answering`, and it had to move rather than be duplicated. Two
    `auto` margins in one flex column SPLIT the free space between them instead of pinning either, so the
    controls would have floated at some fraction of whatever the tallest card left over — different on every
    card, which is the one thing a row of comparable buttons must not be.

    So the control is what the free space is spent above, and the closing line rides directly under it. The
    four buttons land on one line across the row however tall the card above them is, which is what makes the
    row scannable as a set of choices rather than as four separate cards.

    THE MIN-HEIGHT IS ONE CfButton, EXPRESSED THE WAY CfButton EXPRESSES IT. Not every card renders a button —
    the current plan renders a status line and a plan with nothing to offer renders a sentence — and without a
    reserved height those cards' closing lines would sit higher than their neighbours'. 2.5rem is
    `.cf-btn`'s own Medium height, font-relative, so the two move together if the scale does.
*/
.plan__cta[b-44pvxpr85z] {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-height: 2.5rem;
    /* The divider moved here from the closing note when the control became the card's last element. It marks
       the boundary between what the plan IS and what you can do about it, which is a better place for a rule
       than in the middle of the fine print. */
    border-block-start: 1px solid var(--stroke);
    margin-block-start: auto;
    padding-block-start: var(--space-4);
}

/*
    THE TRAILING ARROW LEANS INTO THE DIRECTION IT POINTS.

    2px, on the fast token — small enough to read as the control responding rather than as something moving,
    and the same gesture the home page's hero buttons make. `::deep` is not optional here: the icon is CfIcon's
    markup carrying CfIcon's scope, so a bare `.cf-icon` rule written in this file compiles to a selector that
    matches nothing at all. Cheap to write, invisible to test, and the reason DESIGN.md calls scoping the trap
    that cost the most.
*/
.plan__cta[b-44pvxpr85z]  .cf-btn .cf-icon {
    transition: transform var(--motion-fast) var(--ease-out);
}

.plan__cta[b-44pvxpr85z]  .cf-btn:hover .cf-icon {
    transform: translateX(2px);
}

/*
    HOVERING ANYWHERE ON THE CARD LIGHTS ITS BUTTON.

    The card already lifts and takes an accent ring on hover; without this the control inside it stayed
    exactly as it was, so the card read as one object and its button as a separate one sitting on top. The
    glow is the same token the button reaches on its own hover, so pointing at the card and pointing at the
    button arrive at one state rather than at two that have to be told apart.
*/
.plans__item:hover[b-44pvxpr85z]  .cf-btn--primary {
    background-color: var(--action-hover);
    box-shadow: var(--glow-action-strong), var(--edge-lit-strong);
}

.plans__item:hover[b-44pvxpr85z]  .cf-btn--toolbar {
    background-color: var(--control-bg-hover);
    border-color: var(--stroke-strong);
    color: var(--text-primary);
}

/*
    THE CURRENT PLAN'S SLOT, which is a status and not a control — so it is a paragraph, never a disabled
    button. `aria-disabled` would tell a screen reader there is an action here that cannot be used, which is a
    different claim from "this is the plan you are on", and a false one.
*/
.plan__cta-current[b-44pvxpr85z] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: 2.5rem;
    margin: 0;
    border: 1px dashed var(--stroke-strong);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-size: var(--text-sm);
    line-height: 1.2;
    padding-inline: var(--space-3);
    text-align: center;
}

/* The check takes the success hue the chip above it uses, so the two read as one statement. */
.plan__cta-current[b-44pvxpr85z]  .cf-icon {
    color: var(--success);
    flex-shrink: 0;
}

/* A qualification ABOVE the control — what they are actually billed, or why there is nothing to press. Above,
   so that a card carrying one still puts its button on the same line as the three that do not. */
.plan__cta-note[b-44pvxpr85z] {
    margin: 0 0 var(--space-2);
    color: var(--text-muted);
    font-size: var(--text-2xs);
    line-height: var(--leading-snug);
    text-align: center;
}

/* In the content flow now rather than pinned, and without the rule it used to carry — the control below it
   took both jobs. It runs to one, two or three lines depending on the plan, which is exactly why it can no
   longer be the thing the bottom of the card is measured from. */
.plan__answering[b-44pvxpr85z] {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    margin-block-start: var(--space-4);
}

.plan__answering[b-44pvxpr85z]  svg {
    flex-shrink: 0;
    margin-block-start: 0.1rem;
}

/* ── M07-U07: the qualifications, the trial and the matrix ───────────────────────────────────────────── */

.plan__included[b-44pvxpr85z] {
    margin: 0;
    color: var(--text-secondary);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
}

.pricing__terms[b-44pvxpr85z],
.pricing__trial[b-44pvxpr85z],
.pricing__matrix[b-44pvxpr85z] {
    display: flex;
    flex-direction: column;
    /* gap, never `> * + *` — the scope attribute lands on the last compound selector, so a flow rule skips
       every child component. DESIGN.md records this as the trap that cost the most. */
    gap: var(--space-4);
}

/*
    Two columns on a wide viewport, one below.

    This was a single flex column, and each note carried `max-width: var(--measure)`. `ch` resolves against
    the element's OWN font size, so the note capped around 400px while the bold claim directly above it —
    which has no cap — filled the whole 68rem shell. A 2.5x width mismatch on stacked siblings, repeated down
    the page, with the right 60% of the section empty.

    The cap is gone because the column now bounds the line length, and a measure inside an already-constrained
    column is a second, tighter constraint fighting the first. `.rail__detail` and `.facts__note` make the
    same call for the same reason.

    WHICH IS WHY THIS LIST IS CAPPED AT THE NARROW SHELL. The page moved to `page-shell--wide` for the fourth
    plan card, and that quietly broke the argument above: a 78rem shell makes each of these columns ~584px, so
    a 14px note runs to roughly 83 characters against the project's own 68ch measure. The column stopped
    bounding the line, and the reasoning this block states stopped being true of it. Capping the list — rather
    than restoring a measure on the note — keeps that reasoning intact: the column is still what bounds the
    line, it is just no longer allowed to grow with a shell widened for something else.

    The plan grid used to share this 58rem line, deliberately, so the page had one collapse point. It no
    longer does: `.plans` is now `auto-fit` and reflows where its own content needs to. That pairing is
    genuinely lost, and the note at the top of `.plans` records why it was worth losing.
*/
.terms[b-44pvxpr85z] {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-4) var(--space-8);
    max-width: var(--page-max);
    margin: 0;
    padding: 0;
    list-style: none;
}

@media (max-width: 58rem) {
    .terms[b-44pvxpr85z] {
        grid-template-columns: 1fr;
    }
}

.terms__item[b-44pvxpr85z] {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-3);
    align-items: start;
    color: var(--accent);
}

.terms__claim[b-44pvxpr85z] {
    margin: 0;
    color: var(--text-primary);
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
}

.terms__note[b-44pvxpr85z] {
    margin: var(--space-1) 0 0;
    color: var(--text-secondary);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
}

.terms__note strong[b-44pvxpr85z] {
    color: var(--text-primary);
    font-weight: var(--weight-semibold);
}
/* /Marketing/WaitlistForm.razor.rz.scp.css */
/*
    The labelled Cloud waitlist.

    A PANEL, NOT A BAND. Every other section on the pricing page is prose at measure on the page ground; this
    one asks for something, so it is the only element there that sits on its own surface. That is the whole
    visual argument for it — the reader's eye finds one object that is different in kind, once, near the end
    of a long page, and it is the object that wants an action.

    It borrows the plan card's material rather than inventing one: --surface-panel, --radius-lg, the same
    stroke and the same edge-lit inset. A section that asked for an email address in a material found nowhere
    else on the site would read as a third-party embed, which for a form collecting an address is exactly the
    wrong association.
*/
.waitlist[b-ww085291em] {
    max-width: var(--measure);

    padding: var(--space-6);

    background-color: var(--surface-panel);
    border: 1px solid var(--stroke);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-2), var(--edge-lit);
}

.waitlist__heading[b-ww085291em] {
    margin: 0 0 var(--space-2);

    color: var(--text-primary);
    font-family: var(--font-display);
    font-size: var(--text-display-xs);
    font-stretch: var(--display-stretch);
    letter-spacing: var(--tracking-display);
    line-height: var(--leading-tight);
}

.waitlist__body[b-ww085291em] {
    margin: 0 0 var(--space-5);

    color: var(--text-secondary);
    font-size: var(--text-md);
    line-height: var(--leading-relaxed);
    text-wrap: pretty;
}

/*
    THE FORM IS A COLUMN, NOT A ROW, AND THAT IS DELIBERATE.

    An input and a button side by side is the newsletter idiom, and it is the idiom because it is compact —
    not because it is good. It puts the label above a control whose width then fights the button's, it wraps
    unpredictably the moment the label or the button copy is translated, and it makes the button look like
    part of the input rather than a decision. Stacked, the field gets its full measure, CfField's label and
    error land where they land everywhere else in the app, and the button is unmistakably a separate act.
*/
/*
    NO align-items, WHICH IS THE WHOLE FIX.

    This began as `align-items: flex-start` plus `::deep input { width: 100% }`, and the pair defeated itself:
    flex-start makes CfField shrink to fit its own content, so the input's 100% resolved against a 188px
    parent inside a 502px panel — a third of the width, and a rule that reads correct while doing nothing.
    Measured before believing it.

    The default `stretch` is what .signin__form already relies on, and it needs no input rule at all: CfField
    fills the column and its own scoped CSS sizes the control. Matching the incumbent here is not tidiness —
    a second way of laying out a labelled field is a second thing to get wrong.
*/
.waitlist__form[b-ww085291em] {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

/*
    The button, and only the button, stays intrinsic. ::deep because CfButton renders its own markup, so the
    caller's rule would otherwise miss it — the same trap the error banner above records. On a narrow screen
    a full-width "Tell me when Cloud opens" would read as the page's primary act, which it is not: the field
    is where the decision is made, and the button only confirms it.
*/
.waitlist__form[b-ww085291em]  .cf-btn {
    align-self: flex-start;
}

/*
    ::deep, even though this component supplied the class itself.

    A CssClass handed to a child component lands on markup carrying THAT component's scope attribute, so
    `.waitlist__error[b-waitlist]` matches nothing and the rule silently does nothing. Passing the class is
    what makes the selector specific; ::deep is what makes it apply. Caught by
    ClassesPassedToChildComponentsAreStyledThroughDeep, which is the reason that test exists — the failure
    mode is a rule that reads correct and has no effect.
*/
.waitlist[b-ww085291em]  .waitlist__error {
    margin-bottom: var(--space-4);
}

.waitlist__email[b-ww085291em] {
    color: var(--text-primary);
    font-weight: var(--weight-semibold);
    /* An address is data, not prose: it must not be re-flowed mid-word, and it must not be read as a
       sentence fragment. */
    overflow-wrap: anywhere;
}

.waitlist__actions[b-ww085291em] {
    margin-top: var(--space-5);
}

.waitlist__fine[b-ww085291em] {
    margin: var(--space-5) 0 0;

    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    text-wrap: pretty;
}

.waitlist__fine a[b-ww085291em] {
    color: var(--text-secondary);
    text-decoration: underline;
    text-decoration-color: var(--accent-line);
    text-underline-offset: 0.2em;
    transition: text-decoration-color var(--motion-fast) var(--ease-out);
}

.waitlist__fine a:hover[b-ww085291em] {
    text-decoration-color: var(--accent);
}
/* /Marketing/WaitlistUnsubscribe.razor.rz.scp.css */
/*
    Leaving the waitlist.

    NO PANEL, unlike the join form. The join form has to earn attention on a page full of other things; this
    page IS the one thing, reached deliberately by somebody who wants it over with. Wrapping it in a card
    would be decoration on a page whose entire job is to be finished quickly, so it sits at measure on the
    page ground and nothing competes with the field.
*/
.unsubscribe[b-fnnfs9ds42] {
    max-width: var(--measure);
}

/* No align-items, and no input rule — WaitlistForm.razor.css records why both were removed. */
.unsubscribe__form[b-fnnfs9ds42] {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.unsubscribe__form[b-fnnfs9ds42]  .cf-btn {
    align-self: flex-start;
}

/* ::deep for the reason WaitlistForm.razor.css records: the class lands on CfBanner's scoped markup. */
.unsubscribe[b-fnnfs9ds42]  .unsubscribe__error {
    margin-bottom: var(--space-5);
}

.unsubscribe__email[b-fnnfs9ds42] {
    color: var(--text-primary);
    font-weight: var(--weight-semibold);
    overflow-wrap: anywhere;
}

.unsubscribe__fine[b-fnnfs9ds42] {
    margin: var(--space-6) 0 0;

    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    text-wrap: pretty;
}
/* /Pages/NotFound.razor.rz.scp.css */
.notfound[b-b0f36ub8rv] {
    max-width: 34rem;
    padding-block: var(--space-16);
}

/* The code sits above the heading as a label, which is the one place a small line over a title earns its
   keep: it is data — the actual HTTP status — not an eyebrow restating the heading in smaller type. */
.notfound__code[b-b0f36ub8rv] {
    color: var(--text-muted);
    font-size: var(--text-sm);
    letter-spacing: var(--tracking-caption);
}

.notfound__title[b-b0f36ub8rv] {
    margin-block-start: var(--space-3);
}

.notfound__body[b-b0f36ub8rv] {
    color: var(--text-secondary);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    margin-block-start: var(--space-3);
}

.notfound__actions[b-b0f36ub8rv] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-block-start: var(--space-6);
}
/* /SignIn/Callback.razor.rz.scp.css */
.callback[b-rcqxn0peza] {
    display: flex;
    justify-content: center;
    padding-block: var(--space-12);
}

.callback__card[b-rcqxn0peza] {
    width: 100%;
    max-width: 30rem;
}

.callback__title[b-rcqxn0peza] {
    font-size: var(--text-2xl);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-display);
}

.callback__body[b-rcqxn0peza] {
    color: var(--text-secondary);
    font-size: var(--text-md);
    margin-block-start: var(--space-2);
}

/* ::deep — the class was passed to CfSkeleton, so it lands on CfSkeleton's scoped markup. */
.callback__card[b-rcqxn0peza]  .callback__wait {
    margin-block-start: var(--space-6);
}
/* /SignIn/SignIn.razor.rz.scp.css */
/*
    Centred in the viewport, not parked near the top of it. The card sat in the upper third with a large
    void beneath — a single-task page whose task floats above a field of nothing.

    min-height accounts for the sticky header so "centred" means centred in what is actually visible.
*/
.signin[b-3gbhf20vdj] {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: calc(100dvh - var(--header-height) - var(--space-16));
    padding-block: var(--space-12);
}

/* A glass card floating on the light field, rather than copy sitting directly on the page. Sign-in is
   the one public route that is a single focused task, so it gets a container and nothing else does. */
/*
    A glass card lit from behind. The page's light field is a full-viewport wash, so on a short page like
    this one it reads as flat black — the card carries its own local bloom so the world reaches the one
    surface the visitor is looking at.
*/
.signin__card[b-3gbhf20vdj] {
    position: relative;
    width: 100%;
    max-width: 27rem;
    background-color: var(--glass);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-3), var(--glow-cool);
    padding: var(--space-8);
    animation: signin-enter-b-3gbhf20vdj var(--motion-reveal) var(--ease-out) both;
}

/* The bloom sits behind the card rather than on it, so the blur reads as light in the space around the
   glass instead of as a border effect on it. */
.signin__card[b-3gbhf20vdj]::before {
    content: "";
    position: absolute;
    inset: -20%;
    z-index: -1;
    background: radial-gradient(closest-side, var(--field-cool) 0%, transparent 100%);
    pointer-events: none;
}

@keyframes signin-enter-b-3gbhf20vdj {
    from { opacity: 0; transform: translateY(14px); }
    to { opacity: 1; transform: none; }
}

/* The entrance is the only motion here and it is not load-bearing, so reduced motion simply removes it.
   The global reset zeroes the duration; this makes the end state explicit under `both`. */
@media (prefers-reduced-motion: reduce) {
    .signin__card[b-3gbhf20vdj] {
        animation: none;
    }
}

@media (max-width: 32rem) {
    .signin__card[b-3gbhf20vdj] {
        padding: var(--space-5);
    }
}

.signin__form[b-3gbhf20vdj] {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    margin-block-start: var(--space-6);
}

/* ::deep — the class was passed to CfBanner, so it lands on CfBanner's scoped markup. */
.signin__card[b-3gbhf20vdj]  .signin__error {
    margin-block-start: var(--space-5);
}

.signin__body[b-3gbhf20vdj] {
    color: var(--text-secondary);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    margin-block-start: var(--space-4);
}

/* The address is echoed back so a typo is visible before the user goes looking in the wrong inbox. */
.signin__email[b-3gbhf20vdj] {
    color: var(--text-primary);
    font-family: var(--font-mono);
    font-size: 0.95em;
    overflow-wrap: anywhere;
}

.signin__hint[b-3gbhf20vdj] {
    background-color: var(--surface-inset);
    border: 1px solid var(--stroke);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    margin-block-start: var(--space-5);
    padding: var(--space-3);
}

.signin__actions[b-3gbhf20vdj] {
    display: flex;
    justify-content: flex-start;
    margin-block-start: var(--space-5);
}
