/*!
 * Nativa Theme — base layer
 *
 * This design is STANDALONE: the product does not emit its own landing
 * stylesheet when Nativa is active, so everything the page needs is here.
 *
 * Two rules govern colour. The operator's brand colour is seeded AFTER this file
 * as --lp-brand and it always wins, so every accent below paints with it rather
 * than with a literal. The warm tints the design is built on are derived from
 * that same colour with color-mix, each one preceded by the value Nativa was
 * drawn with, so a browser that does not understand color-mix still gets the
 * intended shade instead of nothing.
 */

/* ── Poppins, served from the package (SIL Open Font License 1.1) ─────────── */
@font-face {
    font-family: 'Nativa Poppins';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/poppins-400-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Nativa Poppins';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('fonts/poppins-400-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Nativa Poppins';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('fonts/poppins-500-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Nativa Poppins';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('fonts/poppins-500-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Nativa Poppins';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('fonts/poppins-600-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Nativa Poppins';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('fonts/poppins-600-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Nativa Poppins';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('fonts/poppins-700-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Nativa Poppins';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('fonts/poppins-700-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ── Tokens ───────────────────────────────────────────────────────────────── */
body.lp[data-lp-template='nativa'],
[data-rf-theme='nativa'] {
    --nv-brand: var(--lp-brand, #f7c600);
    --nv-on-brand: var(--lp-on-brand, #1b1b1b);
    /* The reference's neutral ramp is SEVEN steps, measured on screen. This
       package had four and shared the texts between them, so 47 of them came out
       in the neighbouring grey. Steps 3, 4 and 6 are the ones that were missing.
       The older names stay as aliases of their ORIGINAL value, so widening the
       ramp cannot move anything that was already right. */
    --nv-ink: #1b1b1b;      /* 27  */
    --nv-ink-2: #4a4a4a;    /* 74  */
    --nv-ink-3: #5f5f5f;    /* 95  */
    --nv-ink-4: #6b6b6b;    /* 107 */
    --nv-ink-5: #7a7a7a;    /* 122 */
    --nv-ink-6: #8a8a8a;    /* 138 */
    --nv-ink-7: #9a9a9a;    /* 154 */
    --nv-ink-soft: var(--nv-ink-2);
    --nv-muted: var(--nv-ink-5);
    --nv-muted-2: var(--nv-ink-7);
    --nv-white: #fff;

    /* Warm tints. Literal first (the shade Nativa was drawn with), then the
       same shade derived from whatever colour the operator picked. */
    --nv-paper: #fdf6dc;
    --nv-paper: color-mix(in srgb, var(--nv-brand) 13%, #fff);
    --nv-paper-2: #fef9e8;
    --nv-paper-2: color-mix(in srgb, var(--nv-brand) 7%, #fff);
    --nv-soft: #fdf0c2;
    --nv-soft: color-mix(in srgb, var(--nv-brand) 24%, #fff);
    --nv-light: #ffe27a;
    --nv-light: color-mix(in srgb, var(--nv-brand) 52%, #fff);
    /* Both ambers darken against BLACK, not against the ink: mixing with #1b1b1b
       pushed in 6 points of blue the reference does not have and left the shade
       muddy. Against black, at these percentages, the mockup's brand lands within
       3-4 points of 255 of the drawn value — invisible to the eye and, unlike
       hard-coding the literal, still whatever colour the operator picked. */
    --nv-deep: #c99a00;
    --nv-deep: color-mix(in srgb, var(--nv-brand) 80%, #000);
    --nv-deeper: #7a6200;
    --nv-deeper: color-mix(in srgb, var(--nv-brand) 49.4%, #000);
    --nv-line: #f1ecd9;
    --nv-line: color-mix(in srgb, var(--nv-brand) 10%, #ece9e0);
    --nv-line-2: #ece7d3;
    --nv-line-2: color-mix(in srgb, var(--nv-brand) 14%, #e7e4da);

    --nv-shadow-sm: 0 4px 14px rgba(0, 0, 0, .05);
    --nv-shadow: 0 10px 30px rgba(0, 0, 0, .05);
    --nv-shadow-md: 0 12px 30px rgba(0, 0, 0, .1);
    --nv-shadow-lg: 0 16px 40px rgba(0, 0, 0, .14);
    --nv-shadow-brand: 0 8px 20px color-mix(in srgb, var(--nv-brand) 35%, transparent);

    --nv-wrap: 1180px;
    --nv-pad: clamp(20px, 4vw, 40px);
    /* Fixed-header height. The design draws 73 px of clear sky below the bar,
       not 76 (the rendered height): the next block sits 3 px under the edge,
       which matches what was drawn. */
    --nv-head: 73px;
    --nv-ease: cubic-bezier(.2, .7, .2, 1);
    --nv-font: 'Nativa Poppins', system-ui, -apple-system, Segoe UI, sans-serif;
}

/* ── Reset and page ───────────────────────────────────────────────────────── */
html {
    scroll-behavior: smooth;
    /* The product's nav navigates by anchor (#networks, #faq…) and the bar above
       is out of flow, so without this the destination's first lines land under
       it. The reference has the same fixed bar and does NOT declare this — its
       anchors land under the header too. That is a defect of the reference, not
       a decision to copy.

       THE VALUE IS REDECLARED HERE AND THAT IS THE WHOLE POINT. Every other
       --nv-* token is declared on [data-rf-theme='nativa'] / body.lp — which is
       the BODY — and custom properties inherit DOWNWARDS, so `html` could never
       read one. `var(--nv-head)` therefore failed at computed-value time and the
       declaration fell back to `auto`: this rule had never once run. Clicking
       "Services" in the landing nav put 76px of the section behind the bar, which
       is exactly the defect the rule was written to prevent. It is a literal and
       not a var() on purpose — the only scope that can hold it is the one scope
       the theme does not own, so a token here would have to be declared twice
       anyway, and two declarations of one number is how they drift apart.

       Why 100 and not 73: the rails (.nv-art-aside, .nv-faqp-rail) and the
       article's own scroll-margin-top already stop at 100, which is the bar plus
       the 24px of air the design leaves under it. A destination that lands level
       with the rail beside it is the same page; one that lands 27px higher is a
       second, quieter mismatch.

       Scoped by the SHEET, not by a selector: this file only ships while the
       panel is wearing Nativa, so an `html` rule here cannot reach another
       design. */
    scroll-padding-top: 100px;
}

body.lp[data-lp-template='nativa'] {
    margin: 0;
    padding: 0;
    background: var(--nv-white);
    color: var(--nv-ink);
    font-family: var(--nv-font);
    font-size: 15px;
    /* No line-height on purpose: the reference never declares one and leaves
       Poppins at `normal`. A 1.6 inherited from here raised every line on the page
       and added 882px of height — the drift that pushed EVERYTHING out of place.
       A block that needs different leading declares it, and only if the
       reference does. */
    text-wrap: pretty;
    -webkit-font-smoothing: antialiased;
    /* `clip`, not `hidden`. Both stop the sideways overflow the floating orbs
       would otherwise cause, but `hidden` turns the body into a scroll container,
       and a `position: sticky` descendant then sticks to a box that never
       scrolls — which is why the FAQ column refused to ride down the page. */
    overflow-x: clip;
}

:where(body.lp[data-lp-template='nativa']) :where(*, *::before, *::after) {
    box-sizing: border-box;
}

:where(body.lp[data-lp-template='nativa']) :where(h1, h2, h3, h4, p, figure, ul, ol) {
    margin: 0;
}

:where(body.lp[data-lp-template='nativa']) :where(ul, ol) {
    padding: 0;
    list-style: none;
}

:where(body.lp[data-lp-template='nativa']) a {
    color: var(--nv-ink);
    text-decoration: none;
    transition: color .25s;
}

:where(body.lp[data-lp-template='nativa']) a:hover {
    color: var(--nv-deep);
}

:where(body.lp[data-lp-template='nativa']) :where(img, svg) {
    max-width: 100%;
}

:where(body.lp[data-lp-template='nativa']) :where(button, input, select, textarea) {
    font: inherit;
    color: inherit;
}

:where(body.lp[data-lp-template='nativa']) input::placeholder {
    color: var(--nv-muted-2);
}

:where(body.lp[data-lp-template='nativa']) :focus-visible {
    outline: 2px solid var(--nv-brand);
    outline-offset: 2px;
}

:where(body.lp[data-lp-template='nativa']) [hidden] {
    display: none !important;
}

/* ── Layout primitives ────────────────────────────────────────────────────── */
.lp-wrap,
.nv-wrap {
    /* --nv-wrap is the CONTENT width (1180 px, what the reference measures inside
       the padding). Because the theme is border-box throughout, padding eats into
       max-width — so the rail is added back so the element reaches 1260 px and
       the content area inside it is the intended 1180 px. */
    max-width: calc(var(--nv-wrap) + var(--nv-pad) * 2);
    margin: 0 auto;
    padding: 0 var(--nv-pad);
}

/* 96px is the air the reference gives a section, measured on screen; this was 90,
   which slid every block a few pixels against the one above it. Not all of them
   carry it on top: the reference runs several flush against the previous block
   (padding-top: 0) so the page breathes in stretches rather than at an even beat —
   each one declares that in its own file. */
.lp-section {
    padding: clamp(56px, 7vw, 96px) 0;
}

.lp-section-surface {
    background: var(--nv-paper);
}

.lp-section-alt {
    background: var(--nv-paper-2);
}

.lp-narrow {
    max-width: 760px;
    margin: 0 auto;
}

.lp-grid {
    display: grid;
    gap: 24px;
}

.lp-grid-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.lp-grid-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* ── Type ─────────────────────────────────────────────────────────────────── */
.lp-eyebrow,
.nv-kicker {
    margin: 0 0 14px;
    color: var(--nv-deep);
    font-size: 15px;
    font-weight: 600;
}

.lp-h2,
.nv-h2 {
    margin: 0;
    font-size: clamp(28px, 3.2vw, 40px);
    line-height: 1.2;
    font-weight: 700;
    color: var(--nv-ink);
    text-wrap: balance;
}

.lp-lead,
.nv-lead {
    margin: 16px 0 0;
    font-size: 14px;
    line-height: 1.75;
    color: var(--nv-ink-3);
}

.nv-head {
    text-align: center;
    max-width: 640px;
    margin: 0 auto 44px;
}

.nv-head .lp-lead {
    max-width: 60ch;
    margin-inline: auto;
}

/* ── Buttons ──────────────────────────────────────────────────────────────── */
.lp-btn,
.nv-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 14px 28px;
    border: 0;
    border-radius: 999px;
    background: var(--nv-ink);
    color: var(--nv-white);
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    transition: transform .25s var(--nv-ease), box-shadow .25s, background .25s, color .25s;
}

.lp-btn:hover,
.nv-btn:hover {
    transform: translateY(-2px);
    box-shadow: var(--nv-shadow-brand);
    color: var(--nv-white);
}

.lp-btn-primary,
.nv-btn-brand {
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

.lp-btn-primary:hover,
.nv-btn-brand:hover {
    color: var(--nv-on-brand);
}

.lp-btn-outline,
.nv-btn-outline {
    background: var(--nv-white);
    color: var(--nv-ink);
    border: 1.5px solid var(--nv-ink);
    font-weight: 500;
}

.lp-btn-outline:hover,
.nv-btn-outline:hover {
    background: var(--nv-ink);
    color: var(--nv-white);
}

.lp-btn-ghost-d {
    background: transparent;
    color: var(--nv-ink);
    border: 1.5px solid var(--nv-line-2);
}

.lp-btn-lg {
    padding: 16px 34px;
    font-size: 16px;
}

.lp-link-muted {
    display: inline-flex;
    align-items: center;
    font-weight: 500;
    color: var(--nv-ink);
}

.nv-link-underline {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 2px;
    border-bottom: 2px solid var(--nv-brand);
    font-size: 14px;
    font-weight: 600;
    color: var(--nv-ink);
}

/* ── Chips, badges, cards ─────────────────────────────────────────────────── */
.lp-badge,
.nv-badge {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px 8px 10px;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .06);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--nv-deeper);
}

.lp-badge-dot,
.nv-dot {
    width: 8px;
    height: 8px;
    flex: none;
    border-radius: 50%;
    background: var(--nv-brand);
    box-shadow: 0 0 0 4px var(--nv-soft);
}

.lp-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--nv-soft);
    color: var(--nv-deeper);
    font-size: 12px;
    font-weight: 600;
}

.lp-card,
.nv-card {
    padding: 28px;
    border-radius: 22px;
    background: var(--nv-white);
    box-shadow: var(--nv-shadow);
    transition: transform .35s var(--nv-ease), box-shadow .35s;
}

.nv-card-hover:hover,
.lp-card:hover {
    transform: translateY(-6px);
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
}

.nv-ico {
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    border-radius: 14px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

/* ── Motion ───────────────────────────────────────────────────────────────── */
/* The product reveals with .lp-in once its observer sees the block; without JS
   nothing is ever hidden (the html.lp-js guard below is the product's own). */
.lp-js [data-reveal] {
    opacity: 0;
    transform: translateY(30px);
    transition: opacity .8s var(--nv-ease), transform .8s var(--nv-ease);
}

.lp-js [data-reveal].lp-in {
    opacity: 1;
    transform: none;
}

/* The three directions the design reveals from. Written as overrides of the
   rule above so a block declares WHERE it comes from and inherits the same
   timing — the alternative was every block restating the transition and the
   page ending up with four slightly different easings. */
.lp-js [data-reveal="left"] {
    transform: translateX(-50px);
}

.lp-js [data-reveal="right"] {
    transform: translateX(50px);
}

.lp-js [data-reveal="zoom"] {
    transform: scale(.92);
}

/* The lift a button and a card do under the pointer, shared for the same reason
   as the reveal: every block was writing its own and they were drifting by a
   pixel and fifty milliseconds.

   `translate` rather than `transform`, and that is the whole point: the reveal
   above animates `transform` and wins the specificity it needs to. An element
   that both reveals and lifts would lose its hover in silence once revealed if
   the two fought over one property. Separate properties compose instead. */
[data-btn] {
    transition: translate .25s var(--nv-ease), box-shadow .25s, background .25s;
}

[data-btn]:hover {
    translate: 0 -2px;
    box-shadow: 0 10px 24px color-mix(in srgb, var(--nv-brand) 35%, transparent);
}

[data-card] {
    transition: translate .35s var(--nv-ease), box-shadow .35s;
}

[data-card]:hover {
    translate: 0 -6px;
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
}

/* Decoration that drifts. Never put on something a visitor has to read or
   click: it would move under the pointer. */
[data-float] {
    animation: nv-float 4s ease-in-out infinite;
}

[data-float="2"] {
    animation-duration: 5s;
    animation-delay: -1.5s;
}

[data-float="3"] {
    animation-duration: 6s;
    animation-delay: -3s;
}

.nv-float {
    animation: nv-float 4s ease-in-out infinite;
}

.nv-float-2 {
    animation: nv-float 5s ease-in-out infinite;
    animation-delay: -1.5s;
}

.nv-float-3 {
    animation: nv-float 6s ease-in-out infinite;
    animation-delay: -3s;
}

@keyframes nv-float {
    0%, 100% { translate: 0 0; }
    50% { translate: 0 -12px; }
}

.nv-caret {
    display: inline-block;
    width: 4px;
    height: .8em;
    margin-left: 6px;
    vertical-align: -.06em;
    border-radius: 2px;
    background: var(--nv-ink);
    animation: nv-blink 1s steps(2, start) infinite;
}

@keyframes nv-blink {
    to { visibility: hidden; }
}

/* A drawn ring leaving the element it sits on: it grows to three times its size
   and fades out over the cycle. Measured on the reference — a ring at 0.7 alpha
   scaling to 3× is what reads as "live" on the head of the growth line, where a
   soft halo read as a blur. */
@keyframes nv-pulse-ring {
    0% { transform: scale(1); opacity: .7; }
    100% { transform: scale(3); opacity: 0; }
}

@keyframes nv-msg-in {
    from { opacity: 0; transform: translateY(10px) scale(.97); }
    to { opacity: 1; transform: none; }
}

@keyframes nv-dot-bounce {
    0%, 80%, 100% { transform: translateY(0); }
    40% { transform: translateY(-4px); }
}

@keyframes nv-marquee {
    from { transform: translateX(0); }
    to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
    /* Both public surfaces: the landing marks itself with data-lp-template and
       the content pages with data-rf-theme. Scoped to one of them only, a
       visitor who asked the operating system to stop animations still got the
       blog moving. */
    :where(body.lp[data-lp-template='nativa'], body[data-rf-theme='nativa']) * {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ── Line height on the content pages ─────────────────────────────────────────
   The landing is standalone and inherits nothing, but the blog, the article, the
   FAQ and the legal pages run ON TOP of the product's compiled bundle, whose
   reset declares `line-height: 1.5` at the root. The reference declares none at
   all — it leaves Poppins' own `normal`, about 7% tighter — and that difference
   alone put 17px under the footer and pushed eighteen lines out of place.

   Declared on the surfaces THIS theme draws and never on the root: the FAQ and
   the legal pages are still the product's screens, written against 1.5, and
   tightening them would be changing a page nobody asked us to touch. Every
   block that sets its own line height (the footer blurb at 1.8, the leads at
   1.7) keeps winning — this only replaces what was being inherited. */
:where(.nv-pubhead, .nv-footer, .nv-posts, .nv-article-page) {
    line-height: normal;
}

/* ── Scroll progress + back to top (injected at body end) ─────────────────── */
/* Both nodes are built by 05-scroll.js and live on the LANDING only, which is
   where the reference draws BOTH of them. Its article export carries a rail too
   — the same 4px one — but it measures the prose rather than the page, so that
   one is .nv-read-progress and it is built by the article script; the article
   has no back-to-top button in the reference, and neither has the blog list. */
.nv-progress {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    /* 4px is the reference's rail, on the landing and on the article alike. */
    height: 4px;
    z-index: 60;
    /* The unfilled rail is visible in the reference: ink at 6%, not transparent,
       so the bar reads as a track that fills rather than a line that grows. */
    background: color-mix(in srgb, var(--nv-ink) 6%, transparent);
    pointer-events: none;
}

.nv-progress i {
    display: block;
    height: 100%;
    width: 0;
    background: var(--nv-brand);
    transition: width .1s linear;
}

.nv-totop {
    position: fixed;
    right: 24px;
    bottom: 24px;
    /* Same layer as the progress bar, and for the same reason: above this
       theme's fixed header (50) and below the product's own overlays. */
    z-index: 60;
    width: 56px;
    height: 56px;
    display: grid;
    place-items: center;
    border: 0;
    padding: 0;
    border-radius: 50%;
    background: transparent;
    opacity: 0;
    transform: translateY(16px);
    pointer-events: none;
    /* `visibility` is in the transition on purpose (05-scroll.css sets it):
       as a discrete property it flips at the END of the duration when hiding,
       so the fade-out plays in full, and immediately when showing. Without it
       here the button would vanish before it had faded. */
    transition: opacity .35s, transform .35s, visibility .35s;
    cursor: pointer;
}

.nv-totop.is-on {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}

/* Direct child only. The chevron is a second <svg> INSIDE the span, and a
   descendant selector would rip it out of the disc and rotate it too. */
.nv-totop > svg {
    position: absolute;
    inset: 0;
    transform: rotate(-90deg);
}

.nv-totop span {
    position: relative;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--nv-ink);
    color: var(--nv-brand);
    box-shadow: 0 8px 20px rgba(0, 0, 0, .18);
    transition: transform .25s, background .25s;
}

/* The reference darkens the disc to pure black on hover. Derived from the ink
   token rather than written as #000 so an operator who themes the ink keeps a
   hover state that belongs to their palette. */
.nv-totop:hover span {
    transform: translateY(-2px);
    background: color-mix(in srgb, var(--nv-ink) 70%, #000);
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
    .lp-grid-3 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 640px) {
    .lp-grid-2,
    .lp-grid-3 {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ── Shared layout hooks ──────────────────────────────────────────────────────
   The design carries its responsive decisions on the elements themselves, as
   data attributes, rather than in a per-block breakpoint. Copied here with the
   designer's own numbers so a block declares WHAT it does on a small screen
   ([data-cols]) instead of each block writing its own media query and drifting.

   The product's own reveal hook stays as it is above: [data-reveal] is the
   product's, these are the layout ones. */
[data-cols],
[data-cols-2] {
    min-width: 0;
}

@media (max-width: 900px) {
    /* One column. The design's own rule, and it uses !important for the same
       reason we keep it: a block's grid-template-columns is a more specific
       declaration than this attribute selector. */
    [data-cols] {
        grid-template-columns: minmax(0, 1fr) !important;
    }

    [data-cols-2] {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    }

    /* Decoration that has no room left. Never applied to content. */
    [data-hide-sm] {
        display: none !important;
    }

    /* Stacking puts the artwork under the words it illustrates; this pulls the
       piece that has to lead back to the top. */
    [data-order-first] {
        order: -1;
    }
}

@media (max-width: 560px) {
    [data-cols-2] {
        grid-template-columns: minmax(0, 1fr) !important;
    }
}

/* Nothing on a phone should be able to push the page sideways: a hero orb or a
   floating card that overflows turns into horizontal scroll on every screen.
   `clip` rather than `hidden` so a sticky column still works. */
html,
body {
    overflow-x: clip;
}

/* ── Brand logo that follows the light/dark switch ────────────────────────
   The panel prints BOTH variants when the operator picks "Both" under
   Branding, and the stylesheet decides which one is on screen. This design is
   STANDALONE on the landing, which means it receives none of the product's own
   CSS there — without these three rules a visitor would see both logos at once,
   stacked. The content pages and the sign-in do get the core bundle, so there
   they are simply redundant, which is cheaper than a rule that only exists on
   half the pages this package dresses.

   The class is doubled on purpose: a plain `.rf-logo-ondark` is (0,1,0) and
   loses to this package's own `.nv-drawer-brand img { display: block }`, which
   is (0,1,1) — measured, the switch simply did not apply. Repeating it makes it
   (0,2,0) and it outranks every reset of that shape in this file. */
.rf-logo-ondark.rf-logo-ondark { display: none; }
html.dark .rf-logo-onlight.rf-logo-onlight,
html[data-theme="dark"] .rf-logo-onlight.rf-logo-onlight { display: none; }
html.dark .rf-logo-ondark.rf-logo-ondark,
html[data-theme="dark"] .rf-logo-ondark.rf-logo-ondark { display: block; }

/* ── Scroll progress bar + back-to-top button ──────────────────────────────
   Both nodes are injected into the body by 05-scroll.js; this file supplies
   only what 00-base.css does not already declare.

   00-base.css owns the layout rules for .nv-progress and .nv-totop (position,
   size, z-index: 60, transition, .is-on toggle) so this file does not repeat
   them. It adds:
     — The brand gradient on the progress fill (base has a plain brand fill
       used as the design baseline; the gradient matches the reference).
     — The SVG ring colours (rail + active arc), expressed with theme tokens
       so the design adapts to any operator brand without CSS changes.
     — The accessibility fix: `visibility: hidden` on the hidden button so it
       is removed from the tab order and from assistive-technology trees when
       not on screen. `opacity: 0` hides it visually but leaves it reachable
       by keyboard, which means a screen-reader user would encounter a button
       that appears to do nothing — the scroll position is already at the top.
       `visibility: hidden` is chosen over `inert` because `inert` does not
       participate in CSS transitions and the button's reveal uses a
       `transition: visibility .35s` trick (a delay equal to the opacity
       transition keeps the element in the flow long enough for the fade-out
       to play before it disappears from accessibility trees entirely).
     — The small-screen position adjustment (480 px, from the reference).

   z-index: 60 — WHY NOT 1000 (the reference value)
   The product's fixed header lives at z-index: 50 (deliberately kept below
   the product's own modals and drawers). The progress bar needs to sit on
   top of that header, so 60 is sufficient; 1000 would compete with the
   product's own overlay stack and bury modals under the bar. Same logic for
   the button. */

/* ── Progress bar fill: gradient ────────────────────────────────────────── */

/* The reference paints `#f7c600 → #ffdd55`. In the token system, --nv-brand
   is the base hue and --nv-light is `color-mix(in srgb, var(--nv-brand) 52%,
   #fff)` — the lighter warm amber the reference uses as the second stop.
   The glow reuses the same brand-to-transparent mix already declared as
   --nv-shadow-brand; a separate rgba literal would diverge from the operator's
   colour. */
.nv-progress i {
    background: linear-gradient(
        90deg,
        var(--nv-brand),
        var(--nv-light)
    );
    box-shadow: 0 0 12px color-mix(in srgb, var(--nv-brand) 70%, transparent);
}

/* ── Back-to-top: accessibility — visibility follows opacity ─────────────── */

/* `pointer-events: none` (already in 00-base.css for the hidden state) stops
   the mouse, but the button stays in the tab order and in the accessibility
   tree — a screen-reader user would meet a control that does nothing, because
   the page is already at the top. `visibility: hidden` removes it from both.

   Chosen over `inert`, which is not a CSS property and therefore cannot be
   coordinated with the fade: toggling it from the script would strip the
   button from the accessibility tree mid-animation. `visibility` IS
   transitionable (as a discrete property it flips at the end of the duration
   when hiding), and 00-base.css lists it in the transition for exactly that. */
.nv-totop {
    visibility: hidden;
}

.nv-totop.is-on {
    visibility: visible;
}

/* ── Back-to-top: SVG ring colours ──────────────────────────────────────── */

/* The rail circle (first child, fill = white, stroke = soft warm line).
   `fill` and `stroke` as CSS properties override SVG presentation attributes,
   so the HTML does not need to be re-generated if the tokens change. */
.nv-totop-rail {
    fill: var(--nv-white);
    stroke: var(--nv-line);
    stroke-width: 3;
}

/* The active arc (second child). The fill is transparent; only the stroke
   advances. `stroke-dashoffset` is set by the script; the transition here
   gives it the same .1 s linear ease the reference uses. */
.nv-totop-arc {
    fill: none;
    stroke: var(--nv-brand);
    stroke-width: 3;
    stroke-linecap: round;
    transition: stroke-dashoffset .1s linear;
}

/* ── Back-to-top: small screen position ─────────────────────────────────── */

@media (max-width: 480px) {
    .nv-totop {
        right: 14px;
        bottom: 14px;
    }
}

/* ── Header ───────────────────────────────────────────────────────────────────
   ONE bar for the two public surfaces. The product renders the landing header
   itself, so Nativa dresses the markup it emits (.lp-header / .lp-headrow /
   .lp-brand / .lp-nav / .lp-headcta); the content pages (blog, article, FAQ,
   terms, /p/{slug}, catalogue) get the same bar from the theme's own
   public-header partial (.nv-pubhead). Every number below is the reference's:
   16px rail padding, a 32px gap, 30px between links, 10px/22px pills.

   The design's z-index is 900 and that one number is NOT copied. It would sit
   above this theme's own reading-progress bar (60) and above the product's
   modals, so the header keeps the product's own layer instead: a bar that
   covers a dialog is a bug, not a design. */

.lp-header,
.nv-pubhead {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    /* The design's z-index is 900 and that one number is NOT copied. It would sit
       above this theme's own reading-progress bar (60) and above the product's
       modals, so the header keeps the product's own layer instead: a bar that
       covers a dialog is a bug, not a design.
       NOTE: fixed is used instead of sticky because the content pages set
       overflow-x:clip on the body, which (when combined with height:100% on the
       scroll container) promotes the body to a scroll port and leaves sticky
       glued to a box that never scrolls — measured at scrollY=1200 the sticky
       bar sat at top:-472px. fixed resolves against the viewport on both surfaces. */
    z-index: 50;
    background: rgba(255, 255, 255, .92);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--nv-line);
    box-shadow: 0 6px 24px rgba(0, 0, 0, .05);
}

/* Landing compensator. The landing header is emitted by the product; the theme
   cannot insert a sibling spacer. padding-top on the body pushes the first section
   down by the header height. The preview banner (?preview_landing=) is the first
   child of body: with fixed position the banner appears correctly below the header,
   which is the right behaviour — it is not part of the page content. */
body.lp[data-lp-template='nativa'] {
    padding-top: var(--nv-head);
}

/* The content pages are dressed by the product's compiled bundle, which knows
   nothing about this design's typeface. Scoped to the bar so the theme sets the
   font where it owns the markup and nowhere else. */
.nv-pubhead {
    font-family: var(--nv-font);
    color: var(--nv-ink);
}

/* Content-page compensator. The theme owns this partial, so it inserts a sibling
   spacer directly after </header>. Sized to --nv-head to stay in sync with the
   variable and never need an independent update. */
.nv-pubhead-spacer {
    height: var(--nv-head);
}

.lp-headrow,
.nv-pubhead-row {
    display: flex;
    align-items: center;
    gap: 32px;
    padding-top: 16px;
    padding-bottom: 16px;
}

.lp-brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    /* The name is the operator's and can be long. It shrinks and truncates
       instead of wrapping: two lines of brand double the height of a sticky bar
       on the screen that has the least of it. */
    min-width: 0;
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -.02em;
    color: var(--nv-ink);
    text-decoration: none;
}

.lp-brand-name {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.lp-brand-logo {
    display: block;
    height: 34px;
    max-width: 190px;
    object-fit: contain;
}

.lp-brand-mark {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 9px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 16px;
    font-weight: 700;
}

.lp-nav,
.nv-pubnav {
    display: flex;
    gap: 30px;
    margin-left: auto;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -.005em;
    color: var(--nv-ink);
}

.lp-nav a,
.nv-pubnav a {
    color: var(--nv-ink);
    text-decoration: none;
    transition: color .25s;
}

.lp-nav a:hover,
.nv-pubnav a:hover {
    color: var(--nv-ink);
}

/* The page you are on. The reference underlines it in the brand colour; the
   attribute is the markup's own answer to "which one is current", so no extra
   class has to be kept in sync with the router. */
.nv-pubnav a[aria-current='page'] {
    padding-bottom: 2px;
    border-bottom: 2px solid var(--nv-brand);
    color: var(--nv-ink);
    font-weight: 600;
}

.lp-headcta,
.nv-pubcta {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-left: auto;
}

/* The product emits "Sign in" as lp-link-muted and "Get started" as lp-btn-primary.
   The design reverses the visual weight: "Sign up" (register) is the quiet outlined
   pill and "Sign in" (login) is the brand pill. Nativa achieves this with CSS alone,
   without touching the product's markup or routing.

   On the landing: lp-link-muted → brand pill; lp-btn-primary → outlined pill.
   On content pages: the theme's own partial emits the classes in the correct order
   (lp-btn-outline for register, lp-btn-primary for login), so no flip is needed. */

/* Landing — "Sign in" link: make it the brand pill, and send it AFTER the
   register pill. The reference puts the quiet "Sign up" first and closes the bar
   with the brand pill, which is the order the eye reads as "or just sign in".
   The product emits them the other way round and that markup belongs to the
   core, so the order is expressed here — the only lever a design has over a bar
   it does not write. `order` moves the painted box and NOT the tab sequence:
   a keyboard reaches Sign in before Sign up, the same as the document says.
   Both entries are labelled, so the two orders never disagree about meaning. */
.lp-headcta .lp-link-muted {
    order: 2;
    padding: 10px 22px;
    border-radius: 999px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 14px;
    font-weight: 600;
    opacity: 1;
    text-decoration: none;
    transition: filter .25s;
}

.lp-headcta .lp-link-muted:hover {
    opacity: 1;
    filter: brightness(1.07);
}

/* Landing — "Get started" button: make it the outlined pill.
   The product's gradient and shadow are overridden so only the border survives. */
.lp-headcta .lp-btn-primary {
    background: transparent;
    color: var(--nv-ink);
    border: 1.5px solid var(--nv-ink);
    box-shadow: none;
    filter: none;
    font-weight: 500;
}

.lp-headcta .lp-btn-primary:hover {
    background: var(--nv-ink);
    color: var(--nv-white);
    filter: none;
    transform: none;
}

.lp-headcta .lp-btn,
.nv-pubcta .lp-btn {
    padding: 10px 22px;
    font-size: 14px;
    /* A pill is a pill on every screen: "Go to dashboard" broken over two lines
       makes the bar grow and the label read like two controls. */
    white-space: nowrap;
}

/* Content pages — the theme's partial already emits the correct class per role,
   so these only need size and colour, nothing structural. */
.nv-pubcta .lp-btn-outline {
    border: 1.5px solid var(--nv-ink);
    background: transparent;
    color: var(--nv-ink);
    font-weight: 500;
    transition: background .25s, color .25s;
}

.nv-pubcta .lp-btn-outline:hover {
    background: var(--nv-ink);
    color: var(--nv-white);
}

.nv-pubcta .lp-btn-primary {
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-weight: 600;
}

/* The dark/light control. It started on the content pages, where the product
   had always carried one, and the landing now emits the same control as
   `.lp-theme` — so the two are dressed by ONE rule. Drawn as a quiet square next
   to the pills rather than a third pill: it switches a preference, it does not
   ask for anything.

   The two never diverge because they are the same declaration, which matters
   more here than it looks: a visitor meets this control on the home page and
   then again on the blog, and a square that changes shape between them reads as
   two different buttons doing two different things. */
.nv-themebtn,
.lp-theme {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    flex: none;
    border: 1.5px solid var(--nv-line-2);
    border-radius: 12px;
    background: var(--nv-white);
    color: var(--nv-ink);
    cursor: pointer;
    transition: background .25s, color .25s;
}

.nv-themebtn:hover,
.lp-theme:hover {
    background: var(--nv-paper);
}

/* The product hides the moon in dark and the sun in light with its own
   stylesheet, which a standalone design does not receive. */
.lp-theme span {
    display: inline-flex;
}

.lp-theme .lp-theme-sun {
    display: none;
}

html.dark .lp-theme .lp-theme-moon {
    display: none;
}

html.dark .lp-theme .lp-theme-sun {
    display: inline-flex;
}

/* ── Burger + drawer ──────────────────────────────────────────────────────────
   The burger is 44×44 with a 12px radius and a 1.5px warm border, exactly as the
   reference draws it, and it is DISPLAY:NONE until 10-nav.js has marked the
   header ready. A control that cannot open anything is worse than no control, so
   without the script the bar keeps the scrolling link row further down instead.

   The drawer hangs off the header rather than covering the screen: the bar is
   sticky, so it is already the positioning context, and the visitor keeps sight
   of where they are. */

/* `.lp-burger` is the product's own menu button (core 1.9.0+). The theme dresses
   it instead of building a second one — see 10-nav.js — so both surfaces show
   one control wearing the same skin. */
.nv-burger,
.lp-burger {
    display: none;
    width: 44px;
    height: 44px;
    flex: none;
    place-items: center;
    border: 1.5px solid var(--nv-line-2);
    border-radius: 12px;
    background: var(--nv-white);
    color: var(--nv-ink);
    cursor: pointer;
    transition: background .25s;
}

.nv-burger:hover,
.lp-burger:hover {
    background: var(--nv-paper);
}

/* The BARS inside the product's button. `.lp-burger-bars i` is core CSS, and a
   standalone theme is not sent the core sheet — so dressing only the button left
   a 44px white square with nothing drawn in it: a control that is on the screen
   and invisible, on a white bar, which is exactly how it was reported. Anything
   a theme adopts from the product has to be dressed down to its last child. */
.lp-burger-bars {
    display: block;
    width: 18px;
}

.lp-burger-bars i {
    display: block;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform .22s ease, opacity .18s;
}

.lp-burger-bars i + i {
    margin-top: 4px;
}

.lp-drawer-on .lp-burger-bars i:nth-child(1) {
    transform: translateY(6px) rotate(45deg);
}

.lp-drawer-on .lp-burger-bars i:nth-child(2) {
    opacity: 0;
}

.lp-drawer-on .lp-burger-bars i:nth-child(3) {
    transform: translateY(-6px) rotate(-45deg);
}

/* Which of the two icons is showing is a function of the button's own state, so
   nothing has to be toggled in script beyond aria-expanded. */
.nv-burger-close,
.nv-burger[aria-expanded='true'] .nv-burger-open {
    display: none;
}

.nv-burger[aria-expanded='true'] .nv-burger-close {
    display: block;
}

/* ── The phone menu ───────────────────────────────────────────────────────────
   A SIDE PANEL, not a sheet dropped under the bar. The sheet was the shape the
   reference drew, and on a real panel it read as a plain list of text: it grew
   with however many links the operator had, it could not hold the sign-in pair
   as anything but two more rows, and it covered the page it belonged to. The
   panel is the shape a phone already teaches — it slides in, it dims what is
   behind it, and its height is its own.

   It sits OUTSIDE the header in the document (see the partial): the bar carries
   backdrop-filter, and such an ancestor becomes the containing block of any
   `fixed` descendant, which would trap the panel in the 76px strip the bar
   occupies. */
.nv-drawer,
.lp-drawer {
    display: none;
    position: fixed;
    inset: 0;
    /* One above the header's own 50: the panel is a response to a control in the
       bar, so it belongs over it — and still under the product's modals. */
    z-index: 55;
}

.nv-drawer-veil,
.lp-drawer-veil {
    position: absolute;
    inset: 0;
    background: color-mix(in srgb, var(--nv-ink) 55%, transparent);
    backdrop-filter: blur(2px);
    opacity: 0;
    transition: opacity .24s ease;
}

.nv-drawer-panel,
.lp-drawer-panel {
    position: absolute;
    inset-block: 0;
    /* Slides out of the INLINE end, so it arrives from the right in English and
       from the left in Arabic without a second rule. */
    inset-inline-end: 0;
    width: min(320px, 86vw);
    display: flex;
    flex-direction: column;
    background: var(--nv-white);
    border-inline-start: 1.5px solid var(--nv-line-2);
    box-shadow: -26px 0 64px -32px rgba(0, 0, 0, .5);
    transform: translateX(100%);
    transition: transform .28s cubic-bezier(.4, 0, .2, 1);
    /* Taller than the screen on a short phone in landscape: the panel scrolls
       itself instead of hiding its own last entries under the fold. */
    overflow-y: auto;
    overscroll-behavior: contain;
}

[dir='rtl'] .nv-drawer-panel,
[dir='rtl'] .lp-drawer-panel {
    transform: translateX(-100%);
}

/* The product's own panel is driven by `hidden` + `.is-on` from its own script,
   and this file has already given the shared base a `display: none`. Declared
   outside the media query because the core offers its button from 720px while
   this design offers it from 900: whoever opened it, an open panel is drawn. */
/* `.is-on` alone, not `[data-nv-nav-ready] .nv-drawer.is-on`: the panel is a
   SIBLING of the bar now, so a descendant selector anchored on the header flag
   stopped matching — the menu opened, locked the page and drew nothing. The
   guard it used to provide is unchanged: only the script ever writes `.is-on`,
   so a page whose JavaScript never arrived still cannot open an empty panel. */
.nv-drawer.is-on,
.lp-drawer.is-on {
    display: block;
}

.nv-drawer.is-on .nv-drawer-veil,
.lp-drawer.is-on .lp-drawer-veil {
    opacity: 1;
}

.nv-drawer.is-on .nv-drawer-panel,
.lp-drawer.is-on .lp-drawer-panel {
    transform: translateX(0);
}

.nv-drawer-head,
.lp-drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--nv-line);
}

.nv-drawer-brand {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    color: var(--nv-ink);
    font-size: 15px;
    font-weight: 800;
    letter-spacing: -.02em;
    text-decoration: none;
}

.nv-drawer-brand img {
    max-height: 28px;
    max-width: 150px;
    width: auto;
    object-fit: contain;
    display: block;
}

/* The letter takes the ink the product computed for this brand, never a
   hardcoded white: an operator whose colour is light would be reading their own
   initial against it. */
.nv-drawer-mark {
    width: 28px;
    height: 28px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: 9px;
    background: var(--nv-brand, var(--lp-brand));
    color: var(--lp-on-brand, #fff);
    font-size: 15px;
    font-weight: 800;
}

/* Switch + close, side by side at the top of the panel. The switch is the same
   `.lp-theme` this file already dresses, so it arrives wearing the theme's skin
   and in both palettes; what it needs here is a row to sit in — and the brand
   beside it needs capping, or a wide logo in a 310px panel gets clipped the same
   way it was getting clipped in the bar. */
.nv-drawer-tools,
.lp-drawer-tools {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
}

.lp-drawer-head .lp-brand {
    min-width: 0;
}

.lp-drawer-head .lp-brand-logo {
    max-height: 30px;
    max-width: 130px;
}

.nv-drawer-x,
.lp-drawer-x {
    width: 38px;
    height: 38px;
    flex: none;
    padding: 0;
    display: grid;
    place-items: center;
    border: 1.5px solid var(--nv-line-2);
    border-radius: 11px;
    background: var(--nv-white);
    color: var(--nv-ink);
    cursor: pointer;
    transition: background .2s;
}

.nv-drawer-x:hover,
.lp-drawer-x:hover {
    background: var(--nv-paper);
}

.nv-drawer-inner,
.lp-drawer-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 10px 4px;
}

/* One step up from the 14px the sheet used: in a panel of its own the entries
   are the page, not a strip under the bar, and 15.5px is the size the reference
   gives a primary list. */
.nv-drawer a,
.lp-drawer-nav a {
    padding: 13px 14px;
    border-radius: 12px;
    color: var(--nv-ink);
    font-size: 15.5px;
    font-weight: 600;
    text-decoration: none;
    transition: background .2s;
}

.nv-drawer a:hover,
.nv-drawer a:focus-visible,
.lp-drawer-nav a:hover,
.lp-drawer-nav a:focus-visible {
    background: var(--nv-paper);
}

/* Which page you are on is said by the SURFACE, not by the ink. `--nv-deep` is
   the brand mixed towards the ink and it measured 2.38:1 on this cream row —
   the entry whose whole job is to tell the visitor where they are was the least
   readable one in the panel, and it read that way before this redesign too. The
   tint plus the weight carry the state; the text stays at 15:1. */
.nv-drawer a[aria-current='page'],
.lp-drawer-nav a[aria-current='page'] {
    background: var(--nv-paper);
    color: var(--nv-ink);
    font-weight: 700;
}

/* Pushed to the foot by margin-top, so the pair sits at the bottom on a tall
   phone and simply follows the links on a short one. */
.nv-drawer-cta,
.lp-drawer-cta {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--nv-line);
}

/* The product's secondary link is a plain anchor, and the core rule that centres
   it lives in the stylesheet this design replaces (standalone). Without this it
   sat left-aligned under two full-width buttons. */
.lp-drawer-cta .lp-link-muted {
    display: block;
    padding: 6px 0;
    color: var(--nv-ink);
    font-size: 15px;
    font-weight: 600;
    text-align: center;
    text-decoration: none;
}

.nv-drawer-cta .lp-btn,
.lp-drawer-cta .lp-btn {
    width: 100%;
    padding: 13px 18px;
    font-size: 15px;
}

@media (prefers-reduced-motion: reduce) {
    .nv-drawer-panel,
    .lp-drawer-panel,
    .nv-drawer-veil,
    .lp-drawer-veil {
        transition: none;
    }
}

/* Scroll is locked on BOTH elements on purpose: this theme's base layer sets
   overflow-x on <html>, which stops <body>'s own overflow from propagating to
   the viewport — locking only the body would leave the page scrolling behind an
   open drawer. */
html.nv-nav-open,
html.nv-nav-open body,
body.lp-drawer-on,
html:has(body.lp-drawer-on) {
    overflow: hidden;
}

/* ── Narrow screens ───────────────────────────────────────────────────────────
   The design's own breakpoint and its own rules: the burger appears at 900px,
   the outlined call to action folds away ([data-nav-cta]) and the link row is
   replaced by the drawer.

   Everything is conditioned on [data-nv-nav-ready], the flag 10-nav.js sets once
   the drawer works. A page whose script never arrived keeps the fallback below —
   the links wrap onto their own line and scroll sideways — so the site is never
   left without navigation on a phone. */
@media (max-width: 900px) {
    /* The desktop rail is a 32px gap between three groups. With the links gone
       the row is brand + controls, and that gap is what pushed the burger off
       the right edge of a 390px screen. */
    [data-nv-nav-ready] .lp-headrow,
    [data-nv-nav-ready] .nv-pubhead-row {
        gap: 12px;
    }

    /* Shown at the design's 900px, not the product's 720px: between the two the
       theme has already hidden the link row, so leaving the button on the
       product's breakpoint would put the bar back where this file started —
       no links and no way to reach them. */
    [data-nv-nav-ready] .nv-burger,
    [data-nv-nav-ready] .lp-burger {
        display: inline-grid;
        /* This row is flex-start (the desktop pushes its groups apart with the
           link rail in the middle). With the rail and the controls folded away
           the button would sit against the logo instead of the edge it is
           reached from — and on a phone that edge is where the thumb is. */
        margin-inline-start: auto;
    }

    [data-nv-nav-ready] .lp-nav,
    [data-nv-nav-ready] .nv-pubnav {
        display: none;
    }

    /* The design's hook. On the content pages the partial writes it; on the
       landing 10-nav.js puts it on the outlined pill, which is the same control
       under the product's own class name. The drawer carries it, so folding it
       away here never makes it unreachable. */
    [data-nv-nav-ready] [data-nav-cta] {
        display: none !important;
    }

    /* And the rest of the control group goes with it, not just the pill the hook
       was on. With the switch and the sign-in pair still in the row, a 390px bar
       was carrying four things and the brand was the one that gave way — the
       logo came out clipped mid-word. The bar is the logo and the way into the
       menu; the switch is re-drawn in the drawer head and the pair at its foot.

       Hidden CHILD BY CHILD rather than by folding the container away, because
       the button itself can be inside it: the content pages ship it there in
       their markup, and on a core older than 1.9.0 10-nav.js appends the one it
       builds there too. Collapsing the group would have taken the menu with it —
       a blog with no way into anything, which is the very defect this file came
       from. */
    [data-nv-nav-ready] .lp-headcta > *:not(.nv-burger):not(.lp-burger),
    [data-nv-nav-ready] .nv-pubcta > *:not(.nv-burger):not(.lp-burger) {
        display: none;
    }

    .lp-header:not([data-nv-nav-ready]) .lp-headrow,
    .nv-pubhead:not([data-nv-nav-ready]) .nv-pubhead-row {
        flex-wrap: wrap;
        gap: 10px 14px;
    }

    .lp-header:not([data-nv-nav-ready]) .lp-nav,
    .nv-pubhead:not([data-nv-nav-ready]) .nv-pubnav {
        order: 3;
        width: 100%;
        margin: 0;
        gap: 20px;
        overflow-x: auto;
        scrollbar-width: none;
        padding-bottom: 2px;
        white-space: nowrap;
    }

    .lp-nav::-webkit-scrollbar,
    .nv-pubnav::-webkit-scrollbar {
        display: none;
    }

    .lp-headcta,
    .nv-pubcta {
        gap: 8px;
    }

    .lp-headcta .lp-link-muted,
    .lp-headcta .lp-btn,
    .nv-pubcta .lp-btn {
        padding: 9px 16px;
        font-size: 13px;
    }
}

/* A phone has room for the mark, a short name and the controls — and the name
   is the piece that gives way, because the controls are what the visitor came
   to press. */
@media (max-width: 560px) {
    .lp-brand {
        font-size: 17px;
    }

    .nv-themebtn,
    .lp-theme {
        width: 38px;
        height: 38px;
    }

    [data-nv-nav-ready] .nv-burger {
        width: 40px;
        height: 40px;
    }
}

/* ── The bars in dark mode ────────────────────────────────────────────────────
   The switch lives on <html> and now reaches BOTH bars: the content pages have
   always had it and the landing gained the same control, so .lp-header is
   repainted here alongside .nv-pubhead. A white bar over a dark page is what
   made the inherited control look broken in the first place.

   Painted in tokens rather than the neutral greys this block used to carry
   (#161616 / #1f1f1f / #2a2a2a). Those were a second, colder night sitting on
   top of the one the palette defines — visible the moment a visitor scrolled
   from the bar into the page, and impossible to keep in step with a brand that
   is not the default yellow. */
html.dark .nv-pubhead,
html.dark .lp-header {
    background: color-mix(in srgb, var(--nv-white) 92%, transparent);
    border-bottom-color: var(--nv-line-2);
    color: var(--nv-ink);
}

html.dark .nv-pubhead .lp-brand,
html.dark .lp-header .lp-brand,
html.dark .nv-pubnav a:hover,
html.dark .lp-nav a:hover,
html.dark .nv-pubnav a[aria-current='page'] {
    color: var(--nv-ink);
}

html.dark .nv-pubnav a,
html.dark .lp-nav a {
    color: var(--nv-ink-2);
}

html.dark .nv-themebtn,
html.dark .lp-theme,
html.dark .nv-burger {
    border-color: var(--nv-line-2);
    background: var(--nv-soft);
    color: var(--nv-ink);
}

html.dark .nv-themebtn:hover,
html.dark .lp-theme:hover,
html.dark .nv-burger:hover {
    background: var(--nv-line-2);
}

/* The panel's own surface inverts with the palette; the veil does not need a
   dark rule (it is ink at 55% either way). */
html.dark .nv-drawer-panel,
html.dark .lp-drawer-panel {
    background: var(--nv-white);
    border-inline-start-color: var(--nv-line-2);
}

html.dark .nv-drawer-head,
html.dark .lp-drawer-head,
html.dark .nv-drawer-cta,
html.dark .lp-drawer-cta {
    border-color: var(--nv-line-2);
}

/* `:not([aria-current])` is not cosmetic. This rule and the current-page rule in
   the light block have the SAME specificity, and this file's dark layer is
   concatenated later — so without the exclusion the general rule won, and the
   entry telling the visitor which page they are on lost its brand colour in dark
   mode only. A blanket accessibility rule needs the escape hatch for the one
   surface that already declared its own. */
html.dark .nv-drawer a:not([aria-current='page']),
html.dark .lp-drawer-nav a:not([aria-current='page']) {
    color: var(--nv-ink);
}

html.dark .nv-drawer a:hover,
html.dark .lp-drawer-nav a:hover {
    background: var(--nv-line-2);
}

/* The full brand, not `--nv-deep`. That token is the brand mixed TOWARDS the ink
   so it stays readable on a light surface; over the dark row it measured 3.46:1,
   under the 4.5:1 this size needs. The undiluted colour measures 5.9:1 there and
   is still the operator's own. */
html.dark .nv-drawer a[aria-current='page'],
html.dark .lp-drawer-nav a[aria-current='page'] {
    background: var(--nv-line-2);
    color: var(--nv-brand, var(--lp-brand));
}

html.dark .nv-drawer-x,
html.dark .lp-drawer-x {
    background: transparent;
    border-color: var(--nv-line-2);
    color: var(--nv-ink);
}

/* Landing dark mode: the brand pill keeps its colour; the outlined pill inverts
   to white border so it remains legible against the dark bar. */
html.dark .lp-headcta .lp-btn-primary {
    border-color: color-mix(in srgb, var(--nv-ink) 70%, transparent);
    color: var(--nv-ink);
}

html.dark .lp-headcta .lp-btn-primary:hover {
    background: var(--nv-ink);
    color: var(--nv-paper);
}

html.dark .nv-pubcta .lp-btn-outline {
    background: transparent;
    border-color: color-mix(in srgb, var(--nv-ink) 70%, transparent);
    color: var(--nv-ink);
}

html.dark .nv-pubcta .lp-btn-outline:hover {
    background: var(--nv-ink);
    color: var(--nv-paper);
}

/* ── The design's shared responsive hooks ─────────────────────────────────────
   The reference carries its small-screen decisions on the elements themselves,
   as data attributes, and the base layer already holds [data-cols], [data-cols-2],
   [data-hide-sm] and [data-order-first]. These four are the rest of that set,
   with the designer's own numbers. They live here rather than in the base layer
   because the base layer is shared scaffolding this task does not own, and they
   are the responsive behaviour this file is responsible for. */
@media (max-width: 900px) {
    /* A column that sticks has nothing to stick beside once the grid is one
       column wide, and it would strand the article's sidebar mid-scroll. */
    [data-sticky-col] {
        position: static !important;
    }

    /* Headlines are drawn on one line at desktop width; on a phone that line is
       wider than the screen. */
    [data-hero-title] {
        white-space: normal !important;
    }

    /* A fixed-height artwork box turns into a letterbox with the copy stacked on
       top of it. The design's own floor of 260px keeps it a picture. */
    [data-fixed-h] {
        height: auto !important;
        min-height: 260px;
    }
}

@media (max-width: 480px) {
    /* The back-to-top button moves in from the edge on a small screen, where
       24px of margin is a thumb's worth of dead space. */
    .nv-totop,
    [data-totop] {
        right: 14px;
        bottom: 14px;
    }
}

/* ── Hero ─────────────────────────────────────────────────────────────────────
   A cream gradient, copy on the left and the illustration on the right, standing
   on a brand-coloured plinth that the model overflows. The artwork is absolutely
   positioned inside a fixed-height box so the floating badges can sit outside it
   without changing the flow; below 900px it loses its negative margin and the
   grid collapses to one column. */

.lp-hero {
    position: relative;
    padding: clamp(48px, 6vw, 80px) 0 140px;
    background: linear-gradient(var(--nv-paper) 0%, var(--nv-paper-2) 100%);
    overflow: visible;
}

.lp-hero-inner {
    /* Same border-box correction as .lp-wrap: the rail is added back so the
       content area reaches the intended 1180 px. */
    max-width: calc(var(--nv-wrap) + var(--nv-pad) * 2);
    margin: 0 auto;
    padding: 0 var(--nv-pad);
}

.lp-hero-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 40px;
    align-items: center;
}

.lp-hero-center {
    text-align: center;
}

/* The product's floating emoji layer belongs to its own skins. */
.lp-hearts {
    display: none;
}

.nv-hero-badge {
    margin: 0 0 18px;
}

.nv-hero-title {
    margin: 0;
    font-size: clamp(34px, 4vw, 54px);
    line-height: 1.1;
    font-weight: 600;
    letter-spacing: -.03em;
    color: var(--nv-ink);
    text-wrap: balance;
}

.nv-hero-line {
    display: block;
}

/* The accent line reserves its height and hides overflow so that a word swap
   never reflows the lines above or below. The caret sits outside the <em> so
   it is never clipped by the highlight pseudo-element. */
.nv-hero-accent {
    min-height: 1.15em;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
}

.nv-hero-mark {
    position: relative;
    display: inline-block;
    font-style: normal;
}

/* The skewed highlight behind the accent line. Drawn with a pseudo-element so
   the markup stays a plain <em> the Landing Studio can patch. */
.nv-hero-mark::before {
    content: '';
    position: absolute;
    left: -8px;
    right: -8px;
    bottom: 8%;
    height: 36%;
    border-radius: 6px;
    background: var(--nv-brand);
    transform: skewX(-6deg);
    z-index: 0;
}

.nv-hero-mark > span {
    position: relative;
    z-index: 1;
}

.nv-hero-sub {
    margin: 24px 0 0;
    max-width: 44ch;
    font-size: 16px;
    line-height: 1.7;
    color: var(--nv-ink-soft);
    transition-delay: .12s;
}

.nv-hero-actions {
    display: flex;
    align-items: center;
    gap: 22px;
    flex-wrap: wrap;
    margin-top: 34px;
    transition-delay: .24s;
}

.nv-btn-ink {
    padding: 15px 30px;
    background: var(--nv-ink);
    color: var(--nv-white);
}

.nv-video-btn {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 0;
    border: 0;
    background: none;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
}

.nv-video-play {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--nv-white);
    color: var(--nv-ink);
    box-shadow: var(--nv-shadow-md);
}

.nv-trust {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 26px;
}

/* ── Hero artwork ─────────────────────────────────────────────────────────── */
.nv-art {
    position: relative;
    height: 520px;
    align-self: end;
    margin-bottom: -50px;
    z-index: 3;
}

.nv-art-plinth {
    position: absolute;
    inset: 120px 8% 0;
    border-radius: 48px 48px 0 0;
    background: linear-gradient(160deg, var(--nv-brand) 0%, var(--nv-light) 100%);
    box-shadow: 0 30px 60px color-mix(in srgb, var(--nv-brand) 28%, transparent);
}

.nv-art-glow {
    position: absolute;
    left: 12%;
    right: 12%;
    top: 112px;
    height: 40px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .35);
    filter: blur(10px);
}

.nv-art-model {
    position: absolute;
    inset: -40px 0 0;
    width: 100%;
    height: calc(100% + 40px);
    background: url('img/hero-model.webp') no-repeat center bottom;
    background-size: contain;
    filter: drop-shadow(0 24px 40px rgba(0, 0, 0, .18));
}

.nv-art-bubble {
    position: absolute;
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--nv-white);
    box-shadow: var(--nv-shadow-md);
}

.nv-art-bubble-fb {
    left: -14px;
    top: 150px;
    color: #1877f2;
}

.nv-art-bubble-panel {
    left: 14%;
    top: 70px;
    width: 52px;
    height: 52px;
    background: var(--nv-ink);
    color: var(--nv-brand);
    box-shadow: var(--nv-shadow-lg);
}

.nv-art-bubble-tw {
    right: -8px;
    top: 30%;
    color: #1da1f2;
}

.nv-art-bubble-heart {
    right: -16px;
    top: 48%;
    width: 48px;
    height: 48px;
    color: #e0245e;
}

.nv-art-bubble-ig {
    left: -18px;
    top: 56%;
    color: #e1306c;
}

.nv-art-bubble-like {
    right: -6px;
    bottom: 18%;
    width: 52px;
    height: 52px;
    color: var(--nv-ink);
}

.nv-art-people {
    position: absolute;
    right: 6%;
    bottom: 22%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px 8px 14px;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: var(--nv-shadow-md);
}

.nv-art-people b {
    min-width: 44px;
    font-size: 15px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.nv-art-people i {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 2px solid var(--nv-white);
}

.nv-art-people i + i {
    margin-left: -8px;
}

.nv-art-dot-fb { background: #1877f2; }
.nv-art-dot-tw { background: #1da1f2; }
.nv-art-dot-ig { background: #e1306c; }

.nv-art-rating {
    position: absolute;
    left: -4%;
    bottom: 28px;
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    column-gap: 12px;
    padding: 12px 18px 12px 12px;
    border-radius: 18px;
    background: var(--nv-white);
    box-shadow: 0 16px 40px rgba(0, 0, 0, .12);
}

.nv-art-avatar {
    grid-row: span 2;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--nv-soft) url('img/hero-model.webp') no-repeat center -2px;
    background-size: 150%;
}

.nv-art-rating b {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 16px;
    font-weight: 700;
}

.nv-art-rating b svg {
    color: var(--nv-brand);
}

.nv-art-rating small {
    font-size: 12px;
    color: var(--nv-muted);
}

@media (max-width: 900px) {
    .lp-hero {
        padding-bottom: 90px;
    }

    .lp-hero-split {
        grid-template-columns: minmax(0, 1fr);
    }

    .nv-art {
        height: 420px;
        margin-bottom: 0;
    }

    .nv-hero-sub {
        max-width: none;
    }
}

@media (max-width: 560px) {
    .nv-art {
        height: 340px;
    }

    .nv-art-people,
    .nv-art-rating {
        transform: scale(.85);
    }
}

/* ── Sign-in card ─────────────────────────────────────────────────────────────
   One white card, lifted off the page, holding the whole sign-in flow: a row of
   pill fields with a brand disc each, an ink submit beside them, the small print
   under it and the social buttons below a hairline rule. The markup is Nativa's
   own (sections/login.blade.php), so everything here is an nv-* class. */

.nv-login {
    position: relative;
    /* Under the hero artwork on purpose: .nv-art sits at 3 and overhangs the
       bottom of the hero, so the model's feet fall ONTO this card, which is the
       overlap the design draws. */
    z-index: 2;
    padding: clamp(28px, 4vw, 36px) 0;
}

/* The design has the card lapping 90px onto the cream hero. It only does so when
   the card is what actually follows the hero: the product renders the stats
   strip between the two whenever that block is on, and pulling the card up then
   would slide it under those cards instead of onto the hero. */
.lp-hero + .nv-login {
    padding-top: 0;
}

.lp-hero + .nv-login .nv-login-card {
    margin-top: -90px;
}

.nv-login-card {
    padding: clamp(24px, 3vw, 36px) clamp(20px, 3vw, 40px);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .1);
}

/* ── Card heading ─────────────────────────────────────────────────────────── */
.nv-login-head {
    margin-bottom: 20px;
}

.nv-login-eyebrow {
    margin: 0 0 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--nv-deep);
}

.nv-login-title {
    margin: 0;
    font-size: 20px;
    font-weight: 600;
    color: var(--nv-ink);
}

.nv-login-sub {
    margin: 6px 0 0;
    max-width: 62ch;
    font-size: 13px;
    line-height: 1.6;
    color: var(--nv-muted);
}

.nv-login-note {
    margin: 16px 0 0;
    font-size: 12px;
    color: var(--nv-muted-2);
}

/* A line the operator emptied takes no room. The Studio patches text nodes in
   place, so the node stays in the DOM and reappears as soon as it has words. */
.nv-login-eyebrow:empty,
.nv-login-sub:empty,
.nv-login-note:empty {
    display: none;
}

/* ── Fields ───────────────────────────────────────────────────────────────── */
.nv-login-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
    gap: 16px;
    align-items: center;
}

.nv-field {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px;
    border: 1px solid var(--nv-line);
    border-radius: 999px;
    background: var(--nv-paper-2);
    cursor: text;
    transition: border-color .25s, box-shadow .25s;
}

/* The ring is drawn on the pill rather than on the input, because the input has
   no border of its own and an outline inside the pill reads as a second field. */
.nv-field:focus-within {
    border-color: var(--nv-brand);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--nv-brand) 22%, transparent);
}

.nv-field-ico {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

.nv-field-input {
    flex: 1 1 0;
    min-width: 0;
    padding: 0;
    border: 0;
    background: transparent;
    font-size: 14px;
    color: var(--nv-ink);
}

.nv-field-input:focus,
.nv-field-input:focus-visible {
    outline: none;
}

/* Staff previewing the page: the card is inert, and it should look it. */
.nv-field:has(.nv-field-input[disabled]) {
    cursor: default;
    opacity: .75;
}

.nv-login-submit {
    padding: 16px 40px;
    border: 0;
    border-radius: 999px;
    background: var(--nv-ink);
    color: var(--nv-white);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: transform .25s var(--nv-ease), box-shadow .25s;
}

.nv-login-submit:hover {
    transform: translateY(-2px);
    box-shadow: var(--nv-shadow-md);
}

.nv-login-submit[disabled] {
    opacity: .6;
    cursor: default;
    transform: none;
    box-shadow: none;
}

/* The component renders nothing on a panel with no reCAPTCHA configured, so the
   spacing lives on the child: an empty wrapper must not leave a gap. */
.nv-login-captcha > * {
    margin-top: 16px;
}

/* ── Small print row ──────────────────────────────────────────────────────── */
.nv-login-meta {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 16px;
    font-size: 13px;
    color: var(--nv-ink-4);
}

.nv-login-meta a {
    color: var(--nv-ink-4);
}

.nv-login-meta a:hover {
    color: var(--nv-ink);
}

.nv-login-remember {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
}

.nv-login-remember input {
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--nv-brand);
    cursor: pointer;
}

.nv-login-signup a {
    font-weight: 600;
    color: var(--nv-deep);
}

.nv-login-signup a:hover {
    color: var(--nv-ink);
}

.nv-login-error,
.nv-login-ok {
    margin-bottom: 16px;
    padding: 12px 16px;
    border-radius: 14px;
    font-size: 13px;
    font-weight: 500;
}

/* Red and green are the only colours on this page that do not come from the
   brand: "wrong password" has to read as a failure whatever colour the panel
   was painted in. */
.nv-login-error {
    background: #fdecec;
    color: #b3261e;
}

.nv-login-ok {
    background: #eaf6ec;
    color: #1b6b32;
}

.nv-login-hello {
    margin: 0 0 14px;
    font-size: 15px;
    color: var(--nv-ink-soft);
}

.nv-login-go {
    margin-top: 4px;
}

/* ── Social row ───────────────────────────────────────────────────────────── */
.nv-login-or {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-top: 22px;
}

.nv-login-or i {
    flex: 1 1 0;
    height: 1px;
    background: var(--nv-line-2);
}

.nv-login-or em {
    font-style: normal;
    font-size: 12px;
    white-space: nowrap;
    color: var(--nv-muted-2);
}

/* auto-fit, not two fixed columns: a panel with only one provider configured
   gets one button across the card instead of a stranded half. */
.nv-login-social {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 14px;
    margin-top: 16px;
}

.nv-social {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 13px 20px;
    border: 1.5px solid var(--nv-line-2);
    border-radius: 999px;
    background: var(--nv-white);
    font-size: 14px;
    font-weight: 500;
    color: var(--nv-ink);
    transition: transform .25s var(--nv-ease), box-shadow .25s;
}

.nv-social:hover {
    transform: translateY(-2px);
    box-shadow: var(--nv-shadow-sm);
    color: var(--nv-ink);
}

.nv-social svg {
    flex: 0 0 auto;
}

/* Facebook's own blue, like the network badges in the hero: a provider mark is
   not the operator's colour to pick. */
.nv-social-fb {
    border-color: #1877f2;
    background: #1877f2;
    color: var(--nv-white);
}

.nv-social-fb:hover {
    color: var(--nv-white);
}

/* Visually hidden, still read aloud: the design labels the fields with their
   placeholder only, and a placeholder is not a label. */
.nv-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    border: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

@media (max-width: 900px) {
    /* The hero loses its overhang below 900px, so the card laps less. */
    .lp-hero + .nv-login .nv-login-card {
        margin-top: -50px;
    }
}

@media (max-width: 860px) {
    .nv-login-row {
        grid-template-columns: minmax(0, 1fr);
    }

    .nv-login-submit {
        width: 100%;
    }
}

@media (max-width: 520px) {
    .nv-login-meta {
        flex-direction: column;
        gap: 10px;
    }
}

/* ── Features rail ────────────────────────────────────────────────────────────
   A centred heading over a horizontal rail of white cards on the cream page,
   with the arrows the design draws sitting half outside it and the dots below.

   The rail is a real scroll container with snap points, not a paged track: the
   markup (sections/features.blade.php) explains why the arrows and the dots are
   ornament — a theme view holds no JavaScript, and the only no-JS control an
   arrow could have is an `#anchor`, which scrolls the PAGE to the card as well
   as the rail. So the cards are sized to leave a sliver of the next one showing
   and the rail carries the interaction itself. When ::scroll-button() and
   ::scroll-marker() are safe to ship, they turn this same markup into the real
   thing without a line of script.

   Numbers come from the design's resolved DOM (theme-shots/B-sections/05-part):
   24px radius, 32px/28px padding, a 72px tile at 22px, 18px titles. */

.nv-feat-head {
    text-align: center;
    margin-bottom: 40px;
}

.nv-feat-head .lp-h2 {
    /* The design caps the headline at 22ch rather than at a pixel width, so it
       breaks into the two balanced lines it was drawn with in any language. */
    max-width: 22ch;
    margin-inline: auto;
}

.nv-feat-head .lp-lead {
    margin-inline: auto;
    transition-delay: .1s;
}

/* The eyebrow introduces the cards here instead of opening the heading, so it
   sits under the lead and carries its spacing the other way up. */
.nv-feat-head .lp-eyebrow {
    /* 38px, not 14: that is the gap the reference leaves between the lead and
       this line. With 14 the label and the nine cards under it all sat 25px
       high, which is how the whole block drifted out of place. */
    margin: 38px 0 0;
    transition-delay: .15s;
}

/* A line the operator emptied takes no room. The Studio patches text nodes in
   place, so the node stays in the DOM and comes back with its words. */
.nv-feat-head .lp-lead:empty,
.nv-feat-head .lp-eyebrow:empty {
    display: none;
}

/* ── The rail ─────────────────────────────────────────────────────────────── */
.nv-feat-rail {
    position: relative;
}

.nv-feat-track {
    --nv-feat-gap: 24px;
    /* What is left of the next card at rest. With three cards filling the rail
       exactly there would be nothing to say that the rail moves, and this block
       has no working arrow to say it for us. */
    --nv-feat-peek: 34px;

    display: flex;
    gap: var(--nv-feat-gap);
    overflow-x: auto;
    /* A swipe that runs out of rail must stay in the rail: on a phone it would
       otherwise chain into the page's back gesture. */
    overscroll-behavior-inline: contain;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scroll-padding-inline: 6px;
    /* Room for the card shadow and for the 6px the card lifts on hover, given
       back with a negative margin so the rail still lines up with the wrap. */
    margin: -22px -6px;
    padding: 22px 6px;
    /* The dots stand in for the scrollbar; a native bar under the cards would
       cut the design in half. */
    scrollbar-width: none;
}

.nv-feat-track::-webkit-scrollbar {
    display: none;
}

.nv-feat-card {
    flex: 0 0 calc((100% - 2 * var(--nv-feat-gap) - var(--nv-feat-peek)) / 3);
    scroll-snap-align: start;
    padding: 32px 28px;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: var(--nv-shadow);
    text-align: center;
    transition: transform .35s var(--nv-ease), box-shadow .35s;
}

.nv-feat-card:hover {
    transform: translateY(-6px);
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
}

/* The shared tile, re-dressed: the design's is bigger than the 46px square the
   rest of the page uses and lit with a gradient, but it is the same component,
   so the colour still comes from the operator's brand. */
.nv-feat-ico {
    width: 72px;
    height: 72px;
    margin: 0 auto;
    border-radius: 22px;
    background: linear-gradient(160deg, var(--nv-light), var(--nv-brand));
    box-shadow: var(--nv-shadow-brand);
}

.nv-feat-title {
    margin: 22px 0 12px;
    font-size: 18px;
    font-weight: 600;
    color: var(--nv-ink);
}

.nv-feat-text {
    margin: 0;
    font-size: 14px;
    line-height: 1.75;
    color: var(--nv-ink-4);
}

/* ── Arrows and dots (ornament — see the Blade) ───────────────────────────── */
.nv-feat-arrow {
    position: absolute;
    top: 50%;
    translate: 0 -50%;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    /* Inert, and it must not even look clickable: no pointer cursor, and a
       press-and-drag that starts here reaches the rail underneath. */
    pointer-events: none;
}

.nv-feat-prev {
    left: -22px;
    background: var(--nv-white);
    color: var(--nv-ink);
    box-shadow: 0 10px 26px rgba(0, 0, 0, .12);
}

.nv-feat-next {
    right: -22px;
    background: var(--nv-ink);
    color: var(--nv-brand);
    box-shadow: 0 10px 26px rgba(0, 0, 0, .18);
}

.nv-feat-dots {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-top: 28px;
}

.nv-feat-dot {
    width: 10px;
    height: 10px;
    border-radius: 999px;
    /* Literal first, then the same shade mixed from whatever colour the operator
       picked, like every warm tint in this theme. */
    background: #d9d2b8;
    background: color-mix(in srgb, var(--nv-brand) 18%, #d2ccb9);
    transition: width .4s var(--nv-ease), background .4s;
}

/* The rail rests at the start, which is where the page is when it is read. */
.nv-feat-dot-on {
    width: 28px;
    background: var(--nv-ink);
}

.nv-feat-cta {
    display: flex;
    width: fit-content;
    margin: 28px auto 0;
    padding: 14px 30px;
    font-size: 14px;
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
    /* Two cards, and no arrows: at this width they would sit on the page's own
       padding, and the rail is swiped here rather than clicked anyway. */
    .nv-feat-arrow {
        display: none;
    }

    .nv-feat-track {
        --nv-feat-peek: 30px;
    }

    .nv-feat-card {
        flex-basis: calc((100% - var(--nv-feat-gap) - var(--nv-feat-peek)) / 2);
    }
}

@media (max-width: 640px) {
    .nv-feat-track {
        --nv-feat-gap: 16px;
        --nv-feat-peek: 28px;
    }

    .nv-feat-card {
        flex-basis: calc(100% - var(--nv-feat-peek));
        padding: 28px 22px;
    }
}

/* ── Growth chart ─────────────────────────────────────────────────────────────
   A block Nativa adds: the chart card on the left, the promise on the right, on
   the white page between the cream features rail and the network list.

   The card is the only fixed-height box in this design (420px, like the drawing)
   because the chart fills what is left after the head and the axis have taken
   theirs; everything else in here is content-sized. The two flat shapes behind
   it are pseudo-elements — they carry no words, so they have no business being
   nodes the operator can select in the Studio.

   Numbers come from the design's resolved DOM (theme-shots/B-sections/06-part):
   32px radius, 28px/20px padding, a 30px figure, 26px ticks, 48px column gap. */

.nv-growth-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 48px;
    align-items: center;
}

/* ── The card and the shapes behind it ────────────────────────────────────── */
.nv-growth-media {
    position: relative;
    min-height: 420px;
}

/* The rounded slab that leans out from behind the top-left corner. */
.nv-growth-media::before {
    content: '';
    position: absolute;
    left: -18px;
    top: -18px;
    z-index: 0;
    width: 140px;
    height: 140px;
    border-radius: 40px;
    background: var(--nv-brand);
    rotate: -8deg;
}

/* …and the open ring at the other corner, in the same warm tint the chips use. */
.nv-growth-media::after {
    content: '';
    position: absolute;
    right: -14px;
    bottom: -14px;
    z-index: 0;
    width: 120px;
    height: 120px;
    border: 14px solid var(--nv-soft);
    border-radius: 50%;
}

.nv-growth-card {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    height: 420px;
    padding: 28px 28px 20px;
    border: 1px solid var(--nv-line);
    border-radius: 32px;
    background: var(--nv-white);
    box-shadow: 0 30px 70px rgba(0, 0, 0, .14);
}

.nv-growth-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

.nv-growth-cap {
    margin: 0;
    font-size: 12px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--nv-ink-6);
}

.nv-growth-value {
    margin: 6px 0 0;
    font-size: 30px;
    font-weight: 700;
    line-height: 1;
    color: var(--nv-ink);
    /* The figure is the one number a visitor reads twice; tabular digits stop it
       shuffling sideways while the Studio patches it letter by letter. */
    font-variant-numeric: tabular-nums;
}

/* The shared chip, one step larger than the rest of the page uses. */
.nv-growth-delta {
    flex: none;
    font-size: 13px;
}

.nv-growth-delta-ico {
    display: inline-flex;
}

/* ── The chart ────────────────────────────────────────────────────────────── */
.nv-growth-plot {
    position: relative;
    flex: 1;
    min-height: 0;
    margin-top: 16px;
}

.nv-growth-svg {
    display: block;
    width: 100%;
    height: 100%;
    /* The last vertex sits on the right edge; half its stroke lives outside the
       viewBox and would be cut off. */
    overflow: visible;
}

.nv-growth-rules {
    stroke: var(--nv-line);
    stroke-width: 1;
}

/* The operator's colour, fading out downwards. Painted here rather than on the
   <stop> so it can read the token — a presentation attribute takes a literal,
   and a literal is the one thing a white-label design must not carry. */
.nv-growth-stop-top {
    stop-color: var(--nv-brand);
    stop-opacity: .35;
}

.nv-growth-stop-bottom {
    stop-color: var(--nv-brand);
    stop-opacity: 0;
}

.nv-growth-line {
    fill: none;
    stroke: var(--nv-brand);
    stroke-width: 3.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* The head of the line: an ink dot that TRAVELS with the curve (the script
   writes left/top as a fraction of the viewBox, which is the only unit that
   survives a stretched svg), with a brand ring breathing out of it.

   The ring is a pseudo-element rather than a shadow on the dot itself: the
   design grows a drawn 2px circle to three times its size and fades it out, and
   a box-shadow ramp reads as a soft halo instead of a ring leaving. The dot
   underneath stays solid ink at all times — it is the head of the line, and a
   head that dims with the pulse would look like the line is losing its end.

   Both stop dead under prefers-reduced-motion via the base layer's blanket
   rule; the position is written by script and does not animate, so the chart
   still renders complete there. */
.nv-growth-tip {
    position: absolute;
    left: 99.9%;
    top: 5.68%;
    width: 14px;
    height: 14px;
    margin: -7px 0 0 -7px;
    border-radius: 50%;
    background: var(--nv-ink);
    pointer-events: none;
}

.nv-growth-tip::after {
    content: '';
    position: absolute;
    inset: 0;
    border: 2px solid var(--nv-brand);
    border-radius: 50%;
    animation: nv-pulse-ring 1.6s ease-out infinite;
}

.nv-growth-axis {
    display: flex;
    justify-content: space-between;
    margin-top: 8px;
    font-size: 11px;
    color: var(--nv-muted-2);
}

/* ── The reach float (bottom-left card) ──────────────────────────────────── */
/* Numbers from the design: left −22px, bottom 56px, padding 12px 18px 12px 12px,
   radius 18px, shadow rgba(0,0,0,.14) 0 16px 40px. The icon box is 44×44 px with
   radius 14px, filled with the ink colour, and the icon itself is brand-coloured
   so the trending-up arrow reads as a positive signal at a glance. */
.nv-growth-reach {
    position: absolute;
    left: -22px;
    bottom: 56px;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 18px 12px 12px;
    border-radius: 18px;
    background: var(--nv-white);
    box-shadow: 0 16px 40px rgba(0, 0, 0, .14);
}

.nv-growth-reach-ico {
    display: grid;
    place-items: center;
    flex: none;
    width: 44px;
    height: 44px;
    border-radius: 14px;
    background: var(--nv-ink);
    color: var(--nv-brand);
}

/* The primary line — the percentage — is the number a visitor reads. */
.nv-growth-reach-delta {
    margin: 0;
    font-weight: 700;
    font-size: 16px;
    line-height: 1;
    color: var(--nv-ink);
}

/* The secondary line — the label — is the context beneath. */
.nv-growth-reach-label {
    margin: 4px 0 0;
    font-size: 12px;
    color: var(--nv-muted);
}

/* The whole card hides if both lines are empty: an operator who clears them
   gets nothing rather than an orphaned icon floating over the chart. */
.nv-growth-reach:has([data-lp]:empty + [data-lp]:empty) {
    display: none;
}

/* ── The likes badge (top-right pill) ────────────────────────────────────── */
.nv-growth-badge {
    position: absolute;
    right: -16px;
    top: -22px;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 12px 30px rgba(0, 0, 0, .12);
    font-size: 13px;
    font-weight: 600;
}

/* A platform's own colour, like the social bubbles in the hero — this one is
   not an accent of the design, it is what a "like" looks like everywhere. */
.nv-growth-badge-ico {
    display: inline-flex;
    color: #e0245e;
}

/* An operator who empties the badge gets no empty pill floating over their
   chart; one keystroke in the Studio brings it back, because the node never
   left the DOM. */
.nv-growth-badge:has(> [data-lp]:empty) {
    display: none;
}

/* ── The promise ──────────────────────────────────────────────────────────── */
.nv-growth-copy .lp-eyebrow {
    margin: 0;
}

.nv-growth-copy .lp-h2 {
    margin-top: 10px;
}

.nv-growth-copy .lp-lead {
    margin-top: 18px;
    max-width: 52ch;
    line-height: 1.8;
}

/* A line the operator emptied takes no room, heading included: the Studio
   patches text in place, so these nodes stay and collapse. */
.nv-growth-copy .lp-eyebrow:empty,
.nv-growth-copy .lp-h2:empty,
.nv-growth-copy .lp-lead:empty,
.nv-growth-cap:empty,
.nv-growth-value:empty {
    display: none;
}

.nv-growth-delta:has(> [data-lp]:empty) {
    display: none;
}

.nv-growth-points {
    display: grid;
    gap: 12px;
    margin: 24px 0 0;
    font-size: 14px;
    color: var(--nv-ink);
}

.nv-growth-points li {
    display: flex;
    align-items: center;
    gap: 12px;
}

.nv-growth-tick {
    display: grid;
    place-items: center;
    flex: none;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

.nv-growth-cta {
    margin-top: 30px;
    padding: 14px 30px;
    font-size: 14px;
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
    .nv-growth-split {
        grid-template-columns: minmax(0, 1fr);
        gap: 56px;
    }

    .nv-growth-media {
        min-height: 0;
    }

    /* The card keeps its proportions rather than its height: on one column it is
       as wide as the page, and 420px of chart would be a wall of empty grid. */
    .nv-growth-card {
        height: auto;
        aspect-ratio: 16 / 11;
    }

    /* Both floats overhang the card edge at desktop — pull them inside the
       card boundary on one-column layouts so they do not escape the viewport
       or overlap neighbouring blocks. The badge moves the least: its top-right
       corner still peeks over, which is the designed look. */
    .nv-growth-reach {
        left: 8px;
        bottom: 40px;
    }

    .nv-growth-badge {
        right: 4px;
    }

    .nv-growth-copy .lp-lead {
        max-width: none;
    }
}

@media (max-width: 560px) {
    .nv-growth-card {
        padding: 22px 20px 16px;
        border-radius: 26px;
        aspect-ratio: 4 / 3;
    }

    .nv-growth-value {
        font-size: 26px;
    }

    /* The shapes shrink with the card: at this width the slab was reaching a
       third of the way across the chart. */
    .nv-growth-media::before {
        width: 96px;
        height: 96px;
        border-radius: 28px;
    }

    .nv-growth-media::after {
        width: 84px;
        height: 84px;
        border-width: 10px;
    }
}

/* ── Stats ────────────────────────────────────────────────────────────────────
   Three metric cards matching the v2 design (03-section.html): a white card on a
   warm page, a 64 px brand-gradient tile with a masked SVG glyph, a 34 px figure
   followed by a coloured "+" suffix, a 14 px bold title, and a 12 px muted
   description one line below.

   Numbers copied from the reference, not approximated:
     gap            24 px
     card padding   26 px (top/bottom) × 28 px (sides)
     card radius    24 px
     card shadow    0 12px 36px rgba(0,0,0,.07)
     card border    1 px var(--nv-line)
     tile size      64 px
     tile radius    20 px
     tile shadow    var(--nv-shadow-brand)
     glyph size     28 px
     gap tile→text  20 px
     figure size    34 px, weight 700, leading 1, tracking −0.02em
     suffix colour  var(--nv-deep)   (the amber-gold the design marks as #c99a00)
     title mt       8 px, size 14 px, weight 600
     desc mt        2 px, size 12 px, colour var(--nv-muted)   (#8a8a8a)
     hover lift     translateY(−4 px) + shadow var(--nv-shadow-md)
     card delay     0 s / 0.1 s / 0.2 s  (set inline by the Blade)

   TWO LAYOUT MODES.
   When the theme's own stats.blade.php is active the grid root is .nv-stats-grid
   (emitted by the Blade). When the product renders the block without a theme
   override (e.g. a core skin, or a test page) the root is .lp-statgrid. Both are
   handled here so the CSS works in either state and a failed view-resolver falls
   back to the core grid looking reasonable rather than unstyled.

   ICON ARTWORK.
   Three SVGs cycling via :nth-child — people (1st/4th/…), orders (2nd/5th/…),
   services (3rd/6th/…) — painted as a ::before gradient tile and a ::after
   mask-image glyph. This matches exactly what the design drew without encoding
   colour into the SVG (the glyph colour tracks --nv-on-brand, which the operator
   chooses). */

/* ── Grid ──────────────────────────────────────────────────────────────────── */

/* Theme override path — three fixed columns at wide widths, wrapping on the way
   down. `repeat(auto-fit, minmax(240px, 1fr))` lets a panel with the default four
   metrics still fit on one row and fold gracefully, so switching from the core
   skin to Nativa does not break a panel that kept the fourth stat. */
.nv-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 24px;
}

/* Core fallback — same grid rule applied to the class the product emits. */
.lp-statgrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 24px;
}

/* ── Card shell ─────────────────────────────────────────────────────────────── */

.nv-stat-card {
    --nv-stat-tile: 64px;
    --nv-stat-pad: 28px;
    --nv-stat-glyph: 28px;

    /* People — first card and every third after it. */
    --nv-stat-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='9' cy='7' r='4'/%3E%3Cpath d='M22 21v-2a4 4 0 0 0-3-3.87'/%3E%3Cpath d='M16 3.13a4 4 0 0 1 0 7.75'/%3E%3C/svg%3E");

    position: relative;
    display: flex;
    align-items: center;
    gap: 20px;
    /* The product centres the strip on its own wrapper with an inline
       `text-align: center`, which every skin that ships with it wants. This
       design does not: the figure, the title and the description sit flush to
       the left of the icon tile. Declared on the card because an inline style on
       an ancestor only INHERITS — any explicit rule down here wins. */
    text-align: start;
    padding: 26px var(--nv-stat-pad);
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .07);
    /* translate rather than transform: data-reveal animates transform, so the
       two do not fight over the same property and the hover lift still works
       on a card that is mid-reveal. */
    transition: translate .35s var(--nv-ease), box-shadow .35s;
}

.nv-stat-card:hover {
    translate: 0 -4px;
    box-shadow: var(--nv-shadow-md);
}

/* Orders — second card and every third after it. */
.nv-stat-card:nth-child(3n + 2) {
    --nv-stat-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z'/%3E%3Cpath d='M3 6h18'/%3E%3Cpath d='M16 10a4 4 0 0 1-8 0'/%3E%3C/svg%3E");
}

/* Services — third card and every third after it. */
.nv-stat-card:nth-child(3n) {
    --nv-stat-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z'/%3E%3Cpath d='m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65'/%3E%3Cpath d='m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65'/%3E%3C/svg%3E");
}

/* ── Tile (gradient square with icon) ──────────────────────────────────────── */

/* The tile is a flex sibling of .nv-stat-body; ::before draws it at the correct
   size without an extra wrapper element. Absolute positioning would fight with
   flexbox, so instead the pseudo occupies a flex slot via `flex: none`. */
.nv-stat-card::before {
    content: '';
    flex: 0 0 auto;
    width: var(--nv-stat-tile);
    height: var(--nv-stat-tile);
    border-radius: 20px;
    background: linear-gradient(160deg, var(--nv-light), var(--nv-brand));
    box-shadow: var(--nv-shadow-brand);
}

/* The glyph, masked over the tile. Positioned inside the card's own padding
   so it sits centred on the tile regardless of card height. */
.nv-stat-card::after {
    content: '';
    position: absolute;
    top: 50%;
    /* The tile starts at --nv-stat-pad from the left edge; the glyph is
       centred inside the tile. */
    inset-inline-start: calc(var(--nv-stat-pad) + (var(--nv-stat-tile) - var(--nv-stat-glyph)) / 2);
    width: var(--nv-stat-glyph);
    height: var(--nv-stat-glyph);
    translate: 0 -50%;
    background: var(--nv-on-brand);
    -webkit-mask: var(--nv-stat-ico) center / var(--nv-stat-glyph) var(--nv-stat-glyph) no-repeat;
    mask: var(--nv-stat-ico) center / var(--nv-stat-glyph) var(--nv-stat-glyph) no-repeat;
}

/* A solid square on the tile is a defect; no glyph is just a detail missing. */
@supports not ((-webkit-mask-image: none) or (mask-image: none)) {
    .nv-stat-card::after {
        display: none;
    }
}

/* ── Text column ─────────────────────────────────────────────────────────────
   Three stacked text nodes: figure (+ suffix), title, description. min-width:0
   prevents a long figure from overflowing the flex row. */

.nv-stat-body {
    min-width: 0;
}

/* ── Figure row ─────────────────────────────────────────────────────────────── */

.nv-stat-value {
    margin: 0;
    font-size: 34px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--nv-ink);
}

/* The "+" that follows the figure. The reference draws it in the amber-gold
   derived from the brand (the design's #c99a00, mapped to --nv-deep). */
.nv-stat-suffix {
    color: var(--nv-deep);
}

/* ── Title ──────────────────────────────────────────────────────────────────── */

/* Also applied with the product's .lp-stat-label class so the two share the
   same target and the core stylesheet (when present) does not fight it. */
.nv-stat-title {
    margin: 8px 0 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--nv-ink);
}

/* ── Description ─────────────────────────────────────────────────────────────
   The third line the design draws: 12 px muted grey, 2 px below the title.
   Not in the product's content model; read from theme.stats.N.description
   (set as a default in the ServiceProvider's section_fields.stats list). */

.nv-stat-desc {
    margin: 2px 0 0;
    font-size: 12px;
    color: var(--nv-ink-6);
}

/* ── Core fallback ───────────────────────────────────────────────────────────
   When the product renders the block without the theme's Blade override, the
   grid root is .lp-statgrid and the card is a bare `> div`. These rules dress
   it with the tile-grid layout so the block looks reasonable rather than raw. */

.lp-statgrid > div {
    --nv-stat-tile: 64px;
    --nv-stat-pad: 28px;
    --nv-stat-glyph: 28px;
    --nv-stat-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='9' cy='7' r='4'/%3E%3Cpath d='M22 21v-2a4 4 0 0 0-3-3.87'/%3E%3Cpath d='M16 3.13a4 4 0 0 1 0 7.75'/%3E%3C/svg%3E");

    position: relative;
    display: grid;
    grid-template-columns: var(--nv-stat-tile) minmax(0, 1fr);
    align-items: center;
    column-gap: 20px;
    padding: 26px var(--nv-stat-pad);
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .07);
    transition: translate .35s var(--nv-ease), box-shadow .35s;
}

.lp-statgrid > div:hover {
    translate: 0 -4px;
    box-shadow: var(--nv-shadow-md);
}

.lp-statgrid > div::before {
    content: '';
    grid-row: 1 / span 2;
    grid-column: 1;
    width: var(--nv-stat-tile);
    height: var(--nv-stat-tile);
    border-radius: 20px;
    background: linear-gradient(160deg, var(--nv-light), var(--nv-brand));
    box-shadow: var(--nv-shadow-brand);
}

.lp-statgrid > div::after {
    content: '';
    position: absolute;
    top: 50%;
    inset-inline-start: calc(var(--nv-stat-pad) + (var(--nv-stat-tile) - var(--nv-stat-glyph)) / 2);
    width: var(--nv-stat-glyph);
    height: var(--nv-stat-glyph);
    translate: 0 -50%;
    background: var(--nv-on-brand);
    -webkit-mask: var(--nv-stat-ico) center / var(--nv-stat-glyph) var(--nv-stat-glyph) no-repeat;
    mask: var(--nv-stat-ico) center / var(--nv-stat-glyph) var(--nv-stat-glyph) no-repeat;
}

@supports not ((-webkit-mask-image: none) or (mask-image: none)) {
    .lp-statgrid > div::after {
        display: none;
    }
}

.lp-statgrid > div:nth-child(3n + 2) {
    --nv-stat-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z'/%3E%3Cpath d='M3 6h18'/%3E%3Cpath d='M16 10a4 4 0 0 1-8 0'/%3E%3C/svg%3E");
}

.lp-statgrid > div:nth-child(3n) {
    --nv-stat-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z'/%3E%3Cpath d='m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65'/%3E%3Cpath d='m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65'/%3E%3C/svg%3E");
}

.lp-stat-value {
    grid-column: 2;
    align-self: end;
    font-size: 34px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    text-align: start;
    color: var(--nv-ink);
}

.lp-stat-label {
    grid-column: 2;
    align-self: start;
    margin-top: 8px;
    font-size: 14px;
    font-weight: 600;
    /* No line-height here either: the tile markup carries BOTH .nv-stat-title and
       this class, and this rule comes later, so a value here silently wins over
       the one next door — which is how the title kept its old leading after the
       sibling rule had already been cleaned. */
    text-align: start;
    color: var(--nv-ink);
}

/* ── Responsive ──────────────────────────────────────────────────────────────
   At 420 px the tile shrinks to 52 px so the figure and title do not crowd it.
   Same breakpoint the reference design uses; both card types adapt. */

@media (max-width: 420px) {
    .nv-stat-card,
    .lp-statgrid > div {
        --nv-stat-tile: 52px;
        --nv-stat-pad: 22px;
        --nv-stat-glyph: 24px;

        gap: 16px;
    }

    .nv-stat-card {
        padding: 22px var(--nv-stat-pad);
    }

    .lp-statgrid > div {
        column-gap: 16px;
        padding: 22px var(--nv-stat-pad);
    }

    .nv-stat-card::before,
    .lp-statgrid > div::before {
        border-radius: 16px;
    }

    .nv-stat-value {
        font-size: 28px;
    }

    .lp-stat-value {
        font-size: 28px;
    }
}

/* ── Networks / platform picker ───────────────────────────────────────────────
   A centred heading, a wrapping strip of pills, and one brand-yellow card per
   platform. Each card has two columns: the left holds the platform heading and
   a selectable service list; the right holds a white floating order card with a
   quantity slider and a live total.

   Numbers come from the design's resolved DOM (v2-landing-sections/06-services):
   pills 10px/20px on a 999px radius with a 0 6px 18px shadow and a .25s
   background fade; the yellow card 32px radius and clamp(28px, 4vw, 56px) of
   padding on a two-column grid with a 40px gap; the white card 28px radius,
   26px 28px 24px of padding, a 0 24px 60px shadow and a 340px cap; the tile 56px
   at an 18px radius with 0 10px 24px under it; the orbs 48px with 0 12px 30px;
   the total box 18px radius with rgb(253,246,220) background; the slider accent
   rgb(247,198,0); the quantity chips font-size 11px tabular-nums.

   Only ONE panel is on the page at a time, and only while the theme's script is
   actually running: the strip is drawn by `[data-nv-ready]`, which that script
   sets on the section, so a page where it is blocked or never arrives shows
   platforms instead of a row of buttons that answer a click with silence. The
   panels are folded by `.lp-js` rather than by the same attribute, because that
   class is on the page before paint — waiting for the script would flash stacked
   cards on a slow connection.

   Each platform's colour arrives as `--nv-net-color`, set on the node by
   public/js/61-networks.js from the value the operator saved. Every rule that
   reads it names a token as the fallback, so the block is complete before the
   script runs and stays complete if it never does. */

/* The reference runs this block flush against the one above it: the rhythm of
   the page is a 96px gap here and 192px elsewhere, not an even beat throughout.
   Only the top is dropped — the bottom keeps the section padding. */
.nv-net {
    padding-top: 0;
}

.nv-net-head {
    text-align: center;
}

.nv-net-eyebrow {
    margin: 0 0 12px;
}

.nv-net-lead {
    max-width: 60ch;
    margin: 14px auto 0;
}

.nv-net-eyebrow:empty,
.nv-net-lead:empty {
    display: none;
}

/* ── The platform strip ───────────────────────────────────────────────────── */
.nv-net-tabs {
    display: none;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px;
    margin: 36px 0 28px;
}

[data-nv-ready] .nv-net-tabs {
    display: flex;
}

.nv-net-tab {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 20px;
    border: 0;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .08);
    font-size: 13px;
    font-weight: 500;
    color: var(--nv-ink);
    cursor: pointer;
    transition: background .25s, color .25s;
}

.nv-net-tab:hover {
    background: var(--nv-soft);
}

.nv-net-tab[aria-pressed='true'] {
    background: var(--nv-ink);
    color: var(--nv-white);
}

.nv-net-dot {
    width: 10px;
    height: 10px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--nv-net-color, var(--nv-brand));
}

/* Icon span for known platforms — SVG coloured with the platform colour.
   The icon is 16×16 and sits inline so the pill keeps its original height. */
.nv-net-tab-icon {
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--nv-net-color, var(--nv-ink));
}

/* ── The platform card ────────────────────────────────────────────────────── */
.nv-net-panel {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 40px;
    align-items: center;
    padding: clamp(28px, 4vw, 56px);
    border-radius: 32px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    text-align: left;
}

.nv-net-panel + .nv-net-panel {
    margin-top: 24px;
}

.lp-js .nv-net-panel {
    display: none;
    margin-top: 0;
}

.lp-js .nv-net-panel.is-on {
    display: grid;
}

/* ── Left column copy ─────────────────────────────────────────────────────── */
.nv-net-title {
    margin: 0;
    font-size: clamp(22px, 2.4vw, 30px);
    font-weight: 700;
    line-height: 1.25;
}

/* On two-column layouts the left panel column is half of a 40 px-gap grid.
   At that width the heading wraps at ~22 px. `text-wrap: nowrap` keeps it
   on one line without shrinking the font; the column itself can give a little
   extra space because the right card has a 340 px cap and rarely fills all of
   its half. Mobile stays unrestricted so nothing overflows a narrow screen. */
@media (min-width: 901px) {
    .nv-net-title {
        text-wrap: nowrap;
    }
}

/* The suffix span ("SMM Panel Services") sits after the platform name. A space
   before the span text comes from the CSS `margin-left` so that clearing the
   field in the Studio leaves no orphan gap in the heading. */
.nv-net-title-suffix {
    margin-left: .25em;
}

:where(.nv-net-title-suffix):empty {
    display: none;
}

.nv-net-text {
    max-width: 50ch;
    margin: 16px 0 0;
    font-size: 14px;
    line-height: 1.8;
    color: #3a3200;
    color: color-mix(in srgb, var(--nv-brand) 24%, #000);
}

.nv-net-text:empty {
    display: none;
}

/* "Choose a service" micro-heading */
.nv-net-choose-label {
    margin: 22px 0 10px;
    font-size: 12px;
    letter-spacing: .06em;
    text-transform: uppercase;
    font-weight: 600;
    color: #7a6200;
    color: var(--nv-deeper);
}

/* ── Service pill buttons ─────────────────────────────────────────────────── */
.nv-net-svcs {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.nv-net-svc {
    display: inline-flex;
    gap: 8px;
    align-items: center;
    padding: 9px 16px;
    border: 2px solid transparent;
    border-radius: 999px;
    background: rgba(255, 255, 255, .6);
    font-size: 13px;
    font-weight: 500;
    /* --nv-on-brand and NOT --nv-ink. The two are the same colour on a light
       page, so this reads as a no-op — and it is the difference between legible
       and invisible in dark mode. The pill sits on a LITERAL white wash over the
       brand panel: that surface does not change with the theme, so its text must
       not either, and the token for "ink that stays put on brand" is on-brand.
       With --nv-ink the label flipped to the light end of the ramp and painted
       white-on-white. */
    color: var(--nv-on-brand);
    cursor: pointer;
    transition: background .25s, border-color .25s;
}

.nv-net-svc:hover {
    background: rgba(255, 255, 255, .85);
}

.nv-net-svc[aria-pressed='true'] {
    border-color: var(--nv-ink);
    background: rgba(255, 255, 255, .85);
}

.nv-net-svc-price {
    color: #7a6200;
    color: var(--nv-deeper);
}


/* ── Right column — white card ────────────────────────────────────────────── */
/* No padding, on purpose: in the reference this column IS the card — both
   measure 367px — and the orbs hang off its edges (top:-6/-20, bottom:-6).
   The 34px of breathing room this used to carry made the section 68px taller
   than the design AND pushed every orb that far away from the card it
   decorates, which is the opposite of what the decoration is for. */
.nv-net-media {
    position: relative;
    display: grid;
    place-items: center;
}

.nv-net-card {
    display: flex;
    flex-direction: column;
    gap: 14px;
    width: 100%;
    max-width: 340px;
    padding: 26px 28px 24px;
    border-radius: 28px;
    background: var(--nv-white);
    color: var(--nv-ink);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .14);
    box-sizing: border-box;
}

/* Card header: tile + platform name + selected service name.
   No rule below it and no padding under it: the reference separates the header
   from the quantity row with the card's own 14px gap and nothing else (its
   header measures exactly the 56px tile). The divider added 15px and a line
   the design does not draw. */
.nv-net-card-head {
    display: flex;
    align-items: center;
    gap: 14px;
}

.nv-net-tile {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 56px;
    height: 56px;
    border-radius: 18px;
    background: var(--nv-net-color, var(--nv-brand));
    box-shadow: 0 10px 24px rgba(0, 0, 0, .14);
    color: var(--nv-white);
    /* Letter variant — shown for custom networks not in the SVG map. */
    font-size: 24px;
    font-weight: 700;
    line-height: 1;
    text-transform: uppercase;
}

/* SVG variant — the icon fills the tile; the SVG takes over from the letter. */
.nv-net-tile-icon {
    font-size: 0; /* suppress the empty text node gap in some browsers */
}

.nv-net-card-meta {
    min-width: 0;
}

.nv-net-card-name {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    line-height: 1.2;
}

.nv-net-card-svc {
    /* The selected service name inline after the platform name. */
    font-weight: 700;
}

.nv-net-card-delivery {
    margin: 4px 0 0;
    font-size: 12px;
    color: var(--nv-ink-5);
}

.nv-net-card-delivery:empty {
    display: none;
}

/* Structured delivery line — three pieces the design styles independently:
   the time value (`delivery_start`) is plain weight like the surrounding text,
   and the quality tag (`delivery_tag`) keeps the same plain style.
   The separator dot is aria-hidden so screen readers hear a natural sentence. */
.nv-net-delivery-value {
    font-weight: inherit;
}

.nv-net-delivery-sep {
    /* Purely visual — the screen reader reads "Starts 0-15 min Real-looking". */
}

.nv-net-delivery-tag {
    font-weight: inherit;
}

/* ── Quantity row ─────────────────────────────────────────────────────────── */
.nv-net-qty-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding-top: 12px;
    border-top: 1px solid #f1ecd9;
}

.nv-net-qty-label {
    font-size: 13px;
    color: var(--nv-ink-5);
}

.nv-net-qty-value {
    font-weight: 700;
    font-size: 22px;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

/* ── Quantity slider ──────────────────────────────────────────────────────── */
.nv-net-slider {
    width: 100%;
    margin: 0;
    cursor: pointer;
    accent-color: var(--nv-brand);
}

/* ── Chip labels under the slider ────────────────────────────────────────── */
.nv-net-qty-chips {
    display: flex;
    justify-content: space-between;
    font-size: 11px;
    color: var(--nv-ink-7);
    font-variant-numeric: tabular-nums;
}

/* ── Total price box ──────────────────────────────────────────────────────── */
.nv-net-total-box {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-radius: 18px;
    background: #fdf6dc;
}

.nv-net-total-label {
    margin: 0;
    font-size: 12px;
    color: #7a6200;
}

.nv-net-total-value {
    margin: 2px 0 0;
    font-weight: 700;
    font-size: 26px;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.nv-net-rate-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: 999px;
    background: var(--nv-white);
    font-size: 12px;
    font-weight: 600;
    color: #7a6200;
    white-space: nowrap;
    flex-shrink: 0;
}

/* ── CTA button ───────────────────────────────────────────────────────────── */
.nv-net-cta {
    display: flex;
    width: 100%;
    padding: 13px 20px;
    font-size: 14px;
    justify-content: center;
}

/* ── Orbs (decoration) ────────────────────────────────────────────────────── */
.nv-net-orb {
    position: absolute;
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    pointer-events: none;
}

.nv-net-orb-1 {
    left: calc(50% + 170px);
    top: -6px;
    translate: -40%;
    background: var(--nv-white);
    box-shadow: 0 12px 30px rgba(0, 0, 0, .14);
    color: var(--nv-net-color, var(--nv-brand));
}

.nv-net-orb-2 {
    left: calc(50% - 170px);
    top: -20px;
    translate: -60%;
    background: var(--nv-ink);
    box-shadow: 0 12px 30px rgba(0, 0, 0, .2);
    color: var(--nv-brand);
}

.nv-net-orb-3 {
    left: calc(50% + 170px);
    bottom: -6px;
    translate: -40%;
    background: var(--nv-white);
    box-shadow: 0 12px 30px rgba(0, 0, 0, .14);
    color: var(--nv-ink);
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
    .nv-net-panel {
        grid-template-columns: minmax(0, 1fr);
        gap: 32px;
    }

    .nv-net-orb {
        display: none;
    }

    .nv-net-media {
        min-height: 0;
    }
}

@media (max-width: 560px) {
    .nv-net-tabs {
        gap: 8px;
        margin: 28px 0 22px;
    }

    .nv-net-tab {
        padding: 9px 16px;
    }

    .nv-net-card {
        padding: 22px 20px 20px;
    }

    .nv-net-svc {
        padding: 8px 14px;
        font-size: 12px;
    }
}

/* ── Payments ─────────────────────────────────────────────────────────────────
   Two columns: copy + a dark wallet card on the left, the methods as a
   two-column grid of white cards on the right.

   Numbers from the design's resolved DOM (v2-landing-sections/07-section):
   · Section gap between the two halves: 48px.
   · Wallet wrapper: max-width 400px, margin-top 28px.
   · Warm shim behind card: inset 18px / -14px / -14px / 18px, radius 28px.
   · Card body: radius 28px, padding 26px 28px, gradient 135deg #1b1b1b → #2a2a2a,
     shadow 0 26px 60px rgba(0,0,0,.22), overflow hidden.
   · Orbs: 160px × 160px, orb-1 at right -40px / top -40px, orb-2 at right -10px / top -80px.
   · Balance: 38px / weight 700 / tabular-nums. Cents span: 22px / color #bdbdbd.
   · Last top-up label: 11px / letter-spacing .06em / uppercase / color #9a9a9a.
   · Last top-up value: 14px / weight 600 / margin-top 4px.
   · Status pill: padding 6px 10px / radius 999px / bg rgba(255,255,255,.1) /
     font-size 12px / weight 600 / color rgb(123,228,149). Dot: 6px circle.
   · Foot row: margin-top 26px, gap 12px, align-items flex-end.
   · Ticked list: gap 12px, margin-top 34px, font-size 14px.
   · Check circle: 26px / radius 50% / brand bg.
   · Method cards: radius 22px, padding 24px 22px 20px, min-height 124px,
     border 1px warm, shadow 0 12px 34px rgba(0,0,0,.06), flex-direction column,
     gap 14px. Hover (via [data-card]): translate 0 -6px / shadow 0 24px 48px rgba(0,0,0,.1).

   What is intentionally absent: per-method logos (trademark; the product ships
   none), delivery chips and description lines (the content model has no such
   field; inventing them would promise something the operator did not configure).
   See the Blade for the full reasoning. ────────────────────────────────────── */

/* ── Section layout ──────────────────────────────────────────────────────── */
/* The reference runs this block flush against the one above it: the rhythm of
   the page is a 96px gap here and 192px elsewhere, not an even beat throughout.
   Only the top is dropped — the bottom keeps the section padding. */
.nv-pay {
    padding-top: 0;
}

.nv-pay-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 48px;
    align-items: center;
}

/* Eyebrow margin matches the design's 10px distance from the headline. The
   shared .lp-eyebrow carries 14px; this overrides only the margin. */
.nv-pay-eyebrow {
    margin-bottom: 10px;
}

.nv-pay-lead {
    max-width: 52ch;
}

/* An operator who cleared the subtitle field should not leave a gap under the
   headline; the Studio patches text nodes in place so the node stays in the DOM. */
.nv-pay-eyebrow:empty,
.nv-pay-lead:empty {
    display: none;
}

/* ── Wallet card ─────────────────────────────────────────────────────────── */
.nv-pay-wallet {
    position: relative;
    margin-top: 28px;
    max-width: 400px;
}

/* The warm slab that peeks out from behind the card: offset 18px down and to
   the right, -14px on the other two sides so it tucks under the card edge. */
.nv-pay-wallet-back {
    position: absolute;
    inset: 18px -14px -14px 18px;
    z-index: 0;
    border-radius: 28px;
    background: var(--nv-soft);
}

.nv-pay-wallet-card {
    position: relative;
    z-index: 1;
    /* Four rows fill the card: label + icon / balance / foot. The orbs are 160px
       and bleed out from the top-right corner — in a card that is only as tall as
       its two rows they would swallow the whole surface rather than framing it.
       Matching the drawn height (min-height 206px) keeps the proportions right. */
    min-height: 206px;
    padding: 26px 28px;
    border-radius: 28px;
    background: linear-gradient(135deg, var(--nv-ink) 0%, #2a2a2a 100%);
    color: var(--nv-white);
    box-shadow: 0 26px 60px rgba(0, 0, 0, .22);
    /* overflow:hidden is what clips the orbs to the card's rounded corner. */
    overflow: hidden;
    /* Three areas stacked so the foot sticks to the bottom automatically
       without absolute positioning that would fight the overflow clip. */
    display: flex;
    flex-direction: column;
}

/* ── Orbs ── */
.nv-pay-orb {
    position: absolute;
    width: 160px;
    height: 160px;
    border-radius: 50%;
    /* Pointer events would reach the orbs before the label and icon without this. */
    pointer-events: none;
}

.nv-pay-orb-1 {
    right: -40px;
    top: -40px;
    background: var(--nv-brand);
    opacity: .9;
}

.nv-pay-orb-2 {
    right: -10px;
    top: -80px;
    /* The lighter orb blends over the first; --nv-light is the 52% mix of the
       brand colour, the closest equivalent to the design's #ffe27a. */
    background: var(--nv-light);
    opacity: .55;
}

/* ── Card head: label + wallet icon ── */
.nv-pay-wallet-head {
    position: relative;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.nv-pay-wallet-label {
    font-size: 12px;
    letter-spacing: .08em;
    text-transform: uppercase;
    /* Neutral grey so the label reads the same whatever brand colour is active. */
    color: #bdbdbd;
}

.nv-pay-wallet-ico {
    display: inline-flex;
    padding: 6px;
    border-radius: 10px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

/* ── Balance ── */
.nv-pay-wallet-amount {
    /* position:relative lifts the text above the orbs that sit at z-index 0
       inside the already-positioned card (same pattern as the design). */
    position: relative;
    margin: 22px 0 0;
    font-size: 38px;
    font-weight: 700;
    line-height: 1;
    /* Prevents the figure from shuffling when a digit changes width. */
    font-variant-numeric: tabular-nums;
}

/* Cents match the design: 22px and the same #bdbdbd the label uses. */
.nv-pay-wallet-cents {
    font-size: 22px;
    color: #bdbdbd;
}

/* ── Foot: last top-up + status pill ── */
.nv-pay-wallet-foot {
    position: relative;
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    margin-top: 26px;
    gap: 12px;
    /* Pushes the foot to the bottom of the flex column so the balance floats
       in the space between, matching the design's vertical spacing. */
    margin-top: auto;
    padding-top: 26px;
}

.nv-pay-wallet-topup-label {
    margin: 0;
    font-size: 11px;
    color: var(--nv-ink-7);
    letter-spacing: .06em;
    text-transform: uppercase;
}

.nv-pay-wallet-topup-value {
    margin: 4px 0 0;
    font-size: 14px;
    font-weight: 600;
}

/* The green "Credited" pill: a translucent white container on the dark card,
   with a current-colour dot that doubles as the green indicator. */
.nv-pay-wallet-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .1);
    font-size: 12px;
    font-weight: 600;
    /* Green from the design: rgb(123, 228, 149). */
    color: #7be495;
    /* Keeps the pill aligned to the baseline of the top-up value next to it. */
    white-space: nowrap;
    flex: 0 0 auto;
}

.nv-pay-wallet-status-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentcolor;
    flex: 0 0 auto;
}

/* ── Ticked selling points ───────────────────────────────────────────────── */
.nv-pay-points {
    display: grid;
    gap: 12px;
    margin: 34px 0 0;
    padding: 0;
    list-style: none;
    font-size: 14px;
    color: var(--nv-ink);
}

.nv-pay-point {
    display: flex;
    align-items: center;
    gap: 12px;
}

/* A point whose field is empty has nothing to tick: the whole row hides so
   there is no orphaned circle under the card. */
.nv-pay-point:has(.nv-pay-point-text:empty) {
    display: none;
}

.nv-pay-check {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

/* ── Method cards ────────────────────────────────────────────────────────── */
.nv-pay-cards {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 18px;
}

.nv-pay-card {
    /* An add-on gateway whose driver key is not listed below falls through to
       the brand colour — the same fallback the core block uses. */
    --nv-pay-tint: var(--nv-brand);

    position: relative;
    display: flex;
    flex-direction: column;
    /* Three rows: top (logo + chip) / name / description. gap 14px is the
       design's measured value between the top row and the name. */
    gap: 14px;
    /* min-height stays at 124px from the design spec. The description row is
       optional — suppressed when it would repeat the method name — so a card
       may have two rows instead of three. Cards in the same row are stretched
       to equal height by the grid regardless, so removing the description from
       one card does not misalign its neighbour. */
    min-height: 124px;
    padding: 24px 22px 20px;
    border: 1px solid var(--nv-line);
    border-radius: 22px;
    background: var(--nv-white);
    box-shadow: 0 12px 34px rgba(0, 0, 0, .06);
    /* Hover transition is declared here even though [data-card] on the element
       adds its own; explicit here in case the hook ever changes. */
    transition: transform .35s var(--nv-ease), box-shadow .35s;
}

.nv-pay-card:hover {
    transform: translateY(-6px);
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
}

/* Per-driver tints. Used by the fallback initial-on-tint mark (.nv-pay-mark)
   when the driver is not in the GatewayMarks catalogue. Drivers that DO have a
   catalogue entry (most of them) paint their own colour inside the SVG and do
   not read this variable. The variable is declared on all known drivers anyway
   so a future CSS rule that references it gets a predictable value. */
.nv-pay-card[data-nv-driver='stripe']        { --nv-pay-tint: #635bff; }
.nv-pay-card[data-nv-driver='paypal']        { --nv-pay-tint: #0070ba; }
.nv-pay-card[data-nv-driver='binance']       { --nv-pay-tint: #f0b90b; }
.nv-pay-card[data-nv-driver='binance_manual']{ --nv-pay-tint: #f0b90b; }
.nv-pay-card[data-nv-driver='korapay']       { --nv-pay-tint: #12b76a; }
.nv-pay-card[data-nv-driver='manual']        { --nv-pay-tint: #64748b; }
.nv-pay-card[data-nv-driver='cryptomus']     { --nv-pay-tint: #f7931a; }
.nv-pay-card[data-nv-driver='flutterwave']   { --nv-pay-tint: #f5a623; }
.nv-pay-card[data-nv-driver='paystack']      { --nv-pay-tint: #00c3f7; }
.nv-pay-card[data-nv-driver='razorpay']      { --nv-pay-tint: #0c2451; }
.nv-pay-card[data-nv-driver='phonepe']       { --nv-pay-tint: #5f259f; }
.nv-pay-card[data-nv-driver='paytm_qr']      { --nv-pay-tint: #00baf2; }

/* ── Card top row: logo + chip ── */
.nv-pay-card-top {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 10px;
}

/* Logo area: wraps the SVG brand mark. flex:1 1 auto lets the logo take all
   the space the chip leaves, while min-width:0 stops a wide wordmark from
   pushing the chip off the card.

   `clip` WITH A BLEED, not `hidden`. A wordmark is lettered with whatever the
   visitor's machine resolves for Arial Black, and an italic face leans PAST the
   advance width the mark declares — `textLength` pins the advance, never the
   ink. Measured here: the Stripe mark paints 78.7 units of ink inside a 72-unit
   box and arrived as "Strip", the last letter sliced off. The 8px margin lets
   that overhang paint; the box still stops a mark long enough to reach the
   chip. `hidden` cannot express this — it has no bleed — and dropping the clip
   altogether would let a long mark run under the chip. */
.nv-pay-logo {
    display: inline-flex;
    align-items: center;
    height: 32px;
    min-width: 0;
    flex: 1 1 auto;
    overflow: clip;
    overflow-clip-margin: 8px;
}

/* The SVG inside .nv-pay-logo. The element already carries width and height
   attributes from the catalogue, giving it an intrinsic aspect ratio. CSS
   anchors the height at 32px and lets the width follow the ratio — no style
   attribute needed on the element, and no fixed width that would clip a wide
   wordmark or leave a gap after a narrow icon.

   `overflow: visible` is the other half of the bleed above: an <svg> clips to
   its own viewport by default, so without this the glyph overhang is cut at the
   element's edge before the wrapper ever sees it. */
.nv-pay-logo svg {
    display: block;
    height: 32px;
    width: auto;
    max-width: 100%;
    overflow: visible;
}

/* Fallback mark for drivers not in the GatewayMarks catalogue. Same height and
   flex behaviour as .nv-pay-logo so the top row aligns identically whether the
   slot holds an SVG brand mark or this initial stand-in. The colour deepens so a
   pale-yellow tint does not produce pale-yellow text on a near-white surface. */
.nv-pay-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    width: 40px;
    flex: 0 0 auto;
    border-radius: 10px;
    background: color-mix(in srgb, var(--nv-pay-tint) 14%, #fff);
    color: color-mix(in srgb, var(--nv-pay-tint) 78%, var(--nv-ink));
    font-size: 16px;
    font-weight: 700;
    line-height: 1;
}

/* ── Speed chips ── */
/* Base chip: shared geometry for both variants. flex:0 0 auto prevents the
   chip from stretching or shrinking with the logo beside it. */
.nv-pay-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
    flex: 0 0 auto;
}

/* The dot that precedes the chip label. background:currentColor means it picks
   up the chip's text colour without a separate declaration per variant. */
.nv-pay-chip-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentcolor;
    flex: 0 0 auto;
}

/* "Instant" chip — green semantic colour.
   WHY LITERALS AND NOT TOKENS. The green here is a success/ready signal, not a
   brand colour. Deriving it from --nv-brand would produce wrong hues when an
   operator picks a non-yellow brand (a red brand would give an olive green; a
   blue brand would give a teal). Success green must always read as green,
   independent of the palette. Two local variables document the intent and
   centralise the value for this block only. */
.nv-pay-chip-instant {
    --nv-chip-instant-bg: #e6f6ec;
    --nv-chip-instant-fg: #0f7a3a;

    background: var(--nv-chip-instant-bg);
    color: var(--nv-chip-instant-fg);
}

/* "On confirm" chip — amber wait state.
   The amber DOES come from the theme's warm palette (--nv-soft for the
   background, --nv-deeper for the text) because the pending/wait state is a
   natural part of the same warm tone the design is built on, and it adapts
   correctly when an operator picks a different brand colour. */
.nv-pay-chip-wait {
    background: var(--nv-soft);
    color: var(--nv-deeper);
}

/* ── Card body: name + description ── */
/* gap:0 on the body itself; the 3px margin on .nv-pay-desc is enough
   separation from the name line and keeps the body compact. */
.nv-pay-card-body {
    display: flex;
    flex-direction: column;
}

/* A two-line cap prevents an unusually long operator-supplied name from making
   one card taller than its row neighbours. The CSS grid already equalises row
   heights so a name that wraps to two lines does not break layout, but a name
   long enough to wrap to three (e.g. "Korapay (Cards & Mobile Money)") would
   produce a card shorter than its text. Two lines covers every realistic method
   name while leaving the operator's choice legible. */
.nv-pay-name {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
    color: var(--nv-ink);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}

/* Description: a one-line fact about the gateway. Uses --nv-muted which maps to
   --nv-ink-5 (#7a7a7a), the design's measured text colour for secondary lines.
   Absent when the driver is not in the catalogue — the Blade simply does not
   render the element, so this rule has nothing to do in that case. */
.nv-pay-desc {
    margin: 3px 0 0;
    font-size: 12px;
    color: var(--nv-muted);
}

/* ── Responsive ──────────────────────────────────────────────────────────── */
/* Column collapse is handled by [data-cols] and [data-cols-2] on the nodes
   themselves (00-base.css); only spacing adjustments belong here. */
@media (max-width: 900px) {
    .nv-pay-split {
        gap: 40px;
    }
}

@media (max-width: 560px) {
    .nv-pay-card {
        min-height: 110px;
        padding: 20px 18px 18px;
    }
}

/* ── Blog ─────────────────────────────────────────────────────────────────────
   The heading and a "view all" pill on one baseline, then three article cards
   with a 16/10 photo, a category tag over it and the excerpt under the title.

   Numbers come from the design's resolved DOM (v2-landing-sections/08-blog):
   the head row flex with a 24px gap and the headline 10px under its eyebrow;
   the grid three columns, 24px apart, 36px below the head; the card 24px radius
   over a 1px warm border with 0 12px 36px rgba(0, 0, 0, .07) under it; the cover
   16/10 on the warm paper; the tag 6px/12px on a 999px radius with 0 6px 18px
   rgba(0, 0, 0, .12) and a 7px dot; the body 22px 22px 24px with a 12px gap, the
   date 12px, the title 17px/1.35, the excerpt 13.5px/1.7 and the action row 13px
   with a 22px chevron in the deep tint; the pill 12px/22px at 14px/600.

   What is NOT here is explained in the Blade: the design's reading time and its
   per-category colour have no field in the content model, so the cards carry
   what the product actually knows.

   The cards rise one after another, 100ms apart, exactly as the design staggers
   them — but the delay is declared INSIDE the reveal transition rather than as a
   transition-delay on the card, because the same delay would then sit on the
   hover lift and the third card would answer the pointer a fifth of a second
   late. For the same reason the lift moves `translate` and the reveal moves
   `transform`: two properties, two durations, no interference. */

/* The reference runs this block flush against the one above it: the rhythm of
   the page is a 96px gap here and 192px elsewhere, not an even beat throughout.
   Only the top is dropped — the bottom keeps the section padding. */
.nv-blog {
    padding-top: 0;
}

.nv-blog-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 24px;
    flex-wrap: wrap;
}

.nv-blog-head-copy {
    min-width: 0;
}

/* The design opens straight on the headline: the eyebrow introduces it from
   directly above rather than from the 14px the shared class carries. */
.nv-blog-eyebrow {
    margin: 0;
}

.nv-blog-head .lp-h2 {
    margin: 10px 0 0;
}

.nv-blog-lead {
    max-width: 56ch;
    margin: 14px 0 0;
}

/* A line the operator emptied takes no room. The Studio patches text nodes in
   place, so the node stays in the DOM and comes back with its words. */
.nv-blog-eyebrow:empty,
.nv-blog-lead:empty {
    display: none;
}

/* And a button with no label is a pill that says nothing — the whole control
   goes, chevron included, while the node it would patch stays where it was. */
.nv-blog-all:has(.nv-blog-all-label:empty) {
    display: none;
}

.nv-blog-all {
    flex: 0 0 auto;
    padding: 12px 22px;
    font-size: 14px;
    font-weight: 600;
}

/* ── The grid ─────────────────────────────────────────────────────────────── */
/* One column under 900px through the shared [data-cols] hook the design carries
   on the node itself. */
.nv-blog-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 24px;
    margin-top: 36px;
}

/* ── The card ─────────────────────────────────────────────────────────────── */
.nv-blog-card {
    --nv-blog-delay: 0s;

    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .07);
    transition: translate .35s var(--nv-ease), box-shadow .35s;
}

/* The card is a link, and the theme's links warm up on hover. Here the whole
   card is the target, so tinting it would repaint the headline, the date and the
   excerpt at once — the design lifts the card and leaves the words alone. */
.nv-blog-card,
.nv-blog-card:hover {
    color: inherit;
}

.nv-blog-card:hover {
    translate: 0 -6px;
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
}

.nv-blog-card:nth-child(2) {
    --nv-blog-delay: .1s;
}

.nv-blog-card:nth-child(3) {
    --nv-blog-delay: .2s;
}

/* Specific enough to beat the base layer's own `.lp-js [data-reveal]` rule,
   which is what this replaces: same 800ms reveal, plus the stagger and the two
   properties the hover needs. */
.lp-js .nv-blog-card[data-reveal] {
    transition:
        opacity .8s var(--nv-ease) var(--nv-blog-delay),
        transform .8s var(--nv-ease) var(--nv-blog-delay),
        translate .35s var(--nv-ease),
        box-shadow .35s;
}

/* ── The cover ────────────────────────────────────────────────────────────── */
.nv-blog-cover {
    position: relative;
    display: block;
    aspect-ratio: 16 / 10;
    overflow: hidden;
    /* Warm, not grey: it is what shows while the photo loads, and for the
       fraction of posts that have none it is the whole panel. */
    background: var(--nv-paper);
}

.nv-blog-cover img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.nv-blog-mark {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    color: var(--nv-deep);
    font-size: 54px;
    font-weight: 700;
    line-height: 1;
}

/* ── The category tag ─────────────────────────────────────────────────────── */
.nv-blog-cat {
    position: absolute;
    left: 14px;
    top: 14px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: calc(100% - 28px);
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .12);
    color: var(--nv-ink);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    line-height: 1.4;
    text-transform: uppercase;
}

/* The design marks each category with that platform's own colour. With no
   colour in the content model the dot takes the operator's, which is the one
   colour on this card they did choose. */
.nv-blog-dot {
    width: 7px;
    height: 7px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--nv-brand);
}

/* ── The body ─────────────────────────────────────────────────────────────── */
.nv-blog-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    flex: 1;
    padding: 22px 22px 24px;
}

/* The meta line holds date, a mid-dot separator and the reading time.
   All three sit in a flex row so the separator spaces evenly without a
   non-breaking space, and none of them wrap mid-word. */
.nv-blog-meta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    color: var(--nv-muted);
    flex-wrap: wrap;
}

/* The mid-dot is decorative — already hidden from the accessibility tree
   with aria-hidden in the Blade. A little extra breathing room keeps it
   from touching the adjacent spans on narrow cards. */
.nv-blog-sep {
    padding: 0 2px;
}

.nv-blog-title {
    margin: 0;
    color: var(--nv-ink);
    font-size: 17px;
    font-weight: 700;
    line-height: 1.35;
    text-wrap: pretty;
}

.nv-blog-ex {
    margin: 0;
    /* Reading grey, half a step darker than the date above it — a neutral, so it
       reads the same whatever colour the operator picked. */
    color: var(--nv-ink-4);
    font-size: 13.5px;
    line-height: 1.7;
    /* Takes the slack, which is what keeps the action row on the floor of the
       card when one article is summarised in a line and the next in four. */
    flex: 1;
}

.nv-blog-more {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 4px;
    color: var(--nv-ink);
    font-size: 13px;
    font-weight: 600;
}

/* Third child means the post has no excerpt, so nothing above is growing and
   the action row has to reach the floor by itself. */
.nv-blog-more:nth-child(3) {
    margin-top: auto;
}

.nv-blog-chev {
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--nv-deep);
}

/* The pill is ink on white, so its chevron follows the label rather than
   holding the brand tint the cards use. */
.nv-blog-all .nv-blog-chev {
    color: inherit;
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
    /* The baseline alignment stays: the pill only leaves the heading's line when
       it no longer fits, and until then it belongs to the bottom of the copy —
       hung from the top it reads as a stray control beside the eyebrow. */
    .nv-blog-head {
        gap: 20px;
    }

    .nv-blog-grid {
        margin-top: 28px;
    }
}

@media (max-width: 560px) {
    .nv-blog-body {
        padding: 20px 18px 22px;
    }
}

/* ── Dark mode ────────────────────────────────────────────────────────────── */
/* The landing page does not have a light/dark toggle (its palette is fixed),
   so these rules will never fire on the landing. They are here for completeness
   and for the rare case of someone embedding this block on a page that does have
   the toggle — the card surfaces and hard-coded literal colours must invert. */

/* Card surface: white becomes the dark warm charcoal (same token the blog list
   and article pages use in 92-dark.css). */
html.dark .nv-blog-card {
    background: var(--nv-white);
    border-color: var(--nv-line-2);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .4);
}

html.dark .nv-blog-card:hover {
    box-shadow: 0 24px 48px rgba(0, 0, 0, .55);
}

/* Cover placeholder: warm paper becomes the dark paper token. */
html.dark .nv-blog-cover {
    background: var(--nv-paper);
}

/* Category tag: hard-coded white background. */
html.dark .nv-blog-cat {
    background: var(--nv-white);
    color: var(--nv-ink);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}

/* Excerpt: the hard-coded neutral grey (#6b6b6b) is invisible on the dark card.
   The muted token is already set to the correct dark value by the token block in
   92-dark.css, so simply re-point to it. */
html.dark .nv-blog-ex {
    color: var(--nv-ink-soft);
}

/* ── Inbox showcase ───────────────────────────────────────────────────────────
   A block Nativa adds: a chat client on the left, the promise on the right, on
   the warm page after the payments block.

   Numbers come from the design's resolved DOM (v2-landing-sections/09-section):
   a 48px column gap on centred rows; the client 400px tall, 28px radius, a
   56px channel rail, 0 30px 70px rgba(0, 0, 0, .14) under it and a 1px warm
   border; channel tiles 34px on an 11px radius with 10px between them and a
   16px pip hanging 5px off the corner; the header 14px/16px with a 34px avatar,
   a 13px name and an 11px line under it; bubbles 12.5px on 1.5, 10px/13px of
   padding, a 16px radius with the 4px corner on the sender's side, capped at
   82% of the thread and 10px apart; the composer 12px/16px with a 12px
   placeholder and a 7px/12px send pill; the figures 22px over a 12px label in
   16px-radius cards 14px deep, 14px apart, capped at 460px; the button 14px/30px.

   The client is an ILLUSTRATION: its rail, its pips and its composer are drawn.
   The thread is content, and it plays itself — see public/js/64-inbox.js. */

.nv-inbox-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 48px;
    align-items: center;
}

/* ── The client and the shape behind it ───────────────────────────────────── */
.nv-inbox-media {
    position: relative;
    min-height: 400px;
}

/* The rounded slab leaning out from behind the bottom-left corner. It carries
   no words, so it is a pseudo-element rather than a node the operator can
   select in the Studio and wonder about. */
.nv-inbox-media::before {
    content: '';
    position: absolute;
    left: -20px;
    bottom: -20px;
    z-index: 0;
    width: 150px;
    height: 150px;
    border-radius: 44px;
    background: var(--nv-brand);
    rotate: 10deg;
}

.nv-inbox-app {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr);
    height: 400px;
    max-width: 100%;
    overflow: hidden;
    border: 1px solid var(--nv-line);
    border-radius: 28px;
    background: var(--nv-white);
    box-shadow: 0 30px 70px rgba(0, 0, 0, .14);
}

/* ── The channel rail ─────────────────────────────────────────────────────── */
.nv-inbox-rail {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 16px 0;
    background: var(--nv-ink);
}

.nv-inbox-ch {
    position: relative;
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 11px;
    color: var(--nv-white);
}

/* Each platform's own colour. These are not accents of this design — they are
   what WhatsApp and Instagram look like everywhere — so they stay literal, the
   way the heart on the growth badge does. */
.nv-inbox-ch-wa { background: #25d366; }
.nv-inbox-ch-ms { background: #0084ff; }
.nv-inbox-ch-ig { background: #e1306c; }
.nv-inbox-ch-tg { background: #229ed9; }
.nv-inbox-ch-em { background: #ec3013; }

/* The unread pip is the one mark on the rail that belongs to the design rather
   than to a platform, so it wears the operator's colour. */
.nv-inbox-pip {
    position: absolute;
    top: -5px;
    right: -5px;
    display: grid;
    place-items: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 10px;
    font-weight: 700;
}

/* ── Header, thread, composer ─────────────────────────────────────────────── */
.nv-inbox-pane {
    display: grid;
    /* The thread takes what the header and the composer leave, and minmax(0)
       is what lets it be shorter than its messages — which is the whole point
       of a thread that scrolls its oldest lines out of sight. */
    grid-template-rows: auto minmax(0, 1fr) auto;
    min-width: 0;
}

.nv-inbox-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--nv-line);
}

.nv-inbox-who {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.nv-inbox-avatar {
    display: grid;
    place-items: center;
    flex: none;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 12px;
    font-weight: 700;
}

.nv-inbox-who-text {
    min-width: 0;
}

.nv-inbox-name {
    margin: 0;
    font-size: 13px;
    font-weight: 700;
    line-height: 1.1;
}

.nv-inbox-meta {
    margin: 2px 0 0;
    font-size: 11px;
    color: var(--nv-muted);
}

/* "Open" is a state, not an accent: the green says the same thing in every
   inbox a visitor has ever used, so it does not follow the brand. */
.nv-inbox-state {
    display: inline-flex;
    align-items: center;
    flex: none;
    gap: 6px;
    padding: 5px 10px;
    border-radius: 999px;
    background: #e6f6ec;
    color: #0f7a3a;
    font-size: 11px;
    font-weight: 600;
}

.nv-inbox-state-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentcolor;
}

.nv-inbox-log {
    display: flex;
    flex-direction: column;
    /* Bottom-aligned and clipped: a thread longer than the client pushes its
       oldest lines out of the top, exactly as a real one does, instead of
       growing the card or opening a scrollbar on a landing page. */
    justify-content: flex-end;
    gap: 10px;
    padding: 16px;
    overflow: hidden;
    background: var(--nv-paper-2);
}

.nv-inbox-row {
    display: flex;
}

.nv-inbox-row.is-me {
    justify-content: flex-end;
}

.nv-inbox-bubble {
    max-width: 82%;
    margin: 0;
    padding: 10px 13px;
    border-radius: 16px;
    background: var(--nv-white);
    color: var(--nv-ink);
    font-size: 12.5px;
    line-height: 1.5;
    box-shadow: var(--nv-shadow-sm);
}

/* The square corner points at whoever said it. */
.nv-inbox-row.is-them .nv-inbox-bubble {
    border-bottom-left-radius: 4px;
}

.nv-inbox-row.is-me .nv-inbox-bubble {
    border-bottom-right-radius: 4px;
    background: var(--nv-ink);
    color: var(--nv-white);
}

.nv-inbox-composer {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    border-top: 1px solid var(--nv-line);
}

.nv-inbox-ph {
    flex: 1;
    font-size: 12px;
    color: var(--nv-muted-2);
}

.nv-inbox-spark {
    display: inline-flex;
    color: var(--nv-muted);
}

.nv-inbox-send {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    border-radius: 999px;
    background: var(--nv-ink);
    color: var(--nv-brand);
    font-size: 12px;
    font-weight: 600;
}

/* The timestamp sits inside the bubble, right-aligned below the text. The
   design's span[data-dc-tpl="311"] uses `display:block; margin-top:4px;
   font-size:10px; opacity:0.6; text-align:right` — reproduced here with
   classes so the bubble `<p>` can contain both without inline styles. */
.nv-inbox-time {
    display: block;
    margin-top: 4px;
    font-size: 10px;
    /* 15px: the one place on this page where the design declares its own
       line-height explicitly — keep it, do not normalise to `normal`. */
    line-height: 15px;
    opacity: 0.6;
    text-align: right;
}

/* ── The thread playing itself ────────────────────────────────────────────── */
/* Nothing here is hidden until the script says it is wired. A page that never
   receives it shows the whole conversation at once, which is the design with
   the animation already finished — never an empty card. */
[data-nv-inbox-play] .nv-inbox-row {
    display: none;
}

[data-nv-inbox-play] .nv-inbox-row.is-in {
    display: flex;
    animation: nv-msg-in .45s cubic-bezier(.2, .8, .2, 1) both;
}

.nv-inbox-typing {
    display: none;
}

[data-nv-inbox-play] .nv-inbox-typing.is-on {
    display: flex;
    animation: nv-msg-in .45s cubic-bezier(.2, .8, .2, 1) both;
}

/* The dots lean the way the bubble they are waiting for will. */
.nv-inbox-typing.is-me {
    justify-content: flex-end;
}

.nv-inbox-typing.is-me .nv-inbox-dots {
    border-bottom-right-radius: 4px;
    background: var(--nv-ink);
}

.nv-inbox-typing.is-them .nv-inbox-dots {
    border-bottom-left-radius: 4px;
}

.nv-inbox-dots {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 12px 14px;
}

.nv-inbox-dots i {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--nv-muted-2);
    animation: nv-dot-bounce 1.2s infinite ease-in-out;
}

.nv-inbox-dots i:nth-child(2) {
    animation-delay: .15s;
}

.nv-inbox-dots i:nth-child(3) {
    animation-delay: .3s;
}

/* A message the operator emptied leaves no bubble hanging in the thread, and one
   keystroke in the Studio brings it back — the node never left the DOM. Stated
   after the playing rules, and once more with their weight, because an emptied
   line must stay gone whether the thread is playing or already finished.

   Each bubble is now a <p> that contains a <span> for the text and optionally
   one for the timestamp. The selector targets the text span being empty rather
   than the bubble itself, which would never be :empty once it has children. */
.nv-inbox-row:has(> .nv-inbox-bubble > span:first-child:empty),
[data-nv-inbox-play] .nv-inbox-row.is-in:has(> .nv-inbox-bubble > span:first-child:empty) {
    display: none;
}

/* ── The AI-agent badge ───────────────────────────────────────────────────── */
/* Positioned over the top-right corner of the card, matching the design's
   div[data-dc-tpl="321"]: right:-18px; top:-18px; z-index:2. The bob comes
   from [data-float="2"] in the shared base stylesheet (5s, −1.5s offset). */
.nv-inbox-ai-badge {
    position: absolute;
    right: -18px;
    top: -18px;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 16px;
    background: var(--nv-white);
    box-shadow: 0 16px 40px rgba(0, 0, 0, .14);
    font-size: 12px;
    /* Keeps the badge from growing wider than necessary on narrow viewports
       where the card's right edge is close to the page edge. */
    white-space: nowrap;
}

/* The robot-head icon sits in an ink square with the brand colour — exactly
   the 32px × 32px, 10px-radius tile the design draws at position [322]. */
.nv-inbox-ai-icon {
    display: grid;
    place-items: center;
    flex: none;
    width: 32px;
    height: 32px;
    border-radius: 10px;
    background: var(--nv-ink);
    color: var(--nv-brand);
}

.nv-inbox-ai-text {
    /* Both lines share a single text column; no gap needed because line-height
       1.1 on the name and a 2px top-margin on the sub-line are sufficient. */
}

.nv-inbox-ai-name {
    margin: 0;
    font-weight: 700;
    line-height: 1.1;
}

.nv-inbox-ai-reply {
    margin: 2px 0 0;
    color: var(--nv-muted);
}

/* ── Contact meta desglose ────────────────────────────────────────────────── */
/* The channel name and ticket number sit inline in the same 11px muted line.
   The design uses regular weight (400) — no emphasis here. */
:where(.nv-inbox-meta) .nv-inbox-meta-channel {
    font-weight: 400;
}

:where(.nv-inbox-meta) .nv-inbox-meta-ticket {
    font-weight: 400;
}

/* ── The promise ──────────────────────────────────────────────────────────── */
.nv-inbox-copy .lp-eyebrow {
    margin: 0;
}

.nv-inbox-copy .lp-h2 {
    margin-top: 10px;
}

.nv-inbox-copy .lp-lead {
    margin-top: 18px;
    max-width: 52ch;
    line-height: 1.8;
}

/* A line the operator emptied takes no room, heading included: the Studio
   patches text in place, so these nodes stay and collapse. */
.nv-inbox-copy .lp-eyebrow:empty,
.nv-inbox-copy .lp-h2:empty,
.nv-inbox-copy .lp-lead:empty,
.nv-inbox-name:empty,
.nv-inbox-meta:empty,
.nv-inbox-fig-value:empty,
.nv-inbox-fig-label:empty {
    display: none;
}

/* Three across, as drawn. Declared by track width rather than by a count so a
   fourth figure — the schema allows one — lands in the same row instead of
   sitting alone under the other three. */
.nv-inbox-figs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: 14px;
    margin-top: 26px;
    max-width: 460px;
}

.nv-inbox-fig {
    padding: 14px;
    border: 1px solid var(--nv-line);
    border-radius: 16px;
    background: var(--nv-white);
}

.nv-inbox-fig-value {
    margin: 0;
    font-size: 22px;
    font-weight: 700;
    line-height: 1;
}

.nv-inbox-fig-label {
    margin: 4px 0 0;
    font-size: 12px;
    color: var(--nv-muted);
}

.nv-inbox-cta {
    margin-top: 28px;
    padding: 14px 30px;
    font-size: 14px;
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
/* The split itself collapses through the shared [data-cols] hook. */
@media (max-width: 900px) {
    .nv-inbox-media {
        /* On one column the client would stretch the width of the page and a
           400px-tall chat that wide reads as a banner, not as a phone someone
           is answering. Capped and centred instead. */
        max-width: 520px;
        margin-inline: auto;
    }

    .nv-inbox-copy .lp-lead {
        max-width: none;
    }
}

@media (max-width: 560px) {
    .nv-inbox-app {
        border-radius: 22px;
    }

    /* The slab shrinks with the card: at this width it was reaching a third of
       the way across the thread. */
    .nv-inbox-media::before {
        width: 104px;
        height: 104px;
        border-radius: 30px;
    }
}

/* ── How it works ─────────────────────────────────────────────────────────────
   Two columns: the heading and a framed piece of artwork on the left, the steps
   as a stack of white cards on the right with one of them lit.

   Numbers come from the design's resolved DOM (v2-landing-sections/10-how):
   a 48px gap between the columns, centred; the lead at 14px/1.8 capped at 48ch;
   the artwork 32px under the copy — a 120px brand tile at 36px radius rotated
   12deg and offset -16px/-16px, a 300px frame at 28px radius under
   0 26px 60px rgba(0, 0, 0, .14), and a white pill at -18px/-18px with an 18px
   radius, 12px 18px 12px 12px of padding and a 40px tile at 12px radius; the
   cards 18px apart, 20px 24px of padding, a 20px radius, a 2px border and
   0 10px 30px rgba(0, 0, 0, .07); the number a 48px circle at 15px/700; the
   title 16px/600, the text 13px/1.7.

   The lit state transitions in .5s — the design's own figure, and twice as slow
   as anything this page does on hover, which is what says it is on a timer
   rather than under a pointer. The script that drives it is public/js/65-steps.js.

   What is NOT here is explained in the Blade: the design's photograph and the
   delivered-order pill have no field in the content model. */

.nv-step-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 48px;
    align-items: center;
}

/* The design opens on the headline and lets the eyebrow sit tight above it,
   which is tighter than the 14px the shared class carries. */
.nv-step-eyebrow {
    margin: 0 0 10px;
}

.nv-step-lead {
    margin: 18px 0 0;
    line-height: 1.8;
    /* A neutral grey the design spells out for this block — not a brand shade,
       so it stays a literal rather than borrowing a token that is not it. */
    color: var(--nv-ink-3);
    max-width: 48ch;
}

/* A line the operator emptied takes no room. The Studio patches text nodes in
   place, so the node stays in the DOM and comes back with its words. */
.nv-step-eyebrow:empty,
.nv-step-lead:empty {
    display: none;
}

/* ── The artwork ──────────────────────────────────────────────────────────── */
.nv-step-art {
    position: relative;
    margin-top: 32px;
}

/* The brand tile leaning out from behind the frame's top-right corner. */
.nv-step-art-tile {
    position: absolute;
    top: -16px;
    right: -16px;
    z-index: 0;
    width: 120px;
    height: 120px;
    border-radius: 36px;
    background: var(--nv-brand);
    rotate: 12deg;
}

/* The design's photo frame, keeping its geometry and filled with the theme's
   own light instead — the content model has no image field to fill it with.
   Deliberately the PALE end of the palette: at 525 × 300 this is the largest
   single shape on the page, and painted in full brand it would outshout the
   steps beside it, which are the block. The tile behind it stays the accent. */
.nv-step-art-frame {
    position: relative;
    z-index: 1;
    display: grid;
    place-items: center;
    overflow: hidden;
    height: 300px;
    border-radius: 28px;
    background: linear-gradient(150deg, var(--nv-paper), var(--nv-soft));
    box-shadow: 0 26px 60px rgba(0, 0, 0, .14);
    color: var(--nv-deep);
}

/* The operator's own picture, when they gave one. `cover` inside a fixed frame
   is the reference's own treatment: whatever they upload fills the shape rather
   than letterboxing inside it, so the block keeps its geometry no matter what
   comes out of their camera. */
.nv-step-art-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.nv-step-art-orb {
    position: absolute;
    border-radius: 50%;
    background: rgba(255, 255, 255, .55);
}

.nv-step-art-orb-1 {
    top: -70px;
    right: -50px;
    width: 220px;
    height: 220px;
}

.nv-step-art-orb-2 {
    bottom: -90px;
    left: -60px;
    width: 260px;
    height: 260px;
    background: var(--nv-light);
    opacity: .35;
}

/* ── The theme's own artwork ──────────────────────────────────────────────────
   Drawn, not photographed: the reference fills this frame with stock of people
   at a table, and that picture cannot travel inside something we sell. What is
   here instead is the product doing its job — an order card with its delivery
   climbing — so the frame says something true about the panel rather than
   standing in as decoration. Every shape reads a token, so it wears the
   operator's colour like the rest of the page.

   `.nv-step-art-mark` is kept: it is the old single glyph, still used by nothing
   in this file, and removing the rule would leave a package upgrade with an
   unstyled icon if a cached view is served for one request after the swap. */
/* Fills the frame the way the reference's photograph does. The drawing is 440×240
   and the frame 566×300 — near enough in proportion that the few pixels clipped
   top and bottom fall in the margin the artwork leaves around itself. */
.nv-step-art-scene {
    position: relative;
    width: 100%;
    height: auto;
}

.nv-step-art-card {
    fill: var(--nv-white);
}

.nv-step-art-dot {
    fill: var(--nv-line);
}

/* The service tile: the brand square the design puts beside every row. */
.nv-step-art-tile-sm {
    fill: var(--nv-brand);
}

.nv-step-art-line {
    fill: var(--nv-line);
}

.nv-step-art-line-soft {
    opacity: .6;
}

.nv-step-art-curve {
    fill: none;
    stroke: var(--nv-brand);
    stroke-width: 3;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.nv-step-art-head {
    fill: var(--nv-ink);
}

/* Painted here rather than on the <stop> for the same reason as the growth
   chart: a presentation attribute takes a literal, and a literal is what a
   white-label design must not carry. */
.nv-step-art-stop-top {
    stop-color: var(--nv-brand);
    stop-opacity: .38;
}

.nv-step-art-stop-bottom {
    stop-color: var(--nv-brand);
    stop-opacity: 0;
}

/* The floating card, top-right — the same shape the design repeats over every
   piece of artwork on this page. It sits INSIDE the frame (unlike the delivery
   pill, which overhangs) so the two never collide on a narrow column. */
.nv-step-art-chip {
    position: absolute;
    right: 18px;
    top: 22px;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 16px;
    background: var(--nv-white);
    box-shadow: 0 12px 30px rgba(0, 0, 0, .12);
}

.nv-step-art-chip-ico {
    display: inline-flex;
    color: #e0245e;
}

.nv-step-art-chip-lines {
    display: grid;
    gap: 6px;
}

.nv-step-art-chip-line {
    display: block;
    width: 54px;
    height: 7px;
    border-radius: 3.5px;
    background: var(--nv-line);
}

.nv-step-art-chip-line-2 {
    width: 34px;
    opacity: .6;
}

.nv-step-art-mark {
    position: relative;
    opacity: .45;
}

.nv-step-pill {
    position: absolute;
    left: -18px;
    bottom: -18px;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 18px 12px 12px;
    border-radius: 18px;
    background: var(--nv-white);
    box-shadow: 0 16px 40px rgba(0, 0, 0, .14);
}

/* The one green in this design: a confirmation, not a brand accent, so it does
   not follow the operator's colour. */
.nv-step-pill-ico {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    border-radius: 12px;
    background: #e6f6ec;
    color: #0f7a3a;
}

/* The pill wraps both lines so the icon and the text block sit side by side. */
.nv-step-pill-body {
    min-width: 0;
}

/* Primary line: the order headline, 14px/700 — matches the design's resolved
   font-size and line-height exactly (14px, line-height 1). */
.nv-step-pill-text {
    margin: 0;
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
    color: var(--nv-ink);
}

/* Secondary line: the metric (followers · time), 12px/400 in the design's
   muted grey rgb(122,122,122). Not a brand shade, so it stays a literal
   mapped to the token that is closest in value. */
.nv-step-pill-sub {
    margin: 4px 0 0;
    font-size: 12px;
    color: var(--nv-muted);
}

/* ── The steps ────────────────────────────────────────────────────────────── */
.nv-step-list {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.nv-step-card {
    display: flex;
    align-items: flex-start;
    gap: 18px;
    padding: 20px 24px;
    border: 2px solid transparent;
    border-radius: 20px;
    background: var(--nv-white);
    box-shadow: 0 10px 30px rgba(0, 0, 0, .07);
    transition: border-color .5s, transform .5s var(--nv-ease);
}

/* Three ways in, one look. The class is what the cycle moves and what the
   server renders on the first card; :hover and :focus-within are what keeps the
   block answering a pointer or a keyboard on a page that never got the script. */
.nv-step-card.is-on,
.nv-step-card:hover,
.nv-step-card:focus-within {
    border-color: var(--nv-brand);
    transform: translateX(-8px);
}

.nv-step-num {
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 15px;
    font-weight: 700;
    transition: background .5s, color .5s;
}

/* The lit card inverts its number: ink disc, brand figure. */
.nv-step-card.is-on .nv-step-num,
.nv-step-card:hover .nv-step-num,
.nv-step-card:focus-within .nv-step-num {
    background: var(--nv-ink);
    color: var(--nv-brand);
}

.nv-step-body {
    min-width: 0;
}

.nv-step-title {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    color: var(--nv-ink);
}

.nv-step-text {
    margin: 6px 0 0;
    font-size: 13px;
    line-height: 1.7;
    color: var(--nv-ink-4);
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
/* [data-cols] collapses the split at 900px (00-base.css). Stacked, the artwork
   sits between the heading and the steps, so it stops being a column-filler and
   is given the width it is worth. */
@media (max-width: 900px) {
    .nv-step-art {
        max-width: 460px;
    }
}

@media (max-width: 560px) {
    .nv-step-art-frame {
        height: 220px;
    }

    .nv-step-art-tile {
        width: 92px;
        height: 92px;
        border-radius: 28px;
    }

    .nv-step-pill {
        left: 0;
        bottom: -14px;
    }

    .nv-step-card {
        gap: 14px;
        padding: 18px 18px;
    }

    .nv-step-num {
        width: 42px;
        height: 42px;
        font-size: 14px;
    }

    /* The 8px the lit card slides is a nudge on a wide screen and a dent in the
       page's gutter on a phone. */
    .nv-step-card.is-on,
    .nv-step-card:hover,
    .nv-step-card:focus-within {
        transform: none;
    }
}

/* ── FAQ ──────────────────────────────────────────────────────────────────────
   A 5/7 split: the heading and a dark support card that follow the reader down
   the left, the questions as an accordion of white cards on the right.

   Numbers come from the design's resolved DOM (v2-landing-sections/11-faq):
   minmax(0, 5fr) / minmax(0, 7fr) with a clamp(32px, 5vw, 72px) gap, aligned to
   the start; the aside sticky at 110px; the title 10px under the eyebrow; the
   support card 28px below it, capped at 360px, 22px 24px of padding at a 24px
   radius with a 14px gap, a 44px tile at 14px radius and a 15px/700 line; its
   button 12px 20px at 14px/600. The questions 14px apart: a 20px radius, a 2px
   border and 0 10px 30px rgba(0, 0, 0, .05); the summary 18px 20px at 15px/600
   with a 16px gap; the number a 34px circle at 12px/700, the chevron a 32px
   circle on the palest warm tint; the answer 14px/1.75 with 0 22px 22px 70px of
   padding — 70px is 20 + 34 + 16, so the prose starts under the question and
   not under its number.

   EVERY STATE IS [open]. The accordion is <details>, so the brand border, the
   inverted number and the plus turning into a cross need no script; the three
   transitions are the design's own .3s.

   The answer is rich text and prints into `.rf-richtext`. Nativa is standalone —
   the product emits no landing stylesheet while it is on — so the prose rules at
   the bottom of this file are the only ones that dress it. */

/* The reference runs this block flush against the one above it: the rhythm of
   the page is a 96px gap here and 192px elsewhere, not an even beat throughout.
   Only the top is dropped — the bottom keeps the section padding. */
.nv-faq {
    padding-top: 0;
}

.nv-faq-grid {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: clamp(32px, 5vw, 72px);
    align-items: start;
}

/* No published questions: the heading takes the page rather than leaving the
   second column standing empty beside it. */
.nv-faq-grid-solo {
    grid-template-columns: minmax(0, 1fr);
}

/* The questions are the long column, so the heading rides down with them.
   max-height guards the case where the aside itself exceeds the viewport: a
   sticky element taller than the window scrolls its own overflow out of reach
   (the bottom of the card becomes unreachable). overflow-y: auto adds a local
   scrollbar only when that actually happens — not in the common case. */
.nv-faq-aside {
    position: sticky;
    top: 110px;
    max-height: calc(100vh - 120px);
    overflow-y: auto;
}

.nv-faq-eyebrow {
    margin: 0;
}

.nv-faq-title {
    margin: 10px 0 0;
}

/* A line the operator emptied takes no room. The Studio patches text nodes in
   place, so the node stays in the DOM and comes back with its words. */
.nv-faq-eyebrow:empty,
.nv-faq-title:empty {
    display: none;
}

/* Lead paragraph under the section title. The design puts this at 14px / 1.8
   with a muted colour, capped to ~40 characters — matching the reference DOM. */
.nv-faq-lead {
    margin: 18px 0 0;
    max-width: 40ch;
    font-size: 14px;
    line-height: 1.8;
    color: var(--nv-ink-3);
}

/* ── The support card ─────────────────────────────────────────────────────── */
.nv-faq-support {
    display: flex;
    flex-direction: column;
    gap: 14px;
    max-width: 360px;
    margin-top: 28px;
    padding: 22px 24px;
    border-radius: 24px;
    background: var(--nv-ink);
    color: var(--nv-white);
}

.nv-faq-support-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.nv-faq-support-ico {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    flex: 0 0 auto;
    border-radius: 14px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

.nv-faq-support-title {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
    line-height: 1.1;
}

/* Response-time line from the design: 12px / dimmed white, 4px below the title. */
.nv-faq-support-meta {
    margin: 4px 0 0;
    font-size: 12px;
    /* The design uses rgb(189, 189, 189) on the dark card background. The card
       background is --nv-ink (the darkest token), so this is a literal rather
       than a brand-derived token — it is decorative dimming, not a content role. */
    color: rgb(189, 189, 189);
}

.nv-faq-support-cta {
    padding: 12px 20px;
    font-size: 14px;
}

/* ── The accordion ────────────────────────────────────────────────────────── */
.nv-faq-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.nv-faq-item {
    border: 2px solid transparent;
    border-radius: 20px;
    background: var(--nv-white);
    box-shadow: 0 10px 30px rgba(0, 0, 0, .05);
    transition: border-color .3s;
}

.nv-faq-item[open] {
    border-color: var(--nv-brand);
}

.nv-faq-q {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 18px 20px;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    /* The native disclosure triangle, removed twice: `list-style` covers the
       standard marker, the pseudo-element covers WebKit's older one. */
    list-style: none;
}

.nv-faq-q::-webkit-details-marker {
    display: none;
}

.nv-faq-q:hover {
    background: var(--nv-paper-2);
    /* Two pixels inside the card's 20px, so the tint never squares off the
       corner it sits in. */
    border-radius: 18px;
}

.nv-faq-num {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 12px;
    font-weight: 700;
    transition: background .3s, color .3s;
}

.nv-faq-item[open] .nv-faq-num {
    background: var(--nv-ink);
    color: var(--nv-brand);
}

.nv-faq-text {
    flex: 1 1 0;
    min-width: 0;
}

/* The plus becomes a cross by turning 45deg — the design's own move, and it is
   why the glyph is a plus and not a chevron. */
.nv-faq-chev {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--nv-paper);
    color: var(--nv-ink);
    transition: transform .3s, background .3s, color .3s;
}

.nv-faq-item[open] .nv-faq-chev {
    transform: rotate(45deg);
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

/* ── The answer ───────────────────────────────────────────────────────────── */
.nv-faq-body {
    padding: 0 22px 22px 70px;
    font-size: 14px;
    line-height: 1.75;
    /* A neutral grey the design spells out for this block — not a brand shade,
       so it stays a literal rather than borrowing a token that is not it. */
    color: var(--nv-ink-4);
}

/* The operator writes this in the editor, so it can be anything the rich text
   filter allows. The first and last blocks lose their outer margin, which is
   what keeps a one-paragraph answer sitting exactly where the design draws it. */
.nv-faq-body > :first-child {
    margin-top: 0;
}

.nv-faq-body > :last-child {
    margin-bottom: 0;
}

.nv-faq-body p {
    margin: 0 0 12px;
}

.nv-faq-body :where(h1, h2, h3, h4) {
    margin: 18px 0 8px;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.4;
    color: var(--nv-ink);
}

.nv-faq-body :where(ul, ol) {
    margin: 0 0 12px;
    padding-left: 20px;
    list-style: revert;
}

.nv-faq-body li {
    margin: 4px 0;
}

.nv-faq-body a {
    color: var(--nv-deep);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.nv-faq-body :where(strong, b) {
    color: var(--nv-ink);
}

.nv-faq-body img {
    height: auto;
    border-radius: 14px;
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
/* [data-cols] collapses the split at 900px (00-base.css). Stacked, a heading
   that follows the reader would sit on top of the answers it introduces. */
@media (max-width: 900px) {
    .nv-faq-aside {
        position: static;
    }
}

@media (max-width: 560px) {
    .nv-faq-q {
        gap: 12px;
        padding: 16px;
        font-size: 14px;
    }

    /* The prose gives up its alignment with the question rather than the width
       it needs to be read. */
    .nv-faq-body {
        padding: 0 16px 18px;
    }
}

/* ── Dark mode ────────────────────────────────────────────────────────────────
   The public layout (layouts/public) toggles html.dark. The landing is fixed-
   light so these rules only fire on content pages (FAQ standalone page, etc.)
   that wear the Nativa design via data-rf-theme.

   Only elements that paint a hard-coded literal in the light design need an
   explicit rule; everything using a token (--nv-ink, --nv-brand, --nv-paper,
   --nv-paper-2) flips automatically through 92-dark.css. */
html.dark [data-rf-theme='nativa'] .nv-faq-lead {
    /* --nv-ink-soft is already overridden in 92-dark.css to a warm mid-grey. */
    color: var(--nv-ink-soft);
}

html.dark [data-rf-theme='nativa'] .nv-faq-item {
    /* The card background flips via --nv-white. The shadow at 5% black is
       invisible on a dark surface — replace with the deeper elevation hint. */
    box-shadow: var(--nv-shadow);
}

html.dark [data-rf-theme='nativa'] .nv-faq-q:hover {
    /* --nv-paper-2 is overridden in 92-dark.css, so the hover tint is correct. */
    background: var(--nv-paper-2);
}

html.dark [data-rf-theme='nativa'] .nv-faq-body {
    /* The hard-coded #6b6b6b reads as near-invisible on a dark card surface;
       replace with the dimmer ink token that 92-dark.css has already calibrated
       for readability at this weight. */
    color: var(--nv-ink-soft);
}

/* ── Testimonials ─────────────────────────────────────────────────────────────
   A centred heading, a white rating pill, and three white quote cards across.

   Numbers come from the design's resolved DOM (v2-landing-sections/12-section):
   the eyebrow at 15px/600 with the headline 10px under it; the pill 8px 16px on
   a 999px radius with a 0 8px 24px shadow at 13px/600, 18px above and 36px below
   it; the row three columns with a 24px gap; each card 24px radius, 30px 28px
   26px of padding, a 0 12px 36px shadow, a 1px warm border and an 18px gap
   between its parts; the quote glyph 72px of Georgia at 20px from the right and
   10px from the top; the avatar 56px inside a 3px ring; the name 15px/700, the
   role 12px, the quote 14px/1.75; the stars 16px with a 2px gap; and the reveal
   staggered 0s / .12s / .24s across the row.

   THE PILL HAS TWO NODES. The score ("4.9 / 5") is black/600 and the count
   ("· 2,340 reviews") is the design's muted grey (#7a7a7a) at weight 500.
   They are separate spans so the Studio can patch each independently.

   THE ROW IS A GRID FIRST AND A CAROUSEL SECOND. Three testimonials is the
   arrangement that was drawn and it is what this file paints by default. The
   Studio's list has no ceiling, so once there are more cards than fit the row
   scrolls one card at a time — but only while the theme's script is running:
   `.lp-js` turns the grid into the scroller (that class is on the page before
   paint, so no flash), and `[data-nv-ready]`, which public/js/67-testimonials.js
   sets on the section ONLY after measuring real overflow, is what draws the
   arrows. A page without the script shows every testimonial in a wrapping grid;
   a row with nothing behind its edge shows no controls at all. */

/* The reference runs this block flush against the one above it: the rhythm of
   the page is a 96px gap here and 192px elsewhere, not an even beat throughout.
   Only the top is dropped — the bottom keeps the section padding. */
.nv-tm {
    padding-top: 0;
}

.nv-tm-head {
    text-align: center;
}

/* The design opens on the eyebrow with the headline tight under it, rather than
   with the 14px the shared rule gives every other block. */
.nv-tm-eyebrow {
    margin: 0 0 10px;
}

/* A line the operator emptied takes no room. The Studio patches text nodes in
   place, so the node stays in the DOM and comes back with its words. */
.nv-tm-eyebrow:empty {
    display: none;
}

/* ── The rating pill ──────────────────────────────────────────────────────── */
/* The pill sits between the headline and the card row. It is an inline-flex row
   so long scores do not wrap mid-pill, and it is centred by the text-align on
   the parent rather than by margin:auto so it stays centred without a width. */
.nv-tm-rating {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin: 18px 0 36px;
    padding: 8px 16px;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .06);
    font-size: 13px;
    font-weight: 600;
    color: var(--nv-ink);
    text-align: start;
}

/* The pill exists to carry the score. With no score it would be five loose stars
   and a stray review count making a claim nobody wrote, so it goes entirely. */
.nv-tm-rating:has(.nv-tm-rating-score:empty) {
    display: none;
}

/* The score node: "4.9 / 5" — inherits the pill's 600 weight and ink colour. */
.nv-tm-rating-score {
    max-width: 16ch;
}

/* The count node: "· 2,340 reviews" — the design's #7a7a7a at weight 500.
   Stays in the DOM when empty so the Studio can patch it back in place; its
   :empty rule hides it visually without removing the node. */
.nv-tm-rating-count {
    font-weight: 500;
    color: var(--nv-muted);
}

.nv-tm-rating-count:empty {
    display: none;
}

.nv-tm-stars {
    display: inline-flex;
    flex: 0 0 auto;
    gap: 2px;
    color: var(--nv-brand);
}

/* ── The row ──────────────────────────────────────────────────────────────── */
/* No script: a plain grid that wraps, which is the only arrangement that shows
   every testimonial the operator wrote. */
.nv-tm-track {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 24px;
    text-align: start;
}

/* With the script: one row of cards a third of the width each, snapping. The
   arithmetic is the design's own — three columns and two 24px gaps — so three
   testimonials fill the row exactly and nothing scrolls. */
.lp-js .nv-tm-track {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - 48px) / 3);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    /* A scroller clips on BOTH axes, and these cards carry a 36px shadow and
       rise 30px as they reveal. The padding gives that room back and the equal
       negative margin keeps the row where the design put it. */
    padding: 18px 0 46px;
    margin: -18px 0 -46px;
    /* Hidden because the arrows below are the affordance, and they are only
       drawn when this actually scrolls. */
    scrollbar-width: none;
}

.lp-js .nv-tm-track::-webkit-scrollbar {
    display: none;
}

.lp-js .nv-tm-card {
    scroll-snap-align: start;
}

/* ── The card ─────────────────────────────────────────────────────────────── */
.nv-tm-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 18px;
    margin: 0;
    padding: 30px 28px 26px;
    border-radius: 24px;
    /* The design's #f4efdc — the warm line this theme derives from the brand. */
    border: 1px solid var(--nv-line);
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .07);
    transition: transform .35s var(--nv-ease), box-shadow .35s;
}

.nv-tm-card:hover {
    transform: translateY(-6px);
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
}

/* Under the product's reveal this card is ALSO the element that fades up, and
   that shared rule lands with more weight than a plain :hover — so once a card
   has arrived it would never lift again. The arrived state restates the lift,
   and restates the transition too, because the shared rule replaced the card's
   own with one written for a fade. */
.lp-js .nv-tm-card[data-reveal].lp-in {
    transition: opacity .8s var(--nv-ease), transform .35s var(--nv-ease), box-shadow .35s;
}

/* The stagger the reference carries as a style attribute on each card. Written
   per column so it survives the row wrapping and a fourth testimonial. */
.lp-js .nv-tm-card[data-reveal].lp-in:nth-child(3n + 2) {
    transition-delay: .12s;
}

.lp-js .nv-tm-card[data-reveal].lp-in:nth-child(3n) {
    transition-delay: .24s;
}

.lp-js .nv-tm-card[data-reveal].lp-in:hover {
    transform: translateY(-6px);
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
    /* Or the third card starts moving a quarter of a second after the pointer
       arrives, wearing the delay it needed once. */
    transition-delay: 0s;
}

.nv-tm-mark {
    position: absolute;
    right: 20px;
    top: 10px;
    z-index: 0;
    font-family: Georgia, 'Times New Roman', serif;
    font-size: 72px;
    font-weight: 700;
    line-height: 1;
    color: var(--nv-soft);
    pointer-events: none;
}

.nv-tm-by {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 14px;
}

/* The ring the design draws around the customer's photograph, with the initials
   the content model does store inside it. Brand on the tile, the theme's own
   answer everywhere a face is missing. */
.nv-tm-avatar {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 62px;
    height: 62px;
    border: 3px solid var(--nv-soft);
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 18px;
    font-weight: 700;
    line-height: 1;
    text-transform: uppercase;
}

.nv-tm-name {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
}

.nv-tm-role {
    margin: 2px 0 0;
    font-size: 12px;
    color: var(--nv-muted);
}

.nv-tm-quote {
    flex: 1 1 0;
    margin: 0;
    font-size: 14px;
    line-height: 1.75;
    /* The design's #5f5f5f — softened ink, not the muted grey the roles use. */
    color: var(--nv-ink-3);
}

.nv-tm-card .nv-tm-stars {
    display: flex;
}

/* ── The arrows ───────────────────────────────────────────────────────────── */
/* Offered only once the script has measured a row with something behind its
   edge: an arrow that cannot move anything is worse than no arrow. */
.nv-tm-nav {
    display: none;
    justify-content: center;
    gap: 12px;
    margin-top: 32px;
}

[data-nv-ready] .nv-tm-nav {
    display: flex;
}

.nv-tm-arrow {
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--nv-white);
    /* The pill's shadow, because these two belong to the same block. */
    box-shadow: 0 8px 24px rgba(0, 0, 0, .06);
    color: var(--nv-ink);
    cursor: pointer;
    transition: background .25s, color .25s, transform .25s var(--nv-ease);
}

.nv-tm-arrow:hover:not(:disabled) {
    transform: translateY(-2px);
    background: var(--nv-ink);
    color: var(--nv-brand);
}

/* Disabled rather than removed: the pair keeps its place at both ends, so the
   row does not shift under the pointer that is using it. */
.nv-tm-arrow:disabled {
    opacity: .35;
    cursor: default;
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
/* One card across, which is the design's own decision for this row ([data-cols]
   in the reference). It cannot be borrowed here: that hook sets
   grid-template-columns, and the scrolling row is sized by grid-auto-columns. */
@media (max-width: 900px) {
    .nv-tm-track {
        grid-template-columns: minmax(0, 1fr);
    }

    .lp-js .nv-tm-track {
        grid-template-columns: none;
        grid-auto-columns: 100%;
    }
}

@media (max-width: 560px) {
    .nv-tm-rating {
        margin-bottom: 28px;
    }

    .nv-tm-card {
        padding: 26px 22px 22px;
    }
}

/* ── Final call to action ─────────────────────────────────────────────────────
   A brand-yellow card with a 36px radius, a two-column layout (copy left,
   order-preview card right), a pill kicker, two buttons and three ticked
   assurances.

   Numbers measured from the reference DOM (v2-landing-sections/13-section.html):
   • Card:        36px radius, clamp(40px,5vw,64px) vertical / clamp(24px,5vw,64px) horizontal padding
   • Grid:        7fr / 5fr, gap clamp(28px,4vw,56px), items: center
   • Bottom gap:  clamp(56px,7vw,96px)
   • Orb:         320×320px at left:-90px / bottom:-140px, opacity:0.7
   • Headline:    clamp(30px,3.6vw,48px) / 1.1 / 700 / max 18ch
   • Paragraph:   15px / 1.8 / max 46ch / 16px margin-top
   • Buttons:     16px 30px (primary) / 16px 26px (secondary), 999px radius,
                  14px font, gap 12px, 28px from paragraph
   • Ticks row:   13px / 500 / gap 22px / 26px from buttons
   • Order card:  dark (#1b1b1b) / 28px radius / 26px×26px top / 24px bottom
                  box-shadow: 0 30px 60px rgba(0,0,0,.25) / max-width: 360px
   • Card prices: struck original 14px #7a7a7a; final 28px/700 in brand colour */

/* ── Outer section ────────────────────────────────────────────────────────── */
/* No padding: the reference gives this block 64px top and bottom, and the yellow
   card already supplies them with ITS own padding (64px). Adding both pushes the
   content down by 64px and stretches the block by another 64 — which is exactly
   what it measured over. */
.nv-cta {
    padding-top: 0;
    padding-bottom: 0;
    /* Air between the yellow card and the dark footer, measured from the reference. */
    margin-bottom: clamp(56px, 7vw, 96px);
}

/* ── Banner card ──────────────────────────────────────────────────────────── */
.nv-cta-box {
    position: relative;
    padding: clamp(40px, 5vw, 64px) clamp(24px, 5vw, 64px);
    border-radius: 36px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    /* Clips the decorative orb that bleeds outside the card boundary. */
    overflow: hidden;
}

/* Two-column layout only when the card column is present. The copy side
   takes 7 parts, the card 5 — exactly the reference proportions. */
.nv-cta-box--split {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: clamp(28px, 4vw, 56px);
    align-items: center;
}

/* The banner's entrance timing. It declares ONLY the transition — the hidden
   and revealed states belong to the shared `[data-reveal]` behaviour in
   00-base.css, and a block that re-declares them owns a state it cannot clear.
   This rule used to also set `opacity: 0; transform: scale(0.9)` behind
   `:not([data-reveal~="in"])`, a guard that can never be false: the observer
   marks a revealed element with the CLASS `lp-in`, it does not write a token
   into the attribute. Being more specific than the base's `.lp-in` rule, it won
   the cascade and left the whole banner invisible — 600 px of blank page above
   the footer, with the text present in the DOM the entire time. */
.lp-js .nv-cta-box[data-reveal="zoom"] {
    transition: opacity 0.8s cubic-bezier(0.2, 0.7, 0.2, 1),
                transform 0.8s cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* ── Decorative orb ───────────────────────────────────────────────────────── */
.nv-cta-orb {
    position: absolute;
    left: -90px;
    bottom: -140px;
    width: 320px;
    height: 320px;
    border-radius: 50%;
    /* #ffdd55 first for browsers without color-mix; then a lift derived from
       whatever brand colour the operator chose — stays warm across the palette. */
    background: #ffdd55;
    background: color-mix(in srgb, var(--nv-brand) 62%, #fff);
    opacity: 0.7;
    pointer-events: none;
}

/* ── Copy column ──────────────────────────────────────────────────────────── */
.nv-cta-copy {
    position: relative;
    z-index: 1;
}

/* ── Pill ─────────────────────────────────────────────────────────────────── */
/* The design's "First order −10%" kicker: dark pill with brand-coloured text.
   All-caps, tracked, 12px — identical to the reference's resolved styles. */
.nv-cta-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px;
    border-radius: 999px;
    background: var(--nv-on-brand);
    color: var(--nv-brand);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    /* Sits directly above the headline; the headline adds its own margin-top. */
    margin-bottom: 0;
}

/* ── Headline ─────────────────────────────────────────────────────────────── */
.nv-cta-title {
    max-width: 18ch;
    margin: 18px 0 0;
    font-size: clamp(30px, 3.6vw, 48px);
    line-height: 1.1;
    font-weight: 700;
    color: var(--nv-on-brand);
    text-wrap: balance;
}

/* When there is no pill above, the headline sits at the card edge. */
.nv-cta-pill + .nv-cta-title {
    margin-top: 18px;
}

.nv-cta-title:empty {
    display: none;
}

/* ── Body paragraph ───────────────────────────────────────────────────────── */
.nv-cta-text {
    max-width: 46ch;
    margin: 16px 0 0;
    font-size: 15px;
    line-height: 1.8;
    /* #3a3200 = the reference's exact dark-amber; mixed toward black (not ink)
       so custom brand colours darken consistently regardless of the ink token. */
    color: #3a3200;
    color: color-mix(in srgb, var(--nv-brand) 24%, #000);
}

.nv-cta-text:empty {
    display: none;
}

/* ── Button row ───────────────────────────────────────────────────────────── */
.nv-cta-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 28px;
}

/* Primary: dark pill, chevron coloured by the brand token. */
.nv-cta-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 16px 30px;
    border-radius: 999px;
    background: var(--nv-on-brand);
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    text-decoration: none;
}

.nv-cta-btn-ico {
    display: inline-flex;
    /* The arrow colour matches the banner background, so it reads as the brand
       accent on both light and dark cards. */
    color: var(--nv-brand);
}

/* Secondary: outlined, same radius and vertical padding as the primary.
   Horizontal padding is 26px (4px less) matching the reference. */
.nv-cta-btn-outline {
    padding: 16px 26px;
    border: 2px solid var(--nv-on-brand);
    background: transparent;
    color: var(--nv-on-brand);
    font-weight: 600;
}

/* The outline button inverts on hover — white on yellow background would give
   the shared base-hover rule (white text) unreadable contrast. */
.nv-cta-btn-outline:hover {
    background: var(--nv-on-brand);
    color: var(--nv-brand);
}

/* ── Three assurance ticks ────────────────────────────────────────────────── */
.nv-cta-ticks {
    display: flex;
    flex-wrap: wrap;
    gap: 22px;
    margin-top: 26px;
    font-size: 13px;
    font-weight: 500;
    /* Mixed toward black (not ink) so custom brand colours darken consistently
       regardless of the ink token — same rationale as .nv-cta-text. */
    color: #3a3200;
    color: color-mix(in srgb, var(--nv-brand) 24%, #000);
}

/* The row disappears when every tick is empty — :has() with multiple targets
   covers the common case of a panel that blanked all three fields. */
.nv-cta-ticks:has(.nv-cta-tick:not(.nv-cta-tick-empty) ~ .nv-cta-tick:not(.nv-cta-tick-empty)) {
    /* Kept visible when at least two ticks have words — handled inline. */
}

.nv-cta-tick {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

/* Tick 1 is patched in place by the Studio, so it stays in the DOM even when
   its field is cleared. The empty modifier hides it until it has words. */
.nv-cta-tick-empty {
    display: none;
}

.nv-cta-check {
    display: inline-flex;
    flex: 0 0 auto;
}

/* ── Order-preview card ───────────────────────────────────────────────────── */
/* Slides in from the right independently — the section zooms in as a whole,
   and the card then settles from translateX(50px). The base stylesheet's
   IntersectionObserver handles the `in` state; data-reveal="right" sets the
   direction. */
.nv-cta-card-wrap {
    position: relative;
    z-index: 1;
}

.nv-cta-card {
    background: #1b1b1b;
    color: #fff;
    border-radius: 28px;
    padding: 26px 26px 24px;
    /* 0 30px 60px — exact from the reference. A colour-mixed value is added so
       the shadow remains visible in dark mode (the base is already dark, so a
       near-black shadow disappears without depth). */
    box-shadow: 0 30px 60px rgba(0, 0, 0, 0.25);
    max-width: 360px;
    margin-left: auto;
}

/* ── Card header ──────────────────────────────────────────────────────────── */
.nv-cta-card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.nv-cta-card-eyebrow {
    margin: 0;
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    /* #bdbdbd from the reference — muted label against the dark card. */
    color: #bdbdbd;
}

/* Discount badge: brand-yellow background at 16% opacity + brand text. */
.nv-cta-card-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px;
    border-radius: 999px;
    /* rgba(247,198,0,.16) from the reference; token version for custom brands. */
    background: rgba(247, 198, 0, 0.16);
    background: color-mix(in srgb, var(--nv-brand) 20%, transparent);
    color: var(--nv-brand);
    font-size: 11px;
    font-weight: 700;
}

/* ── Service row ──────────────────────────────────────────────────────────── */
.nv-cta-card-service {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 18px;
}

/* The Instagram icon tile: 44×44px at 14px radius, platform colour, flex-fixed
   so it never shrinks when the service name is long. */
.nv-cta-card-icon {
    width: 44px;
    height: 44px;
    border-radius: 14px;
    display: grid;
    place-items: center;
    color: #fff;
    flex: 0 0 auto;
}

/* #e1306c — Instagram brand; kept as a literal so it does not inherit the
   operator's brand colour, which would make it read as a generic tile. */
.nv-cta-card-icon--ig {
    background: #e1306c;
}

.nv-cta-card-service-info {
    /* Allows the text to wrap without pushing the icon. */
}

.nv-cta-card-svc-name {
    margin: 0;
    font-weight: 700;
    font-size: 15px;
    line-height: 1.1;
}

.nv-cta-card-svc-meta {
    margin: 4px 0 0;
    font-size: 12px;
    color: #bdbdbd;
}

/* ── Price row ────────────────────────────────────────────────────────────── */
.nv-cta-card-price-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-top: 20px;
    padding-top: 16px;
    /* rgba(255,255,255,.1) from the reference — a faint divider on the dark card. */
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.nv-cta-card-total-label {
    font-size: 13px;
    color: #bdbdbd;
}

.nv-cta-card-prices {
    display: inline-flex;
    align-items: baseline;
    gap: 10px;
}

/* Original price struck through — 14px, dim. */
.nv-cta-card-price-was {
    font-size: 14px;
    color: var(--nv-ink-5);
    text-decoration: line-through;
}

/* Final discounted price — 28px/700, brand-coloured, tabular digits. */
.nv-cta-card-price-now {
    font-size: 28px;
    font-weight: 700;
    line-height: 1;
    color: var(--nv-brand);
    font-variant-numeric: tabular-nums;
}

/* ── Network tiles row ────────────────────────────────────────────────────── */
/* Four platform icon tiles (30×30px, 9px radius) and a trailing "+ N services"
   note, all aligned by the same row. The tiles use platform brand colours so
   a visitor reads them as the real platforms at a glance. */
.nv-cta-card-nets {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-top: 18px;
}

.nv-cta-card-net {
    width: 30px;
    height: 30px;
    border-radius: 9px;
    display: grid;
    place-items: center;
    color: #fff;
    flex: 0 0 auto;
}

.nv-cta-card-net--fb { background: #1877f2; }   /* Facebook blue */
.nv-cta-card-net--tw { background: #1da1f2; }   /* Twitter blue */
.nv-cta-card-net--yt { background: #ff0000; }   /* YouTube red */
/* TikTok: the reference uses a white tile with black stroke — the icon already
   carries brand recognition and white-on-white would be invisible. */
.nv-cta-card-net--tt { background: #fff; color: #010101; }

.nv-cta-card-more {
    margin-left: auto;
    font-size: 12px;
    color: #bdbdbd;
    /* Prevents the text from collapsing onto the tiles; align-self ensures it
       sits at the vertical centre of the row even if a tile rounds slightly
       taller. */
    align-self: center;
    white-space: nowrap;
}

/* ── Dark mode ────────────────────────────────────────────────────────────── */
/* The banner's background is the brand colour; in dark mode the card and the
   banner keep their own colours, but the ticks and text need enough contrast.
   The card is already dark (#1b1b1b) and stays identical. The banner still
   reads against a dark page because it is a solid coloured card, not a
   transparent layer. What changes is the shadow: a near-black shadow at 25%
   opacity is invisible on a dark page, so it is deepened to 40% and the
   spread is tightened to keep it within the card silhouette. */
:where(html.dark) .nv-cta-card {
    box-shadow: 0 30px 60px rgba(0, 0, 0, 0.4);
}

/* The card's own text is already fully opaque white — dark mode changes
   nothing there. Only the badge background token may need re-anchoring if the
   brand is very dark in dark mode: color-mix already handles that because it
   derives from --nv-brand, which the theme declares per-mode. */

/* ── Responsive ───────────────────────────────────────────────────────────── */
/* The two-column split collapses at 720px: the card is already hidden at 560px
   by data-hide-sm, but the grid should drop to a single column before that. */
@media (max-width: 720px) {
    .nv-cta-box--split {
        display: block;
    }
}

@media (max-width: 560px) {
    .nv-cta-box {
        border-radius: 28px;
    }

    /* Both buttons go full-width on narrow screens so the secondary label
       never wraps inside its pill. */
    .nv-cta-btn {
        width: 100%;
        justify-content: center;
    }

    /* The ticks wrap but stay readable with a tighter gap. */
    .nv-cta-ticks {
        gap: 14px;
    }
}

/* ── Footer ───────────────────────────────────────────────────────────────────
   The theme's own footer partial, on the landing and on every content page. The
   reference draws it in near-black with a wide brand column and three narrow
   link columns: 2fr 1fr 1fr 1fr, a 40px gutter and a 48→72px top rail.

   THE COLUMN COUNT IS THE OPERATOR'S, NOT THE DESIGN'S. Their Studio columns
   plus the legal pages they published can be three, four or none, and a grid of
   exactly four tracks puts the fifth column under the brand block. So the row is
   a flex line with the same 2:1:1:1 proportions, which holds the design at the
   width it was drawn for and simply wraps when the operator has more to say.

   The neutrals are written literally on purpose: they are the near-black the
   design is built on, not tints of the brand, and deriving them would repaint
   the footer every time an operator picks a colour. Only the accents — the
   social circles — come from the brand token. */

.nv-footer {
    background: #161616;
    color: #fff;
    font-family: var(--nv-font);
}

.nv-footer-cols {
    display: flex;
    flex-wrap: wrap;
    gap: 40px;
    padding: clamp(48px, 6vw, 72px) var(--nv-pad) 24px;
}

.nv-footer-brand {
    flex: 2 1 280px;
    min-width: 0;
}

.nv-footer-logo {
    display: inline-flex;
    align-items: center;
    color: #fff;
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -.01em;
    text-decoration: none;
}

.nv-footer-logo img {
    display: block;
    height: 34px;
    max-width: 190px;
    object-fit: contain;
}

.nv-footer-about {
    max-width: 32ch;
    margin: 14px 0 0;
    color: #a8a8a8;
    font-size: 13px;
    line-height: 1.8;
}

.nv-footer-social {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 22px;
}

.nv-footer-social a {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 15px;
    font-weight: 700;
    text-decoration: none;
    transition: transform .25s var(--nv-ease), box-shadow .25s;
}

.nv-footer-social a:hover {
    transform: translateY(-2px);
    box-shadow: var(--nv-shadow-brand);
    color: var(--nv-on-brand);
}

.nv-footer-col {
    flex: 1 1 150px;
    min-width: 0;
}

/* 18px under the heading, which is what the reference leaves: its column title
   ends at 95 and the first link starts at 113. The 6px this had squeezed every
   footer column up by 12 and read as a heading glued to its list. */
.nv-footer-h {
    margin: 0 0 18px;
    color: #fff;
    font-size: 15px;
    font-weight: 600;
}

.nv-footer-nav {
    display: flex;
    flex-direction: column;
    gap: 12px;
    font-size: 13px;
}

.nv-footer-nav a {
    color: #d0d0d0;
    text-decoration: none;
    transition: color .25s;
}

.nv-footer-nav a:hover {
    color: var(--nv-brand);
}

/* ── Contact column ────────────────────────────────────────────────────────────
   The design's third column: a blurb, an email and a phone number. These are
   theme-only fields (theme.footer.contact_*) with no slot in the product model.
   The column inherits nv-footer-col sizing; only the contact-specific nodes need
   their own rules. The gap between items follows the reference's 14px. */

/* Wider than a link column, because it holds PROSE and they hold single words.
   The reference gives it 212px; the product carries one column the mockup does
   not —  Legal, whose links are not optional — so an equal share left this one at
   173 and the sentence wrapped to three lines where the design reads two. Taking
   the extra width from columns that have room to spare is the closer answer to
   the design than dropping the links would be. */
.nv-footer-contact {
    gap: 14px;
    display: flex;
    flex-direction: column;
    flex: 1.4 1 200px;
}

/* AND THAT GAP IS WHY THIS COLUMN NEEDS ITS OWN HEADING MARGIN. The 18px above
   was measured as the DISTANCE the reference leaves under a column title, and in
   the link columns the margin IS that distance. Here the column is a flex with a
   14px gap, so the same margin resolves to 32 and pushed the email and the phone
   35px below where the design puts them — a measurement taken in one column and
   applied to a container that adds its own spacing. 4 + 14 = the 18 that was
   meant all along. */
.nv-footer-contact .nv-footer-h {
    margin-bottom: 4px;
}

.nv-footer-contact-blurb {
    margin: 0;
    color: #d0d0d0;
    font-size: 13px;
    line-height: 1.7;
}

.nv-footer-contact-email {
    color: var(--nv-brand);
    font-size: 13px;
    text-decoration: none;
    transition: opacity .25s;
}

.nv-footer-contact-email:hover {
    opacity: .8;
}

.nv-footer-contact-phone {
    color: #d0d0d0;
    font-size: 13px;
}

.nv-footer-bar {
    border-top: 1px solid #2a2a2a;
}

.nv-footer-bar p {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px 18px;
    margin: 0;
    padding: 18px var(--nv-pad);
    color: var(--nv-ink-6);
    font-size: 12px;
    text-align: center;
}

/* Two lines of small print on a phone, one centred line from there up: the
   product's "Powered by" belongs to the operator and is never dropped, it just
   stops competing for the same row. */
@media (max-width: 560px) {
    .nv-footer-bar p {
        flex-direction: column;
        gap: 4px;
    }
}

/* The link columns keep their proportions down to 900px, then pair up — the same
   two-then-one stepping the design's [data-cols-2] blocks use, expressed here
   because this row is a flex line rather than a grid. */
@media (max-width: 900px) {
    .nv-footer-cols {
        gap: 32px;
    }

    .nv-footer-brand {
        flex: 1 1 100%;
    }

    .nv-footer-col {
        flex: 1 1 calc(50% - 32px);
    }
}

@media (max-width: 560px) {
    .nv-footer-col {
        flex: 1 1 100%;
    }
}

/* ── Inherited blocks ─────────────────────────────────────────────────────────
   Nativa is STANDALONE: the product stops emitting its own landing stylesheet,
   so every block whose markup we keep arrives with `lp-*` class names and no
   rules at all. The designer drew no screen for these four — pricing, compare,
   "launch your own panel" and the newsletter — so there is nothing to port and
   nothing to replace: they are dressed in the language of the screens that WERE
   drawn (white card, 24px radius, 1px warm line, 0 10px 30px shadow, a brand
   tile lit 160deg from --nv-light, a pill button) so they read as part of the
   design rather than as the page the buyer switched away from.

   The video lightbox is here for a different reason: `sections.blade.php` emits
   it inline, so no theme view can ever replace it.

   What is NOT here: every block the design does cover (features, growth,
   services, payments, blog, inbox, how it works, FAQ, testimonials, CTA,
   footer) keeps the product's markup only until its own view lands, and those
   views paint with `nv-*`. Dressing their `lp-*` classes here would be a second
   answer to the same question. */

/* ── Section heading ──────────────────────────────────────────────────────────
   The product's centred heading block, and the twin of `.nv-head` in the base
   layer — same intent, different name, because this one comes from the core
   markup. Every inherited block that has a title uses it. */
.lp-head {
    text-align: center;
    max-width: 640px;
    margin: 0 auto 44px;
}

.lp-head .lp-lead {
    max-width: 60ch;
    margin-inline: auto;
}

/* The shared icon tile, at the size the product's markup asks for (a 21px glyph
   inside a span). Same gradient and the same readable ink as the tiles the
   design draws, so an inherited card and a drawn one carry the same badge. */
.lp-ico {
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    border-radius: 18px;
    background: linear-gradient(160deg, var(--nv-light), var(--nv-brand));
    color: var(--nv-on-brand);
    box-shadow: var(--nv-shadow-brand);
}

/* ── Pricing ──────────────────────────────────────────────────────────────────
   Live plans, not landing copy — the cards are read from Admin → Plans — so the
   count is the operator's and the row has to hold from one card to five. The
   tiers are white cards and the recommended one is ink, which is the pair the
   design already uses for its two buttons. */
.lp-plans {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
    gap: 24px;
    max-width: 1020px;
    margin: 0 auto;
    align-items: stretch;
}

.lp-plan {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 34px 30px;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: var(--nv-shadow);
    transition: transform .35s var(--nv-ease), box-shadow .35s;
}

.lp-plan:hover {
    transform: translateY(-6px);
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
}

.lp-plan-feat {
    border-color: var(--nv-ink);
    background: var(--nv-ink);
    color: var(--nv-white);
    box-shadow: 0 28px 60px rgba(0, 0, 0, .28);
}

.lp-plan-tag {
    position: absolute;
    top: -13px;
    left: 50%;
    translate: -50% 0;
    padding: 5px 14px;
    border-radius: 999px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    white-space: nowrap;
    box-shadow: var(--nv-shadow-brand);
}

.lp-plan-name {
    font-size: 15px;
    font-weight: 600;
    margin-bottom: 14px;
}

/* The tier pills the product writes inline. Only the colour is answered, and
   only on a light card: the brand hue is the INK of the first pill there, which
   on its own 14% tint is a yellow-on-yellow that cannot be read. `!important`
   is not a preference — an inline declaration cannot be outranked any other
   way — and the featured card is excluded because its pill is already a light
   tint on ink, where this would be dark on dark. */
.lp-plan:not(.lp-plan-feat) .lp-plan-name + div > span:first-child {
    color: var(--nv-deeper) !important;
}

.lp-plan-price {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-bottom: 24px;
}

.lp-plan-price b {
    font-size: 44px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.03em;
    font-variant-numeric: tabular-nums;
}

.lp-plan-per {
    font-size: 14px;
    color: var(--nv-muted);
}

.lp-plan-feat .lp-plan-per {
    color: var(--nv-muted-2);
}

.lp-plan ul {
    display: flex;
    flex-direction: column;
    gap: 11px;
    margin: 0 0 28px;
    font-size: 14px;
    line-height: 1.6;
}

.lp-plan li {
    display: flex;
    gap: 10px;
    align-items: flex-start;
}

/* The tick is brand-coloured in the product. On white the brand yellow is the
   one place this design cannot use it flat, so the check takes the deep tint —
   still the operator's colour, just the readable end of it. */
.lp-plan li svg {
    flex: none;
    margin-top: 2px;
    color: var(--nv-deep);
}

.lp-plan-feat li svg {
    color: var(--nv-brand);
}

/* The call to action sits on the floor of the card whatever the list above it
   is worth: a row of plans with different feature counts still lines its
   buttons up. */
.lp-plan .lp-btn {
    margin-top: auto;
    width: 100%;
}

/* On ink, the outline button's own border and text would be invisible. */
.lp-plan-feat .lp-btn-outline {
    background: transparent;
    border-color: var(--nv-white);
    color: var(--nv-white);
}

.lp-plan-feat .lp-btn-outline:hover {
    background: var(--nv-white);
    color: var(--nv-ink);
}

/* ── Compare (problem / solution) ─────────────────────────────────────────────
   Two panels the visitor reads side by side, so they are deliberately unequal:
   the problem is a plain white card and the solution is the warm one, which is
   the same way the design separates what it is selling from what it is not. */
.lp-cmp {
    padding: clamp(26px, 3vw, 34px);
    border-radius: 24px;
}

.lp-cmp-bad {
    border: 1px solid var(--nv-line);
    background: var(--nv-white);
    box-shadow: var(--nv-shadow);
}

.lp-cmp-good {
    border: 1px solid var(--nv-light);
    background: var(--nv-paper);
    box-shadow: var(--nv-shadow-sm);
}

.lp-cmp h3 {
    margin: 0 0 18px;
    font-size: 22px;
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -.01em;
    color: var(--nv-ink);
}

.lp-cmp ul {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.lp-cmp li {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    font-size: 14px;
    line-height: 1.7;
    color: var(--nv-ink-soft);
}

.lp-mark {
    flex: none;
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    margin-top: 3px;
    border-radius: 50%;
}

/* The only colour on this page that is not the operator's, and it stays: a
   problem mark is feedback, not branding — painting it in the brand would sell
   the thing the block is arguing against. */
.lp-mark-bad {
    background: color-mix(in srgb, #d64545 14%, transparent);
    color: #d64545;
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
}

.lp-mark-good {
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

/* ── Launch your own panel ────────────────────────────────────────────────────
   Owner-only reseller pitch. Same card as the design's feature tiles, with the
   tile and the copy aligned to the start because these are three claims to read
   rather than three icons to scan. */
.lp-panelcard {
    padding: 32px 28px;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
}

.lp-panelcard h3 {
    margin: 22px 0 12px;
    font-size: 18px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--nv-ink);
}

.lp-panelcard p {
    margin: 0;
    font-size: 14px;
    line-height: 1.75;
    color: var(--nv-muted);
}

.lp-panels-cta {
    margin-top: 44px;
    text-align: center;
}

/* ── Newsletter ───────────────────────────────────────────────────────────────
   A warm band rather than another white section: it closes the page just above
   the footer, and the design uses the paper tint exactly this way to mark the
   end of a run of white blocks. The field is the design's login pill — same
   radius, same warm ground, same 1px line — because a buyer meets both on the
   same page and two shapes of input on one page is how a port starts looking
   assembled. */
.lp-subscribe {
    padding: clamp(56px, 7vw, 90px) 0;
    background: var(--nv-paper);
}

/* Unless the block above it is already a warm one. The newsletter always sits
   last, so which section it follows is the operator's arrangement, not ours —
   and two paper bands in a row read as one very long section with a heading
   stranded in the middle of it. The previous sibling is the only thing that can
   answer this, and on this page it is exactly one selector away. */
.lp-section-surface + .lp-subscribe,
.lp-section-alt + .lp-subscribe {
    background: var(--nv-white);
}

.lp-sub-form {
    max-width: 520px;
    margin: 0 auto;
}

.lp-sub-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.lp-sub-input {
    flex: 1 1 220px;
    min-width: 0;
    height: 52px;
    padding: 0 22px;
    border: 1px solid var(--nv-line-2);
    border-radius: 999px;
    background: var(--nv-white);
    color: var(--nv-ink);
    font-size: 14px;
    outline: none;
    transition: border-color .25s, box-shadow .25s;
}

.lp-sub-input:focus {
    border-color: var(--nv-brand);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--nv-brand) 22%, transparent);
}

.lp-sub-btn {
    height: 52px;
    padding: 0 32px;
}

.lp-sub-note {
    margin-top: 16px;
    font-size: 13px;
    color: var(--nv-muted-2);
}

/* Validation and confirmation. Red and green are feedback, so they stay
   themselves; what they borrow from the design is the pill and the warm line. */
.lp-sub-error {
    margin: 0 0 14px;
    padding: 11px 18px;
    border-radius: 14px;
    background: color-mix(in srgb, #d64545 12%, transparent);
    color: #b83b3b;
    font-size: 14px;
    text-align: start;
}

.lp-sub-success {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 14px 22px;
    border-radius: 999px;
    background: color-mix(in srgb, #16a34a 12%, transparent);
    color: #15803d;
    font-size: 15px;
    font-weight: 500;
}

/* The reCAPTCHA widget mounts inside a centred form, so it centres too — it is
   a fixed-width iframe and the operator cannot move it. */
.lp-rc-widget {
    display: flex;
    justify-content: center;
    margin-top: 14px;
}

/* ── Watch-demo lightbox ──────────────────────────────────────────────────────
   Emitted inline by the product's section runner, which no theme view replaces,
   so these rules are the only dressing it can ever get. The hero's own button is
   the theme's (`nv-video-btn`); this is what opens when it is clicked. */
.lp-modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: color-mix(in srgb, var(--nv-ink) 88%, transparent);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

.lp-modal-box {
    position: relative;
    width: min(940px, 100%);
    aspect-ratio: 16 / 9;
    border-radius: 24px;
    background: #000;
    overflow: hidden;
    box-shadow: 0 40px 120px rgba(0, 0, 0, .55);
}

/* The player is injected INTO this slot, so `height:100%` on the iframe
   resolves against the slot and not against the box: without a definite height
   of its own the slot stays auto and the video falls back to 150px inside a
   correct 16/9 frame. */
.lp-modal-box > div {
    width: 100%;
    height: 100%;
}

.lp-modal-box iframe,
.lp-modal-box video {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}

.lp-modal-close {
    position: absolute;
    top: -46px;
    inset-inline-end: 0;
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border: 0;
    border-radius: 50%;
    background: var(--nv-white);
    color: var(--nv-ink);
    cursor: pointer;
    transition: transform .25s var(--nv-ease), background .25s;
}

.lp-modal-close:hover {
    transform: translateY(-2px);
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

/* A phone has no room above the frame for the close button, so it moves inside
   the video rather than off the top of the screen. */
@media (max-width: 560px) {
    .lp-modal-close {
        top: 10px;
        inset-inline-end: 10px;
    }
}

/* ── Responsive ───────────────────────────────────────────────────────────────
   The product writes these grids without the design's [data-cols] hooks, so the
   breakpoints are restated here on the classes it does emit. */
@media (max-width: 900px) {
    .lp-plans {
        grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    }
}

@media (max-width: 640px) {
    .lp-plan,
    .lp-panelcard {
        padding: 26px 22px;
    }

    .lp-plan-price b {
        font-size: 38px;
    }

    /* The button stops sharing the row with the field: at this width a 32px
       pill beside an input leaves neither of them usable. */
    .lp-sub-btn {
        width: 100%;
    }
}

/* ── Blog listing ─────────────────────────────────────────────────────────────
   The public /blog page: a full-bleed warm hero with the search pill beside it,
   the categories as chips, the newest article as a wide lead card and the rest
   as a three-column grid, closing on the newsletter slab.

   Numbers come from the design's resolved DOM (v2-blog-sections/01, 02 and 03):
   the hero on a #fdf6dc → #fef9e8 gradient with clamp(48px, 6vw, 80px) above and
   clamp(32px, 4vw, 48px) below, its 7fr/5fr columns 40px apart and bottom
   aligned; the headline clamp(34px, 4vw, 54px)/1.1 at -.03em with a 36%-tall
   sweep skewed -6deg behind its last word; the search pill 8px 8px 8px 20px on a
   0 12px 36px rgba(0, 0, 0, .08) shadow with a 10px 16px ink counter; the chips
   10px 18px with a 0 4px 14px rgba(0, 0, 0, .05) shadow and a .25s swap to ink;
   the lead card 32px radius over 0 20px 60px rgba(0, 0, 0, .09) with a 320px
   picture and clamp(26px, 3vw, 44px) of padding; the grid 3 × 24px with 24px
   radius cards, a 16/10 picture and 22px 22px 24px of body; the newsletter 32px
   radius on the ink, clamp(36px, 5vw, 56px) × clamp(24px, 5vw, 64px), a 340px
   orb bleeding out of its top corner and a 6px-padded white pill for the form.

   THIS PAGE IS NOT THE LANDING, so the base layer's page rules — the font, the
   resets, the reduced-motion clause — are scoped to `body.lp` and do not reach
   here. Everything this view needs is therefore declared on `.nv-posts` itself,
   and every rule below is scoped to it so the FAQ, the terms and the services
   catalogue, which share this stylesheet, are left exactly as they were. */

/* The content layout wraps every page in a 1200px rail with 40px of vertical
   padding. The design bleeds its hero to the edges, so the rail is released for
   this page ONLY — matched by what is inside it rather than by the page's
   address, which keeps the other content pages in the box they were built for.
   A browser without :has() simply keeps the rail: the page is narrower than it
   was drawn, never broken. */
body[data-rf-theme='nativa'] main:has(> .nv-posts) {
    max-width: none;
    padding: 0;
}

/* Same result for a browser without :has(): bleed out of the rail instead of
   removing it. Written as the exception so the two can never both apply. */
@supports not (selector(:has(*))) {
    .nv-posts {
        width: 100vw;
        margin: -2.5rem calc(50% - 50vw);
    }
}

.nv-posts {
    /* The layout paints the body with the product's own light/dark token and
       this design is a light one, so the surface is claimed here rather than
       letting the shell show between the blocks. It is the warm PAPER, not
       white: the design's base tint runs behind the cards from the hero all the
       way to the footer, and the cards, the search pill and the chips are what
       carry the white. */
    background: var(--nv-paper);

    /* A block formatting context, and not for layout: without it the
       newsletter's bottom margin COLLAPSES straight out through this element
       and through <main>, ends up on the body, and paints ~84px of the shell's
       own grey between the last block and the dark footer. The margin belongs
       inside the tinted area, which is where the design draws it. */
    display: flow-root;

    color: var(--nv-ink);
    font-family: var(--nv-font);
    font-size: 15px;

    /* No line-height here on purpose — see the base layer. The reference
       declares none on this page and every block that needs one (the lead at
       1.7, the card excerpts) declares its own; inheriting 1.6 from here was
       swelling the chips, the flags and the newsletter by about 7%. */
    text-align: start;
    -webkit-font-smoothing: antialiased;
}

.nv-posts *,
.nv-posts *::before,
.nv-posts *::after {
    box-sizing: border-box;
}

/* :where() so the reset weighs nothing — see the same note in 91-article.css.
   A bare `.nv-posts a` would outrank every button class on this page. */
:where(.nv-posts) a {
    color: inherit;
    text-decoration: none;
}

/* ── Hero ─────────────────────────────────────────────────────────────────── */
.nv-posts-hero {
    background: linear-gradient(var(--nv-paper) 0%, var(--nv-paper-2) 100%);
    padding: clamp(48px, 6vw, 80px) 0 clamp(32px, 4vw, 48px);
}

.nv-posts-hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: 40px;
    /* The rows are the headline and, under it, the paragraph beside the search
       pill. 20px is the gap the design draws between the headline and the
       paragraph, so the paragraph no longer carries it as a margin. */
    row-gap: 20px;
    /* The search pill sits on the baseline of the paragraph next to it, not in
       the middle of the whole column. */
    align-items: end;
}

/* The headline takes a row of its own across BOTH columns. The design keeps it
   inside the 7fr column, and at that width it stopped a third of the way from
   the right edge with nothing beside it — the search pill sits lower, next to
   the paragraph. Released, the title runs the full rail and the pill keeps its
   place. */
.nv-posts-head {
    grid-column: 1 / -1;
}

.nv-posts-title {
    margin: 18px 0 0;

    /* Sized to FILL the rail the row above released, which is this design's own
       rule for a hero headline rather than a liberty taken with it: on the home
       page the headline's four lines measure 570, 519, 546 and 570 inside a
       570px box — the type is chosen so the words reach the edge. Here the box
       was the 7fr column and the headline was one line that filled it exactly;
       widening the box without widening the type simply moved the empty space
       into view. 6.2vw keeps the same relationship at every width (the words
       run 83–86% of the rail from 640px up) and the 34px floor is where a phone
       lets it wrap to two lines instead. */
    font-size: clamp(34px, 6.2vw, 88px);
    line-height: 1.06;
    font-weight: 700;
    letter-spacing: -.03em;

    /* NOT `balance`, which would undo the line above: balancing evens the lines
       by SHORTENING them — it looks for the narrowest width the words still fit
       in — so a headline long enough to wrap would settle back at about half
       the rail and look exactly as boxed-in as before, while a one-line one
       stayed fine. `pretty` fills the line and only guards the last one against
       a single orphan word. (`balance` is still right where the column is
       deliberately narrow: the cards, the FAQ, the catalogue.) */
    text-wrap: pretty;
}

/* The sweep is drawn behind the closing word rather than around it, so the
   letters keep their own colour whatever the operator's brand turns out to be. */
.nv-posts-mark {
    position: relative;
    display: inline-block;
}

.nv-posts-mark-swipe {
    position: absolute;
    inset-inline: -6px;
    bottom: 8%;
    z-index: 0;
    height: 36%;
    border-radius: 6px;
    background: var(--nv-brand);
    transform: skewX(-6deg);
}

.nv-posts-mark-text {
    position: relative;
    z-index: 1;
}

.nv-posts-lead {
    /* The 20px the design draws above this paragraph is the grid's row-gap now
       that the headline is a row of its own. */
    margin: 0;

    /* A reading measure gains width by GROWING, not by stretching: at 16px this
       paragraph ran 52ch ≈ 520px and left ~160px of its own column empty, and
       simply widening it to the column would have printed ~95 characters a
       line. Larger type fills the same column at a measure that still reads.
       The cap stays in characters so a translation is governed by its own
       words, and it is wider than the column on purpose — the column is what
       decides, the cap only catches a very wide screen. */
    max-width: 64ch;
    font-size: clamp(16px, 1.35vw, 19px);
    line-height: 1.7;
    color: var(--nv-ink-soft);
}

/* A line the operator emptied takes no room. */
.nv-posts-lead:empty {
    display: none;
}

/* ── The search pill ──────────────────────────────────────────────────────── */
.nv-posts-search {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 8px 8px 20px;
    border: 1px solid var(--nv-line);
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .08);
    cursor: text;
}

.nv-posts-search-ico {
    display: inline-flex;
    color: var(--nv-muted);
}

.nv-posts-search-input {
    flex: 1;
    min-width: 0;
    padding: 8px 0;
    border: 0;
    background: transparent;
    font: inherit;
    font-size: 14px;
    color: var(--nv-ink);
}

.nv-posts-search-input:focus {
    outline: none;
}

/* The browser's own clear cross would sit on top of the counter. The field is
   emptied the same way it is filled — by typing — and Livewire follows. */
.nv-posts-search-input::-webkit-search-cancel-button {
    display: none;
}

.nv-posts-search-count {
    display: inline-flex;
    align-items: center;
    flex: none;
    padding: 10px 16px;
    border-radius: 999px;
    background: var(--nv-ink);
    color: var(--nv-brand);
    font-size: 12px;
    font-weight: 700;
    /* The figure changes as the visitor types; a fixed digit width stops the
       pill from twitching at every keystroke. */
    font-variant-numeric: tabular-nums;
}

/* ── Category chips ───────────────────────────────────────────────────────── */
.nv-posts-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    padding: 8px 0 36px;
}

.nv-posts-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    border: 0;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 4px 14px rgba(0, 0, 0, .05);
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    color: var(--nv-ink);
    cursor: pointer;
    transition: background .25s, color .25s;
}

.nv-posts-chip:hover {
    background: var(--nv-soft);
}

.nv-posts-chip[aria-pressed='true'] {
    background: var(--nv-ink);
    color: var(--nv-white);
}

/* The design paints a platform's own colour on each dot — Instagram pink,
   YouTube red. A category holds a name and nothing else, so every dot is the
   operator's colour instead of a guess at what they named it. */
.nv-posts-chip-dot {
    width: 8px;
    height: 8px;
    flex: none;
    border-radius: 50%;
    background: var(--nv-brand);
}

/* ── The lead article ─────────────────────────────────────────────────────── */
.nv-posts-feature {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    margin-bottom: 28px;
    border: 1px solid var(--nv-line);
    border-radius: 32px;
    background: var(--nv-white);
    box-shadow: 0 20px 60px rgba(0, 0, 0, .09);
    /* The picture is square-cornered and the card is not: the radius is what
       cuts it. */
    overflow: hidden;
}

.nv-posts-feature-media {
    position: relative;
    display: block;
    min-height: 320px;
    background: var(--nv-paper);
    overflow: hidden;
}

.nv-posts-feature-media img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* The lettered stand-in for a post with no cover, on the warm wash the picture
   would have filled. */
.nv-posts-mark-letter {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    font-size: 54px;
    font-weight: 700;
    color: var(--nv-deep);
}

.nv-posts-feature-flag {
    position: absolute;
    inset-inline-start: 20px;
    top: 20px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 999px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.nv-posts-feature-body {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: clamp(26px, 3vw, 44px);
}

.nv-posts-feature-cat {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--nv-deeper);
}

.nv-posts-feature-title {
    margin: 0;
    font-size: clamp(24px, 2.4vw, 32px);
    line-height: 1.2;
    font-weight: 700;
    text-wrap: balance;
}

.nv-posts-feature-ex {
    margin: 0;
    flex: 1;
    font-size: 15px;
    line-height: 1.75;
    /* Neutral greys, not tints: the body text reads the same whatever colour
       the operator picked, and the card behind it is always white. */
    color: var(--nv-ink-3);
}

.nv-posts-feature-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--nv-line);
}

.nv-posts-by {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

/* Where the design puts the writer's photo. The component hands this page a
   name and no picture, so the circle carries their initial on the same warm
   wash — recognisable per author, and never a broken image. */
.nv-posts-avatar {
    display: grid;
    place-items: center;
    flex: none;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--nv-soft);
    color: var(--nv-deeper);
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
}

.nv-posts-avatar-lg {
    width: 36px;
    height: 36px;
    border: 2px solid var(--nv-soft);
    background: var(--nv-paper);
    font-size: 14px;
}

.nv-posts-by-name {
    display: block;
    font-size: 13px;
    font-weight: 600;
}

.nv-posts-by-date {
    display: block;
    font-size: 12px;

    /* One step up the grey ramp, as on the catalogue and the FAQ page: the
       design's --nv-muted (#7a7a7a) measures 4.29:1 on this card, and 12px
       needs 4.5. --nv-ink-4 is a shade the design already uses, so nothing was
       invented to pass a number. The separator inside this line inherits it. */
    color: var(--nv-ink-4);
}

.nv-posts-read {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 22px;
    border-radius: 999px;
    background: var(--nv-ink);
    color: var(--nv-white);
    font-size: 13px;
    font-weight: 600;
}

.nv-posts-read-ico {
    display: inline-flex;
    color: var(--nv-brand);
}

/* ── The grid ─────────────────────────────────────────────────────────────── */
.nv-posts-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 24px;
    padding-bottom: clamp(56px, 7vw, 96px);
}

/* The pager carries the closing space when there is one, so the two never
   stack into a double gap. */
.nv-posts-grid:has(+ .nv-posts-pager) {
    padding-bottom: 28px;
}

.nv-posts-card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .07);
    overflow: hidden;
}

.nv-posts-card-media {
    position: relative;
    display: block;
    aspect-ratio: 16 / 10;
    background: var(--nv-paper);
    overflow: hidden;
}

.nv-posts-card-media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.nv-posts-card-media .nv-posts-mark-letter {
    font-size: 40px;
}

.nv-posts-card-cat {
    position: absolute;
    inset-inline-start: 14px;
    top: 14px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .12);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--nv-ink);
}

.nv-posts-card-cat .nv-posts-chip-dot {
    width: 7px;
    height: 7px;
}

.nv-posts-card-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: 12px;
    padding: 22px 22px 24px;
}

.nv-posts-card-date {
    font-size: 12px;
    /* Same 12px, same card, same step — see .nv-posts-by-date above. */
    color: var(--nv-ink-4);
}

.nv-posts-card-title {
    margin: 0;
    font-size: 17px;
    line-height: 1.35;
    font-weight: 700;
    text-wrap: pretty;
}

.nv-posts-card-ex {
    margin: 0;
    flex: 1;
    font-size: 13.5px;
    line-height: 1.7;
    color: var(--nv-ink-4);
}

.nv-posts-card-foot {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 6px;
    padding-top: 14px;
    border-top: 1px solid var(--nv-line);
}

.nv-posts-card-by {
    font-size: 12.5px;
    font-weight: 600;
}

.nv-posts-card-go {
    margin-inline-start: auto;
    display: inline-flex;
    color: var(--nv-deep);
}

/* ── Hover ────────────────────────────────────────────────────────────────── */
/* The design carries its hover behaviour as [data-card] and [data-btn] on the
   nodes themselves. The base layer declares the layout hooks but not these two,
   so they are written here, scoped, with the designer's own numbers — the same
   choice 62-payments.css made for its cards. */
.nv-posts [data-card] {
    transition: transform .35s var(--nv-ease), box-shadow .35s;
}

.nv-posts [data-card]:hover {
    transform: translateY(-6px);
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
}

/* The picture grows inside a frame that does not, which is why every media box
   above clips. */
.nv-posts [data-card] img {
    transition: transform .6s var(--nv-ease);
}

.nv-posts [data-card]:hover img {
    transform: scale(1.05);
}

.nv-posts [data-btn] {
    transition: transform .25s var(--nv-ease), box-shadow .25s, background .25s;
}

.nv-posts [data-btn]:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 24px color-mix(in srgb, var(--nv-brand) 35%, transparent);
}

/* ── Entrance ─────────────────────────────────────────────────────────────── */
/* The product's [data-reveal] observer is a landing-page script and does not run
   here, so the cards rise on their own as the markup arrives. It replays after a
   search or a filter, which is exactly when a new set of cards appears. */
@keyframes nv-posts-up {
    from { opacity: 0; transform: translateY(16px); }
    to { opacity: 1; transform: none; }
}

.nv-posts-feature,
.nv-posts-card {
    animation: nv-posts-up .5s var(--nv-ease) both;
}

/* The design staggers the grid by 60ms a card. Capped past the sixth: a page of
   fifteen posts would otherwise finish arriving most of a second late. */
.nv-posts-card:nth-child(2) { animation-delay: .06s; }
.nv-posts-card:nth-child(3) { animation-delay: .12s; }
.nv-posts-card:nth-child(4) { animation-delay: .18s; }
.nv-posts-card:nth-child(5) { animation-delay: .24s; }
.nv-posts-card:nth-child(n + 6) { animation-delay: .3s; }

/* ── Empty state ──────────────────────────────────────────────────────────── */
.nv-posts-empty {
    display: grid;
    justify-items: center;
    gap: 10px;
    margin-bottom: clamp(56px, 7vw, 96px);
    padding: 64px 24px;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .07);
    text-align: center;
}

.nv-posts-empty-ico {
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    margin-bottom: 6px;
    border-radius: 50%;
    background: var(--nv-soft);
    color: var(--nv-deeper);
}

.nv-posts-empty-title {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
}

.nv-posts-empty-text {
    margin: 0;
    font-size: 14px;
    color: var(--nv-muted);
}

/* ── Pager ────────────────────────────────────────────────────────────────── */
/* The control is the product's own markup, dressed by the compiled bundle. Only
   its place on the page is decided here. */
.nv-posts-pager {
    padding-bottom: clamp(56px, 7vw, 96px);
}

/* ── Newsletter ───────────────────────────────────────────────────────────── */
.nv-posts-news {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
    align-items: center;
    gap: 32px;
    margin: 0 0 clamp(56px, 7vw, 96px);
    padding: clamp(36px, 5vw, 56px) clamp(24px, 5vw, 64px);
    border-radius: 32px;
    background: var(--nv-ink);
    color: var(--nv-white);
    /* The orb is drawn outside the slab and clipped by it — that is the whole
       effect, so the radius has to cut it. It works because the slab is
       POSITIONED: `overflow` only clips an absolutely positioned descendant
       whose containing block is the clipping element itself, so dropping the
       `position: relative` above would let the orb escape into the page. */
    overflow: hidden;
}

.nv-posts-news-orb {
    position: absolute;
    inset-inline-end: -100px;
    top: -140px;
    width: 340px;
    height: 340px;
    border-radius: 50%;
    background: var(--nv-brand);
    opacity: .95;
}

/* Everything with words sits above the orb. */
.nv-posts-news-copy,
.nv-posts-news-form,
.nv-posts-news-away {
    position: relative;
    z-index: 1;
}

.nv-posts-news-eyebrow {
    margin: 0;
    color: var(--nv-brand);
    font-size: 14px;
    font-weight: 600;
}

.nv-posts-news-title {
    margin: 10px 0 0;
    font-size: clamp(24px, 2.8vw, 36px);
    line-height: 1.15;
    font-weight: 700;
}

.nv-posts-news-text {
    margin: 14px 0 0;
    max-width: 46ch;
    font-size: 14px;
    line-height: 1.8;
    /* Neutral on the ink slab, which is the one surface that never changes
       colour with the operator's brand. */
    color: #bdbdbd;
}

.nv-posts-news-form {
    display: flex;
    gap: 8px;
    padding: 6px;
    border-radius: 999px;
    background: var(--nv-white);
}

.nv-posts-news-input {
    flex: 1;
    min-width: 0;
    padding: 12px 16px;
    border: 0;
    background: transparent;
    font: inherit;
    font-size: 14px;
    color: var(--nv-ink);
}

.nv-posts-news-input:focus {
    outline: none;
}

.nv-posts-news-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 12px 22px;
    border: 0;
    border-radius: 999px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
}

.nv-posts-news-away {
    margin: 0;
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
/* The hero, the lead card and the newsletter collapse through the shared
   [data-cols] hook the markup carries; the grid has its own two steps, at the
   designer's own widths. */
@media (max-width: 1100px) {
    .nv-posts-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 900px) {
    /* One column here ([data-cols]), so the three pieces stack: headline,
       paragraph, pill. The column gap has nothing left to separate and the row
       gap is what shows, which is why the two are set apart rather than with
       the `gap` shorthand this rule used to carry. */
    .nv-posts-hero-grid {
        column-gap: 28px;
        row-gap: 24px;
    }

    .nv-posts-feature-media {
        min-height: 240px;
    }
}

@media (max-width: 640px) {
    .nv-posts-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .nv-posts-news-form {
        /* Side by side, the field and the button each get half a phone and
           neither is usable. */
        flex-wrap: wrap;
        border-radius: 22px;
    }

    .nv-posts-news-btn {
        flex: 1;
    }

    /* The orb is a corner accent on a two-column slab. On one column it lands
       over the headline and the paragraph, and stacking the words on top does
       not save them: white type on a brand-yellow disc cannot be read at any
       z-index. The decoration is what goes — it carries no meaning, and the
       design never drew this block at phone width. */
    .nv-posts-news-orb {
        display: none;
    }
}

/* The base layer's reduced-motion clause is scoped to the landing's body and
   does not reach this page, so the promise is repeated for what moves here. */
@media (prefers-reduced-motion: reduce) {
    .nv-posts *,
    .nv-posts *::before,
    .nv-posts *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

/* ── Article ──────────────────────────────────────────────────────────────────
   The single post page (livewire/client/pages/blog-show.blade.php).

   Numbers come from the design's resolved DOM (v2-post-sections/01 and /02):
   the hero on a paper → lighter-paper gradient with clamp(36px, 5vw, 64px) of
   top padding; the breadcrumb at 13px with 8px gaps; the header capped at 820px
   and 26px under the crumbs; the pill 6px/12px at 11px with .06em of tracking;
   the title clamp(30px, 4vw, 50px)/1.12 at -.03em; the lead 16px/1.7 over 60ch;
   the byline 46px round on a 3px soft ring; the cover clamp(240px, 40vw, 480px)
   with a 32px 32px 0 0 radius and 0 30px 70px rgba(0, 0, 0, .12) under it; the
   grid 7fr/4fr with a clamp(32px, 5vw, 72px) gutter; the prose 16px/1.85 capped
   at 720px with its h2 at clamp(20px, 2vw, 26px) and 38px/14px around it; the
   quote 24px/28px on a 24px radius with a 150px brand orb bleeding out of its
   top-right; the share pills 10px/16px at 13px; the cards 24px radius, 1px warm
   border and 0 12px 36px rgba(0, 0, 0, .06); the sidebar stuck at 100px with
   20px between its cards; the related band on paper with clamp(56px, 7vw, 96px)
   of padding and 24px between three cards of 16/10 covers.

   THIS PAGE IS NOT THE LANDING, so none of the base file's `body.lp` resets
   reach it: it renders inside the product's public layout, over the compiled
   Tailwind bundle. Everything below therefore says what it wants outright
   instead of inheriting it — and it wins the cascade by position rather than by
   weight, because the bundle's rules sit inside a cascade layer and this
   stylesheet is linked after it.

   What is NOT here is explained in the Blade: the design's reading time, author
   photograph, author biography and category cloud have no field in the model. */

/* The layout wraps a content page in a 1200px rail with 40px of vertical
   padding, which is right for the services table and wrong for a page whose
   hero and closing band run edge to edge. Neutralised only when THIS page is
   the one inside it — the FAQ and the legal pages still want their rail. */
body[data-rf-theme='nativa'] main:has(> .nv-article-page) {
    max-width: none;
    padding: 0;
}

/* Same result for a browser without :has(): bleed out of the rail instead of
   removing it. Written as the exception so the two can never both apply. */
@supports not (selector(:has(*))) {
    .nv-article-page {
        width: 100vw;
        margin: -2.5rem calc(50% - 50vw);
    }
}

.nv-article-page {
    background: var(--nv-paper-2);
    color: var(--nv-ink);
    font-family: var(--nv-font);
    font-size: 15px;

    /* No line-height here on purpose — see the base layer. The reference leaves
       the root at Poppins' own `normal` and lets each piece declare what it
       needs: the prose reads at 1.7, the headings at 1.3, the rail's own lines
       at their own measure. Inheriting 1.6 from the page swelled everything
       that had not asked for a measure. */
    text-align: start;
    -webkit-font-smoothing: antialiased;
}

.nv-article-page *,
.nv-article-page *::before,
.nv-article-page *::after {
    box-sizing: border-box;
}

/* Wrapped in :where() so the reset weighs NOTHING. A bare `.nv-article-page a`
   is (0,1,1) and outranks every single-class button in this file, which is how
   the sidebar CTA came out printing ink on ink: the label was in the markup,
   the colour was not. Every element reset in this theme goes the same way — the
   base stylesheet already does it for the landing. */
:where(.nv-article-page) a {
    color: inherit;
    text-decoration: none;
    transition: color .25s;
}

:where(.nv-article-page) a:hover {
    color: var(--nv-deep);
}

/* The design's own entrance. It is CSS rather than the product's [data-reveal]
   because that hook is driven by the landing's observer, which never runs on a
   content page — a block that relied on it would simply never appear. */
.nv-article-page [data-fade] {
    animation: nv-art-fade .5s var(--nv-ease) both;
}

.nv-article-page [data-fade] + [data-fade] {
    animation-delay: .1s;
}

@keyframes nv-art-fade {
    from { opacity: 0; transform: translateY(16px); }
    to { opacity: 1; transform: none; }
}

/* ── Hero ─────────────────────────────────────────────────────────────────── */
.nv-art-hero {
    padding: clamp(36px, 5vw, 64px) 0 0;
    background: linear-gradient(var(--nv-paper) 0%, var(--nv-paper-2) 100%);
}

.nv-crumbs {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 13px;
    color: var(--nv-muted);
}

:where(.nv-crumbs) a {
    color: var(--nv-muted);
}

.nv-crumb-sep {
    display: inline-flex;
    /* Lighter than the words it separates, and derived so it stays a tint of
       the same grey whatever the operator's colour does around it. */
    color: color-mix(in srgb, var(--nv-muted) 45%, #fff);
}

.nv-crumb-now {
    color: var(--nv-deeper);
    font-weight: 600;
}

/* The reference caps this block at 820px, and on a 1180px container that left a
   third of the row empty with nothing in it — the heading read as a small block
   floating in a wide page while the cover under it went edge to edge. The other
   heroes of this theme are just as narrow in their COPY column and do not look
   like that, because the room they leave is filled (the listing puts its search
   pill there, the FAQ and the catalogue their figure card). The article has
   nothing to put there, so the honest answer is the other one: give the row back
   to the words. The measure is still governed, one element down. */
.nv-art-head {
    margin-top: 26px;
}

.nv-art-tag {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .06);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--nv-ink);
}

.nv-art-tag-dot {
    width: 8px;
    height: 8px;
    flex: 0 0 auto;
    border-radius: 50%;
    /* The design paints one dot per network; a category is a word the operator
       typed, so it carries their colour instead of a platform's. */
    background: var(--nv-brand);
}

/* 56px at the top end, not the reference's 50: the number was drawn for a
   820px column and this one is 1180 wide, so the same type reads a size
   smaller in it. It is not an invented figure either — the listing tops out at
   54 and the FAQ at 58, and an article is the page those two lead to. */
.nv-art-title {
    margin: 18px 0 0;
    font-size: clamp(30px, 4.2vw, 56px);
    line-height: 1.12;
    font-weight: 700;
    letter-spacing: -.03em;
    /* `pretty`, NOT the `balance` the reference uses. Balance evens the lines by
       SHORTENING them, so on a full-width row a two-line title settles at about
       half the container and the block looks exactly as boxed-in as it did when
       a max-width was doing it — the fix would have undone itself on every title
       long enough to wrap. Pretty fills the line and only guards the last one
       against an orphan, which is the behaviour a headline across a whole row
       wants. Balance is still right where a column is narrow by design. */
    text-wrap: pretty;
    color: var(--nv-ink);
}

/* The sweep under the closing words, drawn BEHIND them so the letters keep the
   heading's own ink whatever colour the operator's brand turns out to be. The
   same band the listing, the FAQ and the catalogue wear — this heading was the
   only title on the site printing flat.

   `nowrap` is load-bearing: the band is absolutely positioned inside this box,
   so a tail broken over two lines would paint one rectangle across both of
   them. Headline::split() caps the tail at what fits a phone on a single line
   and hands back nothing when it does not — a title without a sweep looks
   ordinary, a wrapped sweep looks broken. */
.nv-art-mark {
    position: relative;
    display: inline-block;
    white-space: nowrap;
}

.nv-art-mark-swipe {
    position: absolute;
    inset-inline: -6px;
    bottom: 8%;
    z-index: 0;
    height: 36%;
    border-radius: 6px;
    background: var(--nv-brand);
    transform: skewX(-6deg);
}

.nv-art-mark-text {
    position: relative;
    z-index: 1;
}

/* The excerpt is the one thing in this block that a measure still governs, and
   the way it gains width is by growing, not by stretching: 20px over 68
   characters is ~780px of row, where the old 16px over 60 was ~480. A line does
   not become more readable by being longer — at 16px this container is 140
   characters across, and that is the line length the body of the article is
   capped at 720px to avoid. So the deck reads as a deck, the row is filled by
   bigger type instead of a longer line, and an operator who writes a
   three-sentence excerpt still gets something anyone can read.
   `:empty` because an article without an excerpt must not leave a gap. */
.nv-art-lead {
    max-width: 68ch;
    margin: 18px 0 0;
    /* Scaled with the title it sits under: 20px beside a 56px heading is a
       deck, and beside the 30px heading a phone gets it would be a shout. */
    font-size: clamp(17px, 1.4vw, 20px);
    line-height: 1.65;
    color: var(--nv-ink-soft);
}

.nv-art-lead:empty {
    display: none;
}

.nv-art-by {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 26px;
}

.nv-art-by-name {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
}

.nv-art-by-meta {
    margin: 2px 0 0;
    font-size: 12.5px;
    color: var(--nv-muted);
}

/* The initial, in the place and at the size of the design's photograph. */
.nv-art-face {
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    flex: 0 0 auto;
    border: 3px solid var(--nv-soft);
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 17px;
    font-weight: 700;
    line-height: 1;
}

.nv-art-face-lg {
    width: 64px;
    height: 64px;
    font-size: 24px;
}

.nv-art-cover {
    position: relative;
    height: clamp(240px, 40vw, 480px);
    margin-top: 36px;
    border-radius: 32px 32px 0 0;
    overflow: hidden;
    box-shadow: 0 30px 70px rgba(0, 0, 0, .12);
}

.nv-art-cover img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ── The two columns ──────────────────────────────────────────────────────── */
.nv-art-grid {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    gap: clamp(32px, 5vw, 72px);
    align-items: start;
    /* Same border-box correction as .lp-wrap: the rail is added back so the
       content area reaches the intended 1180 px. */
    max-width: calc(var(--nv-wrap) + var(--nv-pad) * 2);
    margin: 0 auto;
    padding: clamp(36px, 5vw, 64px) var(--nv-pad) 0;
}

.nv-art-body {
    max-width: 720px;
    min-width: 0;
}

/* ── The prose ────────────────────────────────────────────────────────────────
   Written by the buyer in the editor and printed by the product's own component,
   so these rules dress tags rather than classes. Scoped under .nv-art-body so
   they out-weigh the bundle's .rf-richtext without an important flag. */
.nv-art-body .nv-art-prose {
    font-size: 16px;
    /* 1.7, measured on the reference (27.2px over 16px) — not 1.85, which was a
       guess at "comfortable" and made the post a screenful taller than the
       drawing for the same words. */
    line-height: 1.7;
    color: color-mix(in srgb, var(--nv-ink-soft) 80%, var(--nv-ink));
}

.nv-art-body .nv-art-prose p {
    margin: 0 0 20px;
    text-wrap: pretty;
}

.nv-art-body .nv-art-prose h2,
.nv-art-body .nv-art-prose h3,
.nv-art-body .nv-art-prose h4 {
    color: var(--nv-ink);
    font-weight: 700;
    line-height: 1.3;
    /* NO scroll-margin-top here, and that is not an oversight. The fixed bar is
       cleared for EVERY anchor by scroll-padding-top on `html` (00-base). The two
       ADD UP — the target's margin box is aligned against the scrollport's padding
       edge — so declaring 100 in both places landed a heading at 200, with 124px of
       empty page under the bar that looks like a layout bug and is really two
       offsets doing the same job. One origin, and it is the scrollport. */
}

.nv-art-body .nv-art-prose h2 {
    margin: 38px 0 14px;
    font-size: clamp(20px, 2vw, 26px);
}

.nv-art-body .nv-art-prose h3 {
    margin: 32px 0 12px;
    font-size: clamp(18px, 1.7vw, 21px);
}

.nv-art-body .nv-art-prose h4 {
    margin: 26px 0 10px;
    font-size: 17px;
}

.nv-art-body .nv-art-prose > *:first-child {
    margin-top: 0;
}

.nv-art-body .nv-art-prose ul,
.nv-art-body .nv-art-prose ol {
    margin: 0 0 20px;
    padding-inline-start: 1.4em;
}

.nv-art-body .nv-art-prose ul {
    list-style: disc;
}

.nv-art-body .nv-art-prose ol {
    list-style: decimal;
}

.nv-art-body .nv-art-prose li {
    margin: .4em 0;
}

.nv-art-body .nv-art-prose li::marker {
    color: var(--nv-deep);
}

.nv-art-body .nv-art-prose a {
    color: var(--nv-deeper);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.nv-art-body .nv-art-prose strong,
.nv-art-body .nv-art-prose b {
    color: var(--nv-ink);
    font-weight: 700;
}

/* The design's pull quote: ink card, brand orb, no border. */
.nv-art-body .nv-art-prose blockquote {
    position: relative;
    margin: 30px 0;
    padding: 24px 28px;
    border: 0;
    border-radius: 24px;
    overflow: hidden;
    background: var(--nv-ink);
    color: var(--nv-white);
    font-size: 18px;
    font-weight: 600;
    line-height: 1.55;
}

.nv-art-body .nv-art-prose blockquote::before {
    content: '';
    position: absolute;
    top: -50px;
    right: -30px;
    width: 150px;
    height: 150px;
    border-radius: 50%;
    background: var(--nv-brand);
    opacity: .9;
}

.nv-art-body .nv-art-prose blockquote > * {
    position: relative;
    max-width: 80%;
    text-wrap: balance;
}

.nv-art-body .nv-art-prose code {
    padding: .1em .35em;
    border-radius: 6px;
    background: var(--nv-soft);
    color: var(--nv-deeper);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .9em;
}

.nv-art-body .nv-art-prose pre {
    margin: 0 0 20px;
    padding: 18px 20px;
    border-radius: 18px;
    background: var(--nv-ink);
    color: var(--nv-white);
    overflow-x: auto;
}

.nv-art-body .nv-art-prose pre code {
    padding: 0;
    background: none;
    color: inherit;
}

.nv-art-body .nv-art-prose hr {
    margin: 30px 0;
    border: 0;
    border-top: 1px solid var(--nv-line);
}

/* ── Share ────────────────────────────────────────────────────────────────── */
.nv-share {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 40px;
    padding-top: 26px;
    border-top: 1px solid var(--nv-line);
}

.nv-share-label {
    margin-inline-end: 6px;
    font-size: 13px;
    font-weight: 600;
    color: var(--nv-muted);
}

.nv-share-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border: 0;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: var(--nv-shadow-sm);
    color: var(--nv-ink);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    /* No line-height: the reference leaves it at `normal`, which is what makes
       this pill 40px tall. Pinning it to 1 squeezed it to 33 — the padding was
       right and the text box inside it was not. The icon and the label are
       centred by align-items, not by the measure. */
    cursor: pointer;
    transition: background .25s, color .25s;
}

.nv-share-btn:hover {
    background: var(--nv-ink);
    color: var(--nv-brand);
}

/* ── Author card ──────────────────────────────────────────────────────────── */
.nv-art-author {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-top: 30px;
    padding: 24px;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .06);
}

.nv-art-author-kicker {
    margin: 0;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--nv-deeper);
}

.nv-art-author-name {
    margin: 4px 0 0;
    font-size: 16px;
    font-weight: 700;
}

/* ── Sidebar ──────────────────────────────────────────────────────────────────
   Sticky, with a ceiling of its own: an element taller than the viewport pins
   its own overflow out of reach, and this column can hold a long index. The
   4px of padding keeps the cards' shadows inside the scrolling box. */
.nv-art-aside {
    position: sticky;
    top: 100px;
    display: flex;
    flex-direction: column;
    gap: 20px;
    max-height: calc(100vh - 124px);
    margin: -4px;
    padding: 4px;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* THE CARDS MUST NOT SHRINK. A flex column with a ceiling squeezes its items
   before it agrees to scroll, and each of these cards clips its own overflow —
   so the column silently made the last one shorter than its contents and cut the
   call-to-action's BUTTON clean off. It looked like a design choice, not a
   defect, which is exactly why it has to be stated: the column scrolls, the
   cards keep their height. Reached the moment a third card joined the rail. */
.nv-art-aside > * {
    flex: 0 0 auto;
}

.nv-toc {
    padding: 22px 24px;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .06);
}

/* The card ships hidden and the script unhides it once it has entries. Stated
   here because the bundle's reset does not carry the attribute's default. */
.nv-toc[hidden] {
    display: none;
}

.nv-toc-kicker {
    margin: 0 0 14px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--nv-deeper);
}

.nv-toc-list {
    display: grid;
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.nv-toc-link {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    font-size: 13.5px;
    line-height: 1.5;
    color: color-mix(in srgb, var(--nv-muted) 75%, var(--nv-ink));
    transition: color .2s;
}

.nv-toc-link:hover {
    color: var(--nv-ink);
}

.nv-toc-num {
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--nv-soft);
    color: var(--nv-deeper);
    font-size: 11px;
    font-weight: 700;
    transition: background .2s, color .2s;
}

/* Where the reader is. The design draws only a hover state, so this is the
   same treatment held: the section being read is simply already hovered. */
.nv-toc-link.is-current {
    color: var(--nv-ink);
    font-weight: 600;
}

.nv-toc-link.is-current .nv-toc-num {
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

.nv-art-cta {
    position: relative;
    padding: 26px;
    border-radius: 28px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    overflow: hidden;
}

.nv-art-cta-orb {
    position: absolute;
    right: -60px;
    bottom: -80px;
    width: 200px;
    height: 200px;
    border-radius: 50%;
    background: var(--nv-light);
    opacity: .7;
}

.nv-art-cta-in {
    position: relative;
}

.nv-art-cta-badge {
    display: inline-flex;
    padding: 5px 12px;
    border-radius: 999px;
    background: var(--nv-ink);
    color: var(--nv-brand);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.nv-art-cta-title {
    margin: 14px 0 0;
    font-size: 22px;
    line-height: 1.2;
    font-weight: 700;
}

.nv-art-cta-body {
    margin: 10px 0 0;
    font-size: 13.5px;
    line-height: 1.7;
    /* Ink at 80% over the brand, which is the design's warm dark on yellow and
       stays readable on whatever colour the operator picked. */
    color: color-mix(in srgb, var(--nv-on-brand) 80%, transparent);
}

.nv-art-cta-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 18px;
    padding: 13px 22px;
    border-radius: 999px;
    background: var(--nv-ink);
    color: var(--nv-white);
    font-size: 14px;
    font-weight: 700;
    transition: transform .25s var(--nv-ease), box-shadow .25s;
}

.nv-art-cta-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 24px rgba(0, 0, 0, .18);
    color: var(--nv-white);
}

.nv-art-cta-chev {
    display: inline-flex;
    color: var(--nv-brand);
}

/* ── Categories card ─────────────────────────────────────────────────────────
   Third sidebar card: every blog category as a chip-link. The dot colour uses
   --nv-brand because a category is operator-named text, not a network icon, so
   it carries their brand colour instead of a per-platform hue. */
.nv-cat-card {
    padding: 22px 24px;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .06);
}

.nv-cat-kicker {
    margin: 0 0 14px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--nv-deeper);
}

.nv-cat-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.nv-cat-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 12px;
    border-radius: 999px;
    /* Warm paper tint — the same chip background as the design reference. */
    background: var(--nv-paper);
    font-size: 12.5px;
    font-weight: 600;
    color: var(--nv-ink);
    transition: background .2s, color .2s;
}

.nv-cat-chip:hover {
    background: var(--nv-soft);
    color: var(--nv-ink);
}

.nv-cat-dot {
    width: 7px;
    height: 7px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--nv-brand);
}

/* ── Further reading ──────────────────────────────────────────────────────── */
.nv-rel {
    margin-top: clamp(56px, 7vw, 96px);
    padding: clamp(56px, 7vw, 96px) 0;
    background: var(--nv-paper);
}

.nv-rel-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 24px;
}

.nv-rel-kicker {
    margin: 0;
    color: var(--nv-deep);
    font-size: 15px;
    font-weight: 600;
}

.nv-rel-title {
    margin: 10px 0 0;
    font-size: clamp(28px, 3.2vw, 40px);
    line-height: 1.2;
    font-weight: 700;
    color: var(--nv-ink);
}

.nv-rel-all {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 22px;
    border: 1.5px solid var(--nv-ink);
    border-radius: 999px;
    background: var(--nv-white);
    font-size: 14px;
    font-weight: 600;
    transition: transform .25s var(--nv-ease), box-shadow .25s, background .25s, color .25s;
}

.nv-rel-all:hover {
    transform: translateY(-2px);
    background: var(--nv-ink);
    box-shadow: var(--nv-shadow-brand);
    color: var(--nv-white);
}

.nv-rel-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 24px;
    margin-top: 36px;
}

.nv-rel-card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--nv-line);
    border-radius: 24px;
    overflow: hidden;
    background: var(--nv-white);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .07);
    color: inherit;
    transition: transform .35s var(--nv-ease), box-shadow .35s;
}

.nv-rel-card:hover {
    transform: translateY(-6px);
    box-shadow: 0 24px 48px rgba(0, 0, 0, .1);
    color: inherit;
}

.nv-rel-cover {
    position: relative;
    display: block;
    aspect-ratio: 16 / 10;
    overflow: hidden;
    background: var(--nv-paper);
}

.nv-rel-cover img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .6s var(--nv-ease);
}

.nv-rel-card:hover .nv-rel-cover img {
    transform: scale(1.05);
}

/* A post whose cover was never set, or whose file is gone: the product's own
   lettered stand-in rather than an empty frame. */
.nv-rel-mark {
    display: grid;
    place-items: center;
    width: 100%;
    height: 100%;
    color: var(--nv-deep);
    font-size: 44px;
    font-weight: 700;
    line-height: 1;
}

.nv-rel-tag {
    position: absolute;
    left: 14px;
    top: 14px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--nv-white);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .12);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.nv-rel-tag-dot {
    width: 7px;
    height: 7px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--nv-brand);
}

.nv-rel-body {
    display: flex;
    flex-direction: column;
    flex: 1 1 0%;
    gap: 12px;
    padding: 22px 22px 24px;
}

.nv-rel-date {
    font-size: 12px;
    color: var(--nv-muted);
}

.nv-rel-name {
    font-size: 17px;
    font-weight: 700;
    line-height: 1.35;
    text-wrap: pretty;
}

.nv-rel-lead {
    flex: 1 1 0%;
    font-size: 13.5px;
    line-height: 1.7;
    color: color-mix(in srgb, var(--nv-muted) 85%, var(--nv-ink));
}

.nv-rel-more {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 4px;
    font-size: 13px;
    font-weight: 600;
}

.nv-rel-chev {
    display: inline-flex;
    color: var(--nv-deep);
}

/* ── Reading progress ─────────────────────────────────────────────────────────
   Built by the script and appended to the body, so it exists only on a page
   that has an article to measure. Above the fixed header (z-index 900) because
   it belongs to its bottom edge.

   Same rail as the landing's scroll bar, measured on the reference's article
   export: 4px tall, an ink-6% track so it reads as a bar that FILLS rather than
   a line that grows, a brand gradient with a glow, and a tenth of a second of
   easing so it glides instead of stepping with each scroll event. It is a
   separate class because it measures a different thing — the prose, not the
   page — and the two never share a page. */
.nv-read-progress {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    z-index: 950;
    background: color-mix(in srgb, var(--nv-ink) 6%, transparent);
    pointer-events: none;
}

.nv-read-progress i {
    display: block;
    width: 0;
    height: 100%;
    background: linear-gradient(90deg, var(--nv-brand), var(--nv-light));
    box-shadow: 0 0 12px color-mix(in srgb, var(--nv-brand) 70%, transparent);
    transition: width .1s linear;
}

/* ── Responsive ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
    /* The grid is already collapsed by [data-cols]; what is left is the column
       that was sticking to a viewport it now occupies in full. */
    .nv-art-aside {
        position: static;
        max-height: none;
        overflow: visible;
    }

    .nv-art-body {
        max-width: none;
    }
}

@media (max-width: 640px) {
    .nv-rel-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .nv-art-cover {
        border-radius: 24px 24px 0 0;
    }

    .nv-art-body .nv-art-prose blockquote > * {
        max-width: 100%;
    }
}

/* ── Dark-mode tokens ─────────────────────────────────────────────────────────
   The visitor's light/dark switch adds `html.dark` to the document element.  It
   used to exist only on the content pages, so this file was scoped to them and
   the home page stayed white underneath a visitor who had chosen dark.  The
   product now offers the same switch on the landing (skins drawn light only), so
   the tokens below are declared for BOTH markers — one palette, so a visitor who
   walks from the home page to the blog and back is never handed two different
   nights.

   Selector rationale:
     html.dark [data-rf-theme='nativa']          — the body on a content page
     html.dark body.lp[data-lp-template='nativa'] — the body on the landing
     + the component roots (.nv-posts / .nv-article-page) below, for the handful
       of properties those set directly on themselves rather than inheriting.

   THE BASE IS #1D1F1F:  the page, then #262929 for cards and bars and #313434
   for anything raised above them — three steps derived from one another rather
   than three colours picked apart, which is what keeps a card from reading
   warmer than the page behind it.  The greys are NEUTRAL (no blue cast), so the
   operator's brand is the only colour on the page and the design stays theirs.

   The tinted tokens stay derived from that brand with color-mix — the same
   pattern the light tokens use in 00-base.css — so a panel that is not the
   default yellow still gets a coherent night.  The literal that precedes each
   color-mix() line is the shade this palette was tuned with, which is what a
   browser without color-mix falls back to.

   THE BRAND CARD (.nv-art-cta) stays in its brand-background with no dark
   override: it is the conversion surface and it is already high-contrast on any
   operator colour.  The newsletter slab (.nv-posts-news) uses --nv-ink as its
   background — that token IS overridden here, so it naturally inherits the new
   dark value without any extra selector.

   Specificity note: the component roots (.nv-posts, .nv-article-page) set a
   background and color directly on themselves so that the dark shell never
   bleeds between the blocks.  Those two declarations are overridden here with
   the same selector weight, one step up via the html.dark ancestor, which is
   enough to win the cascade without an !important.

   Reset rules (`:where(…) a { color: inherit }`) have zero specificity, so they
   are unaffected and do not need repetition here. */

html.dark [data-rf-theme='nativa'],
html.dark body.lp[data-lp-template='nativa'] {
    /* ── Text ────────────────────────────────────────────────────────────────── */
    /* THE WHOLE SEVEN-STEP RAMP, not just the four aliases this file used to
       carry. 00-base.css declares ink-2…ink-7 and a handful of blocks read those
       numbered steps directly, so overriding only the aliases left those texts
       painting their LIGHT-mode grey (#5f5f5f, #6b6b6b) on a near-black card. */
    /* Neutral, because the surfaces are: a blue-cast ramp on a neutral near-black
       reads as a colour cast rather than as grey. */
    --nv-ink: #eceeee;
    --nv-ink-2: #c9cbcb;
    --nv-ink-3: #b5b8b8;
    --nv-ink-4: #a7abab;
    --nv-ink-5: #8d9191;
    --nv-ink-6: #7f8383;
    --nv-ink-7: #727676;
    --nv-ink-soft: var(--nv-ink-2);
    --nv-muted: var(--nv-ink-5);
    --nv-muted-2: var(--nv-ink-7);

    /* ── Surfaces ────────────────────────────────────────────────────────────── */
    /* White, the card surface, becomes the step above the page. */
    --nv-white: #262929;

    /* Paper tints. The deepest one is the page itself; the second is the step
       above it. Both keep a whisper of the operator's brand through color-mix so
       a panel that is not yellow still gets its own night rather than a generic
       grey — the literal in front of each line is what a browser without
       color-mix falls back to. */
    --nv-paper: #1d1f1f;
    --nv-paper: color-mix(in srgb, var(--nv-brand) 4%, #1c1e1e);
    --nv-paper-2: #212424;
    --nv-paper-2: color-mix(in srgb, var(--nv-brand) 3%, #202323);

    /* Soft tint used in avatar / pill / code backgrounds — the raised surface,
       the one a card that must stand out climbs to instead of turning white. */
    --nv-soft: #313434;
    --nv-soft: color-mix(in srgb, var(--nv-brand) 10%, #2e3131);

    /* Brand-derived accent tones for headings and kicker labels. */
    --nv-light: #c4911a;
    --nv-light: color-mix(in srgb, var(--nv-brand) 52%, #1c1e1e);
    --nv-deep: #d4a820;
    --nv-deep: color-mix(in srgb, var(--nv-brand) 70%, #262929);
    --nv-deeper: #e8c640;
    --nv-deeper: color-mix(in srgb, var(--nv-brand) 85%, #fff);

    /* ── Borders ─────────────────────────────────────────────────────────────── */
    --nv-line: #2c2f2f;
    --nv-line: color-mix(in srgb, var(--nv-brand) 5%, #2b2e2e);
    --nv-line-2: #3a3d3d;
    --nv-line-2: color-mix(in srgb, var(--nv-brand) 7%, #383b3b);

    /* ── Shadows ─────────────────────────────────────────────────────────────── */
    /* Black shadows are invisible on dark surfaces. Replaced with a very subtle
       elevation hint so the depth cues read the same way in both modes. */
    --nv-shadow-sm: 0 4px 14px rgba(0, 0, 0, .35);
    --nv-shadow: 0 10px 30px rgba(0, 0, 0, .35);
    --nv-shadow-md: 0 12px 30px rgba(0, 0, 0, .45);
    --nv-shadow-lg: 0 16px 40px rgba(0, 0, 0, .55);
    --nv-shadow-brand: 0 8px 20px color-mix(in srgb, var(--nv-brand) 30%, transparent);
}

/* ── Component roots that paint their own background ──────────────────────── */
/* .nv-posts and .nv-article-page set `background` and `color` directly on
   themselves so the dark shell does not bleed between their blocks.  The token
   override above is not enough on its own because those declarations use the
   literal token value from load time in a browser that resolves custom properties
   eagerly — the selector here repeats the assignment so it unambiguously wins. */
html.dark [data-rf-theme='nativa'] .nv-posts {
    background: var(--nv-white);
    color: var(--nv-ink);
}

html.dark [data-rf-theme='nativa'] .nv-article-page {
    background: var(--nv-paper-2);
    color: var(--nv-ink);
}

/* ── Blog listing — targeted overrides ────────────────────────────────────── */
/* Elements that paint a hard-coded literal colour (not a token) in the light
   design need an explicit rule here; everything using a token flips automatically
   via the block above. */

/* Hero gradient: token-derived, but painted as a gradient on the element itself
   rather than on a child, so the new token values are reasserted. */
html.dark [data-rf-theme='nativa'] .nv-posts-hero {
    background: linear-gradient(var(--nv-paper) 0%, var(--nv-paper-2) 100%);
}

/* Excerpt text uses a hard-coded grey (#5f5f5f / #6b6b6b) in the light design
   because it was drawn on a white card. On dark the card is --nv-white (dark),
   so neutral mid-grey is replaced with the muted token. */
html.dark [data-rf-theme='nativa'] .nv-posts-feature-ex,
html.dark [data-rf-theme='nativa'] .nv-posts-card-ex {
    color: var(--nv-ink-soft);
}

/* Category badge on card thumbnails: hard-coded white background. */
html.dark [data-rf-theme='nativa'] .nv-posts-card-cat,
html.dark [data-rf-theme='nativa'] .nv-posts-feature-flag {
    background: var(--nv-white);
    color: var(--nv-ink);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}

/* Search pill: hard-coded white card. */
html.dark [data-rf-theme='nativa'] .nv-posts-search {
    background: var(--nv-white);
    border-color: var(--nv-line-2);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .35);
}

/* Category chips: hard-coded white background. */
html.dark [data-rf-theme='nativa'] .nv-posts-chip {
    background: var(--nv-white);
    color: var(--nv-ink);
    box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
}

html.dark [data-rf-theme='nativa'] .nv-posts-chip:hover {
    background: var(--nv-soft);
}

/* Featured card and grid cards: hard-coded white background. */
html.dark [data-rf-theme='nativa'] .nv-posts-feature,
html.dark [data-rf-theme='nativa'] .nv-posts-card {
    background: var(--nv-white);
    border-color: var(--nv-line-2);
    box-shadow: 0 20px 60px rgba(0, 0, 0, .4);
}

html.dark [data-rf-theme='nativa'] .nv-posts-card {
    box-shadow: 0 12px 36px rgba(0, 0, 0, .4);
}

/* Empty state card. */
html.dark [data-rf-theme='nativa'] .nv-posts-empty {
    background: var(--nv-white);
    border-color: var(--nv-line-2);
}

/* Newsletter slab: its background is --nv-ink (which is now #ede9e1 in dark —
   too light for the intended dark-on-light slab).  The slab must stay a
   high-contrast dark surface in both modes, so it uses a fixed dark value and
   overrides text colours accordingly. */
html.dark [data-rf-theme='nativa'] .nv-posts-news {
    background: #111009;
    color: var(--nv-ink);
}

html.dark [data-rf-theme='nativa'] .nv-posts-news-text {
    color: #9a9490;
}

/* The newsletter input lives on a white pill that must stay white regardless of
   mode (it's a form field the visitor types into). */
html.dark [data-rf-theme='nativa'] .nv-posts-news-form {
    background: var(--nv-white);
}

html.dark [data-rf-theme='nativa'] .nv-posts-news-input {
    color: var(--nv-ink);
}

/* Hover elevation on cards: the dark surface already provides depth, so a
   heavier shadow makes it visible again. */
html.dark [data-rf-theme='nativa'] .nv-posts [data-card]:hover {
    box-shadow: 0 24px 48px rgba(0, 0, 0, .55);
}

/* ── Article page — targeted overrides ────────────────────────────────────── */
/* Same strategy: tokens flip automatically; literal colours and hard-coded
   surfaces need an explicit rule. */

/* Hero gradient: reasserted for the same reason as .nv-posts-hero. */
html.dark [data-rf-theme='nativa'] .nv-art-hero {
    background: linear-gradient(var(--nv-paper) 0%, var(--nv-paper-2) 100%);
}

/* Category tag badge: hard-coded white. */
html.dark [data-rf-theme='nativa'] .nv-art-tag {
    background: var(--nv-white);
    color: var(--nv-ink);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}

/* Article prose: body copy uses a color-mix literal that must be re-resolved. */
html.dark [data-rf-theme='nativa'] .nv-art-body .nv-art-prose {
    color: var(--nv-ink-soft);
}

html.dark [data-rf-theme='nativa'] .nv-art-body .nv-art-prose h2,
html.dark [data-rf-theme='nativa'] .nv-art-body .nv-art-prose h3,
html.dark [data-rf-theme='nativa'] .nv-art-body .nv-art-prose h4 {
    color: var(--nv-ink);
}

html.dark [data-rf-theme='nativa'] .nv-art-body .nv-art-prose strong,
html.dark [data-rf-theme='nativa'] .nv-art-body .nv-art-prose b {
    color: var(--nv-ink);
}

/* Inline code: hard-coded --nv-soft background on a light value.
   Already token-driven, but the new --nv-soft and --nv-deeper are the right
   dark values (handled by the token block above). */

/* Blockquote: already --nv-ink background + --nv-white text — the inverted
   ink token (#ede9e1) would make it a light card. Lock it to a near-black so
   it remains the punchy pull-quote it was designed to be. */
html.dark [data-rf-theme='nativa'] .nv-art-body .nv-art-prose blockquote {
    background: #0f0e0b;
    color: #ede9e1;
}

/* Share buttons: hard-coded white card. */
html.dark [data-rf-theme='nativa'] .nv-share-btn {
    background: var(--nv-white);
    color: var(--nv-ink);
    box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
}

/* Author card: hard-coded white card. */
html.dark [data-rf-theme='nativa'] .nv-art-author {
    background: var(--nv-white);
    border-color: var(--nv-line-2);
}

/* ToC card: hard-coded white. */
html.dark [data-rf-theme='nativa'] .nv-toc {
    background: var(--nv-white);
    border-color: var(--nv-line-2);
}

/* ToC link colour uses a color-mix literal that resolves at parse time; the
   new --nv-muted / --nv-ink values are the correct ones (token block handles
   them). */
html.dark [data-rf-theme='nativa'] .nv-toc-link {
    color: var(--nv-muted);
}

html.dark [data-rf-theme='nativa'] .nv-toc-link:hover {
    color: var(--nv-ink);
}

/* "View all" button on the further-reading band. */
html.dark [data-rf-theme='nativa'] .nv-rel-all {
    background: var(--nv-white);
    border-color: var(--nv-line-2);
    color: var(--nv-ink);
}

html.dark [data-rf-theme='nativa'] .nv-rel-all:hover {
    background: #0f0e0b;
    border-color: #0f0e0b;
    color: var(--nv-ink);
}

/* Further-reading cards: hard-coded white + warm border. */
html.dark [data-rf-theme='nativa'] .nv-rel-card {
    background: var(--nv-white);
    border-color: var(--nv-line-2);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .4);
}

html.dark [data-rf-theme='nativa'] .nv-rel-card:hover {
    box-shadow: 0 24px 48px rgba(0, 0, 0, .55);
    color: inherit;
}

/* Category tag on rel-card: hard-coded white. */
html.dark [data-rf-theme='nativa'] .nv-rel-tag {
    background: var(--nv-white);
    color: var(--nv-ink);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}

/* Further-reading excerpt: color-mix literal against light values. */
html.dark [data-rf-theme='nativa'] .nv-rel-lead {
    color: var(--nv-muted);
}

/* Further-reading band background: paper token, reasserted. */
html.dark [data-rf-theme='nativa'] .nv-rel {
    background: var(--nv-paper);
}

/* Cover image shadow: black shadow is invisible on dark. Add a border instead
   so the edge reads when the image shares a similar dark tone. */
html.dark [data-rf-theme='nativa'] .nv-art-cover {
    box-shadow: none;
    outline: 1px solid var(--nv-line-2);
}

/* ── Breadcrumb separator ─────────────────────────────────────────────────── */
/* Uses color-mix() with a hard-coded white (#fff) as the mixing base. On a dark
   surface mixing into white still produces a very light colour — correct but no
   longer subtle. Re-derive against the dark ink instead. */
html.dark [data-rf-theme='nativa'] .nv-crumb-sep {
    color: color-mix(in srgb, var(--nv-muted) 45%, var(--nv-white));
}

/* Cards on a dark surface: the article rail's categories card and the services
   catalogue's category cards. The chips and rows need no rule of their own — they
   are painted with --nv-paper, --nv-soft and --nv-ink, and all three are
   overridden at the top of this file, so they flip with the rest of the page.
   What does need one is the SHADOW: black at 5% is invisible against a dark
   surface, which is how a card ends up with no edge at all in dark mode. The
   hairline goes to the deeper line token for the same reason.

   Both are named here rather than sharing one class. They used to share
   `.nv-cat-card` and that was a collision, not reuse: "cat" is the CATEGORY chip
   card in the article and the CATALOGUE card here, the services sheet is
   concatenated after the article's, and its geometry was silently winning on the
   article page. */
html.dark [data-rf-theme='nativa'] .nv-cat-card,
html.dark [data-rf-theme='nativa'] .nv-svc-card {
    border-color: var(--nv-line-2);
    box-shadow: 0 12px 36px rgba(0, 0, 0, .4);
}

/* ── Brand highlight behind a word ────────────────────────────────────────── */
/* The swipe is NOT a highlight box: it is a brand-coloured band across the
   lower third of the words (36% of the line, starting 8% up), so in light the
   ink heading reads against the page above it and against the band below it —
   which is what the design draws.
   In dark that stops working, and the first fix here made it worse: it restated
   the whole word in on-brand ink to beat the yellow, but only the bottom third
   of each letter is ON yellow. The rest was near-black type on a near-black
   page — the heading of the page, unreadable, while the band read as a strike
   through it.
   The honest fix is the band, not the type: dropped below the baseline in dark,
   it becomes the underline it already resembles, the word keeps the cream every
   other heading has, and the operator's colour is still the accent. Measured on
   /services, where the heading is two lines and the miss was widest. */
html.dark [data-rf-theme='nativa'] .nv-posts-mark-swipe,
html.dark [data-rf-theme='nativa'] .nv-art-mark-swipe,
html.dark [data-rf-theme='nativa'] .nv-svc-mark-swipe,
html.dark [data-rf-theme='nativa'] .nv-faqp-mark-swipe,
/* And the reseller funnel's headline, added with the page rather than after a
   visitor found it: the ornament is one component drawn five times, so a new
   page joins this list at the same moment it gets its sweep. */
html.dark [data-rf-theme='nativa'] .nv-su-mark-swipe {
    bottom: 4%;
    height: 14%;
}

/* ── Brand accent on a card that INVERTED ─────────────────────────────────── */
/* The catalogue's lowest-rate card and the FAQ's answer count are drawn on
   `--nv-ink` so they read as an inverted slab, with the figure itself in the
   operator's brand colour. That works in light, where the card is near-black.
   In dark the token flips and the card turns cream — and the figure is still
   brand yellow, which measures 1.33:1 against it. The number is the whole point
   of the card, so it is the one thing on the page that cannot be left to chance.

   The colour is kept in the FAMILY rather than dropped to plain ink: the brand
   hue mixed toward the surface ink lands at 5.9:1 on that cream, so it still
   reads as the operator's amber and still passes. It is derived from
   `--nv-brand`, so it follows whatever colour the buyer picked instead of a
   second yellow this package invented.

   Measured, not guessed: brand-on-cream 1.33:1, `--nv-deep` 2.43:1, a 45% mix
   4.51:1 — only 35% clears AA with room to spare. */
html.dark [data-rf-theme='nativa'] .nv-svc-figure-ink .nv-svc-figure-n,
html.dark [data-rf-theme='nativa'] .nv-faqp-figure-n,
/* The selected topic chip: same slab, same brand figure, same 1.33:1. */
html.dark [data-rf-theme='nativa'] .nv-faqp-topic[aria-pressed='true'] .nv-faqp-topic-n,
/* And the accordion's number once its row is open. This one is the LANDING
   block's rule (66-faq.css), not this page's — the open row inverts to the ink
   and keeps the number brand-coloured, which is correct while the ink is
   near-black and unreadable the moment it is not. It surfaced here because this
   page is the first to put that accordion under the light/dark switch. */
html.dark [data-rf-theme='nativa'] .nv-faq-item[open] .nv-faq-num,
/* The catalogue's result counter (a brand figure on the same inverted pill) and
   the reseller slab's kicker, which sits straight on the slab. */
html.dark [data-rf-theme='nativa'] .nv-svc-count,
html.dark [data-rf-theme='nativa'] .nv-svc-cta-kicker,
/* The blog listing's article counter, inside the search pill. It is the same
   brand figure on the same inverted ink and it was simply missed when this rule
   was written for the catalogue — the two pills are one component drawn twice,
   which is exactly how a defect of this family hides. Measured on that page:
   1.33:1 before, and the mix below clears AA the same way it does above. */
html.dark [data-rf-theme='nativa'] .nv-posts-search-count,
/* The reseller funnel's proof figure, on the same inverted slab. Listed when the
   page was written rather than after somebody read a 1.33:1 figure on a cream
   card: any new brand-coloured number on `--nv-ink` belongs here by
   construction. */
html.dark [data-rf-theme='nativa'] .nv-su-proof-n {
    color: color-mix(in srgb, var(--nv-brand) 35%, var(--nv-white));
}

/* ── Small labels in dark ─────────────────────────────────────────────────── */
/* The catalogue's 11–12px labels are drawn in `--nv-muted`, which is the grey
   the DESIGN uses and which measures 4.0–4.3:1 on its own light surfaces —
   borderline, and the designer's call to make on the page they drew.

   Dark is not their page. The design has no dark mode, so this is the theme's
   own surface, and the same token lands at 3.1–3.9:1 there. The labels move one
   step up the ramp to `--nv-ink-soft`, the token that already carries exactly
   this job elsewhere in the package, so light stays pixel-faithful to the
   reference and dark stops asking the reader to squint. */
/* `:not(.nv-svc-figure-ink)` is load-bearing. The inverted card already states
   its own label colour against its own surface, and this rule is the more
   specific of the two — applied to it as well, the light grey lands on the cream
   the card turns into and measures 1.84:1. A blanket fix that walks over a rule
   written for the one surface that differs is how an accessibility pass creates
   the defect it came to remove. */
html.dark [data-rf-theme='nativa'] .nv-svc-figure:not(.nv-svc-figure-ink) .nv-svc-figure-l,
html.dark [data-rf-theme='nativa'] .nv-svc-meta,
html.dark [data-rf-theme='nativa'] .nv-svc-pill,
html.dark [data-rf-theme='nativa'] .nv-svc-modal-k,
html.dark [data-rf-theme='nativa'] .nv-svc-modal-sid,
html.dark [data-rf-theme='nativa'] .nv-svc-qty-k,
html.dark [data-rf-theme='nativa'] .nv-svc-qty-t,
/* The blog listing's dates, on the lead card and on every card in the grid.
   They are the same 12px small print and they need the step for the SECOND
   reason this layer exists: the light fix moved them DOWN the ramp to clear
   4.5:1 on white (--nv-ink-4, #6b6b6b), and that ramp is not inverted here, so
   left alone they would be a dark grey on a near-black card — worse than the
   token they replaced. Measured dark: 3.87:1 on the design's own grey. */
html.dark [data-rf-theme='nativa'] .nv-posts-by-date,
html.dark [data-rf-theme='nativa'] .nv-posts-card-date {
    color: var(--nv-ink-soft);
}

/* ── The topic chip's count, on a chip that is NOT selected ───────────────── */
/* The chips carry their label in the surface ink and the count one step down
   the grey ramp. That ramp is NOT inverted by this layer (only the semantic
   tokens are), so on the dark chip the count is a dark grey on near-black: it
   measured 3.26:1 — and it got there partly BECAUSE of the light-mode fix in
   parts/94-faq-page.css, which moved the page's small print one step DARKER to
   clear the threshold on white. The two modes pull the same token in opposite
   directions, which is exactly the case this layer exists for.
   Derived from the chip's own ink mixed back into its own fill, so it follows
   whatever surface the chip ends up with instead of naming a third grey: 55%
   measures 5.18:1 and still reads as secondary next to the label. The selected
   chip is excluded — it inverts to cream and has its own rule above. */
html.dark [data-rf-theme='nativa'] .nv-faqp-topic:not([aria-pressed='true']) .nv-faqp-topic-n {
    color: color-mix(in srgb, var(--nv-ink) 55%, var(--nv-paper));
}

/* ── Landing blocks: the contrast cards that carry a THIRD colour ─────────────
   The design's "contrast card" is a pair — `background: var(--nv-ink)` with
   `color: var(--nv-white)` — and that pair needs nothing here: both tokens flip
   together, so the card turns light with dark text on it and stays as readable
   as it was drawn. Inverting a card that exists to stand out is the right answer
   on a dark page; painting it white is not, which is why only the exceptions
   below are pinned.

   The exceptions are the cards that put something OTHER than --nv-white on that
   ink background: a brand-coloured label, a hand-written grey, an amber tuned
   for a dark surface. Those do not flip, so when the card turns light they are
   left painting light-on-light. Each one is kept DARK instead of inverted, which
   is also what the design means: on a dark page a card stands out by being
   raised (--nv-soft, the shade WhatsApp puts its own raised surfaces on), not by
   being the only white rectangle on the screen. */

/* Inbox — the send button is ink with the brand colour on it. */
html.dark body.lp[data-lp-template='nativa'] .nv-inbox-send {
    background: var(--nv-soft);
    color: var(--nv-brand);
}

/* FAQ — the support card is ink with white copy and a hand-written grey meta
   line (the design drew rgb(189,189,189) for a dark card, which is what it is
   again here). */
html.dark body.lp[data-lp-template='nativa'] .nv-faq-support {
    background: var(--nv-soft);
    color: var(--nv-ink);
}

/* ink-4 and not ink-5: the meta line sits on the RAISED surface, not on the
   page, and a grey is chosen against the surface it LANDS on. Measured on the
   current palette, ink-5 clears 4.60:1 against the page and falls to 3.29:1
   against this card; ink-4 holds 4.53:1 where the line actually sits. */
html.dark body.lp[data-lp-template='nativa'] .nv-faq-support-meta {
    color: var(--nv-ink-4);
}

/* Networks — the price box is a literal cream panel with an amber label, both
   drawn for a light page. */
html.dark body.lp[data-lp-template='nativa'] .nv-net-total-box {
    background: var(--nv-soft);
}

html.dark body.lp[data-lp-template='nativa'] .nv-net-total-label,
html.dark body.lp[data-lp-template='nativa'] .nv-net-rate-badge {
    color: var(--nv-deeper);
}

/* Networks — a tab's icon paints in its own network colour and falls back to
   --nv-ink when the network has none (Likes, Reel views, Comments). On the
   SELECTED tab that fallback is the same token the tab just took as its
   background, so those three icons disappeared into it. */
html.dark body.lp[data-lp-template='nativa'] .nv-net-tab[aria-pressed='true'] .nv-net-tab-icon {
    color: var(--nv-white);
}

/* ── Services catalogue ───────────────────────────────────────────────────────
   The public /services page: a full-bleed warm hero carrying the catalogue's
   figures, the search pill and the sort switch beneath it, the networks as chips,
   and the categories as collapsing cards over a six-column table.

   Numbers come from the design's resolved DOM (SMM Services.html): the hero on a
   #fdf6dc → #fef9e8 gradient with clamp(44px, 6vw, 76px) above and
   clamp(28px, 4vw, 44px) below, a 420px orb bleeding out of its top-right corner
   at .35 opacity; its 7fr/5fr columns 32px apart and BOTTOM aligned; the headline
   clamp(34px, 4.6vw, 58px)/1.08 at -.03em with a 36%-tall sweep skewed -6deg; the
   figure cards 20px radius, 18px of padding, 26px numerals at -.02em over
   0 12px 34px rgba(0, 0, 0, .06); the search pill 6px 6px 6px 20px on
   0 14px 40px rgba(0, 0, 0, .08) with an 11px 16px ink counter; the chips
   8px 16px 8px 8px with a 28px round glyph and a .25s swap to ink; the category
   cards 22px radius on a 1.5px #f1ecd9 border over 0 8px 26px rgba(0, 0, 0, .05),
   turning to a #f7c600 border and 0 22px 54px rgba(247, 198, 0, .18) when open;
   the table 56px / 1fr / 110px / 90px / 110px / 88px at 12px gaps, its head
   10px 22px in 11px uppercase at .06em on #fffdf3, its rows 14px 22px over
   #f7f3e4 hairlines; the reseller slab 32px radius on the ink with a 340px orb;
   the modal min(560px, 100%) at 28px radius over 0 40px 100px rgba(0, 0, 0, .35).

   THIS PAGE IS NOT THE LANDING, so the base layer's page rules — the font, the
   resets, the reduced-motion clause — are scoped to `body.lp` and do not reach
   here. Everything is therefore declared on `.nv-svc` itself and every rule below
   is scoped to it, so the blog, the FAQ and the legal pages that share this
   stylesheet are left exactly as they were.

   THE ACCORDION DOES NOT ANIMATE ITS HEIGHT, and that is deliberate rather than
   missing: a category's rows are fetched from the server when it is opened, so
   the panel does not exist to be transitioned from 0fr — it arrives already full.
   The reference's grid-template-rows transition would therefore play against an
   empty box and then pop. The rows fade up instead, which is honest about where
   they came from and reads as the same gesture. */

/* Release the layout's 1200px rail for this page only, matched by what is inside
   it rather than by its address — the other content pages keep the box they were
   built for. A browser without :has() keeps the rail: narrower than drawn, never
   broken. */
body[data-rf-theme='nativa'] main:has(> .nv-svc) {
    max-width: none;
    padding: 0;
}

@supports not (selector(:has(*))) {
    .nv-svc {
        width: 100vw;
        margin: -2.5rem calc(50% - 50vw);
    }
}

.nv-svc {
    background: var(--nv-paper);

    /* A block formatting context: without it the last block's bottom margin
       collapses out through <main> onto the body and paints the shell's own grey
       between this page and the dark footer. */
    display: flow-root;

    color: var(--nv-ink);
    font-family: var(--nv-font);
    font-size: 15px;
    text-align: start;
    -webkit-font-smoothing: antialiased;

    /* One step down the grey ramp for THIS page's small print, scoped here
       rather than changed at the token.
       Why at all: every 12px label on this page — "services live", "from $X /
       1K · Instagram", "4 services" — is drawn in --nv-muted (#7a7a7a), which
       measures 4.29:1 on white and 4.03:1 on the warm pill. The threshold at
       that size is 4.5, so 28 labels sat just under it. --nv-ink-4 (#6b6b6b)
       clears both surfaces, and it is a shade the design already uses — nothing
       was invented to pass a number.
       Why scoped: the same token paints the landing page, where the type it
       colours is 14–16px and comfortably above the line. Moving it globally
       would repaint approved work to fix something that only exists at 12px. */
    --nv-muted: var(--nv-ink-4);
}

.nv-svc *,
.nv-svc *::before,
.nv-svc *::after {
    box-sizing: border-box;
}

.nv-svc :focus-visible {
    outline: 2px solid var(--nv-brand);
    outline-offset: 2px;
}

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

.nv-svc-hero {
    position: relative;
    overflow: hidden;
    background: linear-gradient(180deg, var(--nv-paper) 0%, var(--nv-paper-2) 100%);
    padding: clamp(44px, 6vw, 76px) 0 clamp(28px, 4vw, 44px);
}

.nv-svc-orb {
    position: absolute;
    inset-inline-end: -140px;
    top: -160px;
    width: 420px;
    height: 420px;
    border-radius: 50%;

    /* The brand colour, so the orb is the operator's yellow and not ours. */
    background: var(--nv-brand);
    opacity: .35;
    filter: blur(10px);
    pointer-events: none;
}

.nv-svc-hero-grid {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 32px;

    /* Bottom aligned: the figures sit on the same baseline as the lead paragraph,
       which is what stops the right column floating in the middle of the hero. */
    align-items: end;
}

.nv-svc-title {
    margin: 18px 0 0;
    font-size: clamp(34px, 4.6vw, 58px);
    line-height: 1.08;
    font-weight: 700;
    letter-spacing: -.03em;
    text-wrap: balance;
}

/* The sweep is drawn BEHIND the closing words rather than around them, so the
   letters keep their own colour whatever the operator's brand turns out to be —
   the same reasoning as the blog listing's, which is why the geometry matches. */
.nv-svc-mark {
    position: relative;
    display: inline-block;
}

.nv-svc-mark-swipe {
    position: absolute;
    inset-inline: -6px;
    bottom: 8%;
    z-index: 0;
    height: 36%;
    border-radius: 6px;
    background: var(--nv-brand);
    transform: skewX(-6deg);
}

.nv-svc-mark-text {
    position: relative;
    z-index: 1;
}

.nv-svc-lead {
    margin: 18px 0 0;
    max-width: 52ch;
    font-size: 16px;
    line-height: 1.7;
    color: var(--nv-ink-soft);
}

/* ── The catalogue's figures ─────────────────────────────────────────────────── */

.nv-svc-figures {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
}

/* Two cards when the panel sells nothing yet (the lowest-rate card is omitted
   rather than printing a zero), so the row is told to fill whatever it has
   instead of leaving a gap where the third would be. */
.nv-svc-figures:has(> :last-child:nth-child(2)) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.nv-svc-figure {
    padding: 18px;
    border-radius: 20px;
    background: var(--nv-white);
    border: 1px solid var(--nv-line);
    box-shadow: 0 12px 34px rgba(0, 0, 0, .06);
}

.nv-svc-figure-ink {
    background: var(--nv-ink);
    border-color: var(--nv-ink);
    box-shadow: 0 12px 34px rgba(0, 0, 0, .12);
}

.nv-svc-figure-n {
    margin: 0;
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -.02em;
    line-height: 1.15;
}

.nv-svc-figure-ink .nv-svc-figure-n {
    color: var(--nv-brand);
}

.nv-svc-figure-l {
    margin: 4px 0 0;
    font-size: 12px;
    color: var(--nv-muted);
}

.nv-svc-figure-ink .nv-svc-figure-l {
    color: color-mix(in srgb, var(--nv-white) 72%, var(--nv-ink));
}

/* ── Search + sort ──────────────────────────────────────────────────────────── */

.nv-svc-tools {
    position: relative;
    display: flex;
    gap: 12px;
    margin-top: 34px;
    flex-wrap: wrap;
}

.nv-svc-search {
    flex: 1 1 320px;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 6px 6px 20px;
    border-radius: 999px;
    background: var(--nv-white);
    border: 1px solid var(--nv-line);
    box-shadow: 0 14px 40px rgba(0, 0, 0, .08);
}

.nv-svc-search-i {
    display: inline-flex;
    color: var(--nv-muted);
}

.nv-svc-search input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    font: inherit;
    font-size: 14.5px;
    color: var(--nv-ink);
    padding: 10px 0;
}

.nv-svc-search input:focus {
    outline: none;
}

.nv-svc-search input::placeholder {
    color: var(--nv-muted-2);
}

/* Safari renders the clear affordance of a search field as a dark blob inside a
   rounded pill; the field keeps its semantics either way. */
.nv-svc-search input::-webkit-search-decoration,
.nv-svc-search input::-webkit-search-cancel-button {
    -webkit-appearance: none;
}

.nv-svc-count {
    display: inline-flex;
    align-items: center;
    padding: 11px 16px;
    border-radius: 999px;
    background: var(--nv-ink);
    color: var(--nv-brand);
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
}

.nv-svc-sort {
    display: flex;
    gap: 6px;
    padding: 6px;
    border-radius: 999px;
    background: var(--nv-white);
    border: 1px solid var(--nv-line);
    box-shadow: 0 14px 40px rgba(0, 0, 0, .08);
}

.nv-svc-sort button {
    border: 0;
    padding: 10px 16px;
    border-radius: 999px;
    background: transparent;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    color: var(--nv-ink);
    transition: background .25s, color .25s;
}

.nv-svc-sort button:hover {
    background: var(--nv-soft);
}

.nv-svc-sort button[aria-pressed='true'] {
    background: var(--nv-ink);
    color: var(--nv-white);
    box-shadow: 0 12px 28px rgba(0, 0, 0, .18);
}

/* ── Body ───────────────────────────────────────────────────────────────────── */

.nv-svc-body {
    padding-bottom: clamp(56px, 7vw, 96px);
}

/* ── Networks ───────────────────────────────────────────────────────────────── */

.nv-svc-nets {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    padding: 28px 0;
}

.nv-svc-net {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 8px 16px 8px 8px;
    border-radius: 999px;
    border: 0;
    background: var(--nv-white);
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    color: var(--nv-ink);
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .05);
    transition: background .25s, color .25s, box-shadow .25s;
}

.nv-svc-net:hover {
    background: var(--nv-soft);
}

.nv-svc-net[aria-pressed='true'] {
    background: var(--nv-ink);
    color: var(--nv-white);
    box-shadow: 0 12px 28px rgba(0, 0, 0, .18);
}

.nv-svc-net-i {
    display: inline-grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;

    /* The network's own colour comes in on the element, from the product's shared
       --net-* tokens. This is only the fallback for a category filed under no
       platform, where there is no brand colour to be faithful to. */
    background: var(--nv-muted);
    color: var(--nv-white);
    flex: none;
}

.nv-svc-net-all {
    background: var(--nv-ink);
}

.nv-svc-net[aria-pressed='true'] .nv-svc-net-all {
    background: var(--nv-brand);
    color: var(--nv-ink);
}

.nv-svc-net-i svg {
    fill: currentColor;
}

.nv-svc-net-mono {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: -.02em;
}

.nv-svc-net-n {
    font-size: 11px;
    font-weight: 700;
    opacity: .5;
}

/* ── Category cards ─────────────────────────────────────────────────────────── */

.nv-svc-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.nv-svc-card {
    background: var(--nv-white);
    border-radius: 22px;
    border: 1.5px solid var(--nv-line);
    box-shadow: 0 8px 26px rgba(0, 0, 0, .05);
    overflow: hidden;
    /* The fixed bar is cleared by scroll-padding-top on `html` (00-base). A
       scroll-margin here would ADD to it and drop the card 100px lower than the
       rest of the page's destinations — see the note in 91-article.css. */
    transition: box-shadow .3s, border-color .3s;

    /* Staggered entrance, capped by the blade at eight steps so a long page does
       not end with rows arriving a second and a half late. */
    animation: nv-svc-up .5s cubic-bezier(.2, .7, .2, 1) both;
    animation-delay: calc(var(--nv-i, 0) * .04s);
}

.nv-svc-card:hover {
    box-shadow: 0 18px 44px rgba(0, 0, 0, .08);
}

.nv-svc-card.is-open {
    border-color: var(--nv-brand);
    box-shadow: 0 22px 54px rgba(247, 198, 0, .18);
}

@keyframes nv-svc-up {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: none; }
}

.nv-svc-head {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 18px;
    border: 0;
    background: transparent;
    font: inherit;
    text-align: start;
    cursor: pointer;
    color: inherit;
}

.nv-svc-badge {
    flex: none;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 13px;
    background: var(--nv-ink);
    color: var(--nv-white);
    box-shadow: 0 8px 18px rgba(0, 0, 0, .12);
}

.nv-svc-badge svg {
    fill: currentColor;
}

.nv-svc-badge-mono {
    font-size: 15px;
    font-weight: 700;
}

.nv-svc-headings {
    flex: 1;
    min-width: 0;
}

.nv-svc-name {
    display: block;
    font-size: 15.5px;
    font-weight: 700;
    line-height: 1.3;
}

.nv-svc-meta {
    display: block;
    margin-top: 2px;
    font-size: 12px;
    color: var(--nv-muted);
}

.nv-svc-meta b {
    color: var(--nv-ink);
}

/* An empty meta line (no "from" price resolved and no platform) would still take
   its 2px of margin and push the title off centre. */
.nv-svc-meta:empty {
    display: none;
}

.nv-svc-pill {
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--nv-paper);
    color: var(--nv-muted);
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
    flex: none;
}

.nv-svc-spin {
    display: inline-flex;
    color: var(--nv-muted);
    animation: nv-svc-spin 1s linear infinite;
}

@keyframes nv-svc-spin {
    to { transform: rotate(360deg); }
}

.nv-svc-chev {
    flex: none;
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--nv-paper);
    color: var(--nv-ink);
    transition: transform .35s cubic-bezier(.2, .7, .2, 1), background .3s, color .3s;
}

.nv-svc-card.is-open .nv-svc-chev {
    transform: rotate(180deg);
    background: var(--nv-ink);
    color: var(--nv-brand);
}

/* ── The table ──────────────────────────────────────────────────────────────── */

.nv-svc-drawer {
    border-top: 1px solid var(--nv-line);
}

.nv-svc-th,
.nv-svc-row {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr) 110px 90px 110px 88px;
    gap: 12px;
    align-items: center;
}

.nv-svc-th {
    /* `--nv-ink-soft`, not `--nv-muted-2`: measured on this page's own surfaces
       the lighter grey comes out at 2.71:1 in light and 2.14:1 in dark on 11px
       uppercase, which is unreadable by any bar. The muted greys stay where they
       belong — on text that recedes beside something else carrying the meaning;
       a column heading IS the meaning of its column. */
    padding: 10px 22px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--nv-ink-soft);
    background: var(--nv-paper-2);
}

.nv-svc-th > :nth-child(3),
.nv-svc-th > :nth-child(4),
.nv-svc-th > :nth-child(5) {
    text-align: end;
}

.nv-svc-row {
    padding: 14px 22px;
    border-top: 1px solid var(--nv-line);
    transition: background .2s;

    /* The rows arrive with the drawer, from the server — see the note at the top
       of this file about why the panel itself is not transitioned. */
    animation: nv-svc-up .35s cubic-bezier(.2, .7, .2, 1) both;
}

.nv-svc-row:hover {
    background: var(--nv-paper-2);
}

.nv-svc-id {
    font-size: 12px;
    color: var(--nv-ink-soft);
    font-weight: 600;
}

.nv-svc-svc {
    min-width: 0;
}

.nv-svc-svc-n {
    display: block;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.4;
}

.nv-svc-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}

.nv-tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
}

.nv-tag-warm {
    background: var(--nv-paper);
    color: var(--nv-muted);
}

.nv-tag-good {
    background: #eef7f1;
    color: #0f7a3a;
}

.nv-tag-ink {
    background: var(--nv-ink);
    color: var(--nv-brand);
}

.nv-svc-rate {
    text-align: end;
    font-weight: 700;
    font-size: 15px;
    color: var(--nv-ink);
}

/* A flat-price service says so under its price rather than borrowing the per-1K
   column header, which would misdescribe what the checkout charges. */
.nv-svc-flat {
    display: block;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--nv-muted);
}

.nv-svc-num {
    text-align: end;
    font-size: 13px;
    color: var(--nv-ink-soft);
}

.nv-svc-mlab {
    display: none;
    color: var(--nv-ink-soft);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    margin-inline-end: 4px;
}

.nv-svc-act {
    text-align: end;
}

.nv-svc-view {
    border: 1.5px solid var(--nv-ink);
    padding: 8px 14px;
    border-radius: 999px;
    background: var(--nv-white);
    font: inherit;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    color: var(--nv-ink);
    transition: background .2s, color .2s;
}

.nv-svc-view:hover {
    background: var(--nv-ink);
    color: var(--nv-brand);
}

.nv-svc-more {
    padding: 14px 22px 18px;
    border-top: 1px solid var(--nv-line);
    text-align: center;
}

.nv-svc-pages {
    margin-top: 22px;
}

/* ── Empty state ────────────────────────────────────────────────────────────── */

.nv-svc-empty {
    text-align: center;
    padding: 44px 20px;
    background: var(--nv-white);
    border-radius: 22px;
    border: 1.5px dashed var(--nv-line);
}

.nv-svc-empty-i {
    display: inline-grid;
    place-items: center;
    width: 64px;
    height: 64px;
    border-radius: 20px;
    background: var(--nv-soft);
    color: var(--nv-muted);
    margin-bottom: 14px;
}

.nv-svc-empty-t {
    margin: 0;
    font-weight: 600;
    color: var(--nv-ink);
    font-size: 16px;
}

.nv-svc-empty-s {
    margin: 6px 0 0;
    font-size: 14px;
    color: var(--nv-muted);
}

.nv-svc-empty-s button {
    border: 0;
    background: transparent;
    padding: 0;
    font: inherit;
    font-weight: 600;
    color: var(--nv-ink);
    cursor: pointer;
    text-decoration: underline;
}

/* ── Buttons ────────────────────────────────────────────────────────────────── */

/* .nv-btn, .nv-btn-brand and .nv-btn-outline come from the base layer, which
   declares them UNSCOPED precisely so the content pages can use them. They are
   not redeclared here; only the two things this page needs that do not exist yet
   are, and only the properties that differ.

   The page's buttons are a size down from the landing's (13px 24px against
   14px 28px, 14px type against 15px) because they sit inside cards and a modal
   rather than under a hero. */
.nv-svc .nv-btn {
    padding: 13px 24px;
    font-size: 14px;
    gap: 8px;
}

/* The secondary action on the ink slab: legible on black without competing with
   the brand button beside it. */
.nv-svc .nv-btn-dim {
    /* Derived from the white token rather than written as a white alpha: it sits
       on the ink slab, and the slab inverts with the page. */
    background: color-mix(in srgb, var(--nv-white) 10%, transparent);
    color: var(--nv-white);
    font-weight: 600;
}

.nv-svc .nv-btn-dim:hover {
    background: color-mix(in srgb, var(--nv-white) 20%, transparent);
    box-shadow: none;
}

/* ── Reseller slab ──────────────────────────────────────────────────────────── */

.nv-svc-cta {
    position: relative;
    margin-top: clamp(40px, 5vw, 64px);
    padding: clamp(30px, 4vw, 48px) clamp(24px, 5vw, 56px);
    background: var(--nv-ink);
    color: var(--nv-white);
    border-radius: 32px;
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    gap: 32px;
    align-items: center;
    overflow: hidden;
}

/* The design puts a solid 340px brand orb here AND centres the two buttons in
   the column it bleeds over — measured on its own export, the orb swallows 126px
   of the primary button, which is brand yellow on brand yellow. There is no
   placement that fixes it: the buttons occupy the whole right column and that is
   exactly where the orb lands. So the silhouette stays and the orb becomes a
   wash, the way every other orb in this theme already reads (.35 in the hero,
   .7 in the landing CTA). Below .5 it turns olive over the ink; above it the
   button melts back into it. */
.nv-svc-cta-orb {
    position: absolute;
    inset-inline-end: -100px;
    top: -140px;
    width: 340px;
    height: 340px;
    border-radius: 50%;
    background: var(--nv-brand);
    opacity: .5;
    filter: blur(8px);
    pointer-events: none;
}

/* Both columns sit above the orb — the copy by document order, the actions by
   an explicit layer, since a shorter headline lifts them further into it. */
.nv-svc-cta-copy,
.nv-svc-cta-acts {
    position: relative;
    z-index: 1;
}

.nv-svc-cta-kicker {
    margin: 0;
    color: var(--nv-brand);
    font-weight: 600;
    font-size: 14px;
}

.nv-svc-cta-title {
    margin: 10px 0 0;
    font-size: clamp(24px, 2.8vw, 36px);
    line-height: 1.15;
    font-weight: 700;
}

.nv-svc-cta-body {
    margin: 14px 0 0;
    font-size: 14px;
    line-height: 1.8;
    color: color-mix(in srgb, var(--nv-white) 72%, var(--nv-ink));
    max-width: 52ch;
}

.nv-svc-cta-acts {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* ── Service modal ──────────────────────────────────────────────────────────── */

.nv-svc-modal-back {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(27, 27, 27, .55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);

    /* Layout in CLASSES, never in an inline style: x-show removes the `display`
       property from the inline style when it reveals an element, so a
       display:flex written inline would vanish and the overlay would fall back to
       display:block in the top-left corner. */
    display: grid;
    place-items: center;
    padding: 20px;
}

.nv-svc-modal {
    width: min(560px, 100%);
    background: var(--nv-white);
    border-radius: 28px;
    box-shadow: 0 40px 100px rgba(0, 0, 0, .35);
    overflow: hidden;
    max-height: calc(100vh - 40px);
    overflow-y: auto;
    animation: nv-svc-pop .35s cubic-bezier(.2, .8, .2, 1) both;
}

@keyframes nv-svc-pop {
    from { opacity: 0; transform: translateY(18px) scale(.97); }
    to   { opacity: 1; transform: none; }
}

.nv-svc-modal-top {
    position: relative;
    padding: 24px 26px 20px;
    background: linear-gradient(135deg, var(--nv-paper), var(--nv-white));
}

.nv-svc-modal-x {
    position: absolute;
    inset-inline-end: 16px;
    top: 16px;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 0;
    background: var(--nv-white);
    box-shadow: 0 6px 16px rgba(0, 0, 0, .1);
    display: grid;
    place-items: center;
    cursor: pointer;
    color: var(--nv-ink);
}

.nv-svc-modal-id {
    display: flex;
    align-items: center;
    gap: 12px;
}

.nv-svc-modal-id .nv-svc-badge {
    width: 44px;
    height: 44px;
    border-radius: 14px;
}

.nv-svc-modal-cat {
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--nv-muted);
}

.nv-svc-modal-sid {
    margin: 2px 0 0;
    font-size: 12px;
    color: var(--nv-muted);
}

.nv-svc-modal-title {
    margin: 16px 0 0;
    font-size: 20px;
    line-height: 1.3;
    font-weight: 700;
    padding-inline-end: 40px;
}

.nv-svc-modal-top .nv-svc-tags {
    margin-top: 12px;
}

.nv-svc-modal-body {
    padding: 20px 26px 26px;
}

.nv-svc-modal-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

.nv-svc-modal-cell {
    padding: 14px 16px;
    border-radius: 16px;
    background: var(--nv-paper);
    border: 1px solid var(--nv-line);
}

.nv-svc-modal-k {
    margin: 0;
    font-size: 11px;
    color: var(--nv-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
}

.nv-svc-modal-v {
    margin: 4px 0 0;
    font-size: 22px;
    font-weight: 700;
}

.nv-svc-modal-v-sm {
    font-size: 16px;
}

.nv-svc-modal-desc {
    margin: 18px 0 0;
    font-size: 13.5px;
    line-height: 1.75;
    color: var(--nv-ink-soft);
}

.nv-svc-modal-desc-none {
    opacity: .6;
}

.nv-svc-qty {
    margin-top: 18px;
    padding: 14px 16px;
    border-radius: 16px;
    background: var(--nv-white);
    border: 1.5px solid var(--nv-line);
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.nv-svc-qty-k {
    font-size: 12px;
    font-weight: 600;
    color: var(--nv-muted);
}

.nv-svc-qty input[type='range'] {
    flex: 1;
    min-width: 120px;
    accent-color: var(--nv-brand);
}

.nv-svc-qty-n {
    font-weight: 700;
    font-size: 14px;
    min-width: 64px;
    text-align: end;
}

.nv-svc-qty-t {
    margin-inline-start: auto;
    font-size: 12px;
    color: var(--nv-muted);
}

.nv-svc-qty-t b {
    font-size: 16px;
    color: var(--nv-ink);
    margin-inline-start: 4px;
}

.nv-svc-modal-foot {
    display: flex;
    gap: 10px;
    margin-top: 18px;
    justify-content: flex-end;
    flex-wrap: wrap;
}

/* ── Narrow screens ─────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
    .nv-svc-hero-grid,
    .nv-svc-cta {
        grid-template-columns: 1fr !important;
    }

    .nv-svc-figures {
        grid-template-columns: 1fr 1fr !important;
    }

    /* Three cards into two columns leaves the third alone on its row with an
       empty half beside it — the only ragged edge on the page at this width,
       and it falls on the card that carries the price. It spans the row
       instead. Written with :has so it applies ONLY when there are three: the
       two-card panel (no services priced yet) already fills its row. */
    .nv-svc-figures:has(> :last-child:nth-child(3)) > :last-child {
        grid-column: 1 / -1;
    }

    .nv-svc [data-hide-sm] {
        display: none !important;
    }
}

@media (max-width: 760px) {
    /* The orb is an ACCENT, and an accent is a proportion of the screen, not a
       number of pixels. At 420px it covers a fifth of a desktop hero and the
       WHOLE of a phone's — the brand colour stops being a glow in the corner
       and becomes the background, which on the dark palette reads as an olive
       wash behind the text. Halved and dimmed so it does the same job on a
       phone that it does on a laptop. */
    .nv-svc-orb {
        width: 220px;
        height: 220px;
        inset-inline-end: -90px;
        top: -110px;
        opacity: .22;
    }

    /* The head disappears and every cell labels itself, because a six-column
       table at 380px is six columns of nothing. */
    .nv-svc-th {
        display: none !important;
    }

    .nv-svc-row {
        grid-template-columns: 1fr auto !important;
    }

    .nv-svc-id {
        display: none !important;
    }

    .nv-svc-num {
        grid-column: 1 / -1;
        display: flex;
        gap: 14px;
        padding-top: 6px;
        text-align: start;
    }

    .nv-svc-mlab {
        display: inline;
    }

    .nv-svc-modal-grid {
        grid-template-columns: 1fr;
    }
}

/* Someone who asked their system for less movement gets the page, not the
   choreography. */
@media (prefers-reduced-motion: reduce) {
    .nv-svc *,
    .nv-svc *::before,
    .nv-svc *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

/* ── Dark mode ──────────────────────────────────────────────────────────────── */
/* Everything above is written in the semantic tokens, which 92-dark.css already
   flips, so this section is only for the two pairs that are genuinely their own
   colour rather than a shade of the page: the green "this service does that"
   ticks, and the hairline between table rows, which at 10% of the brand is too
   faint to read against a dark card. */
html.dark [data-rf-theme='nativa'] .nv-tag-good {
    background: color-mix(in srgb, #2ecc71 16%, transparent);
    color: #6ee7a8;
}

html.dark [data-rf-theme='nativa'] .nv-svc-row,
html.dark [data-rf-theme='nativa'] .nv-svc-more,
html.dark [data-rf-theme='nativa'] .nv-svc-drawer {
    border-color: color-mix(in srgb, var(--nv-ink) 14%, transparent);
}

/* ── FAQ page ─────────────────────────────────────────────────────────────────
   The public /faq page: the same warm full-bleed hero, search pill and chips as
   the services catalogue, over the accordion this theme already draws on the
   landing, with a sticky rail beside it.

   NOTHING ABOUT THE ACCORDION IS DECLARED HERE. `.nv-faq-item`, `.nv-faq-q`,
   `.nv-faq-num`, `.nv-faq-text`, `.nv-faq-chev` and the `.nv-faq-body` prose
   rules live in 66-faq.css and are not scoped to `body.lp`, so this page uses
   them as they stand. A second copy would be two accordions drifting apart the
   first time one is touched.

   THE PREFIX IS `nv-faqp-`, NOT `nv-faq-`, and that is load-bearing: this theme
   ships ONE concatenated stylesheet, so a class name carrying two meanings is
   not reuse — it is the later sheet silently restyling the earlier page. It
   already happened once between the article rail's `.nv-cat-card` (category) and
   the catalogue's (catalogue), which is how the article ended up with a 22px
   radius nobody had asked for.

   THIS PAGE IS NOT THE LANDING, so the base layer's page rules — the font, the
   resets — are scoped to `body.lp` and do not reach here. Everything is declared
   on `.nv-faqp` itself and every rule below is scoped to it, so the blog, the
   catalogue and the legal pages that share this stylesheet are untouched. */

/* Release the layout's rail for this page only, matched by what is inside it
   rather than by its address. A browser without :has() keeps the rail: narrower
   than drawn, never broken. */
body[data-rf-theme='nativa'] main:has(> .nv-faqp) {
    max-width: none;
    padding: 0;
}

@supports not (selector(:has(*))) {
    .nv-faqp {
        width: 100vw;
        margin: -2.5rem calc(50% - 50vw);
    }
}

.nv-faqp {
    background: var(--nv-paper);

    /* A block formatting context: without it the last block's bottom margin
       collapses out through <main> onto the body and paints the shell's own grey
       between this page and the dark footer. */
    display: flow-root;

    color: var(--nv-ink);
    font-family: var(--nv-font);
    font-size: 15px;
    text-align: start;
    -webkit-font-smoothing: antialiased;

    /* Same step down the ramp as the catalogue page, for the same reason and
       with the same scope — see the note in parts/93-services.css. */
    --nv-muted: var(--nv-ink-4);
}

.nv-faqp *,
.nv-faqp *::before,
.nv-faqp *::after {
    box-sizing: border-box;
}

.nv-faqp :focus-visible {
    outline: 2px solid var(--nv-brand);
    outline-offset: 2px;
}

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

.nv-faqp-hero {
    position: relative;
    overflow: hidden;
    background: linear-gradient(180deg, var(--nv-paper) 0%, var(--nv-paper-2) 100%);
    padding: clamp(44px, 6vw, 76px) 0 clamp(28px, 4vw, 44px);
}

.nv-faqp-orb {
    position: absolute;
    inset-inline-end: -140px;
    top: -160px;
    width: 420px;
    height: 420px;
    border-radius: 50%;

    /* The brand colour, so the orb is the operator's yellow and not ours. */
    background: var(--nv-brand);
    opacity: .35;
    filter: blur(10px);
    pointer-events: none;
}

.nv-faqp-hero-grid {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 8fr) minmax(0, 4fr);
    gap: 32px;

    /* Bottom aligned: the figure sits on the lead paragraph's baseline, which is
       what stops the right column floating in the middle of the hero. */
    align-items: end;
}

/* One column when the panel has published nothing, so the heading takes the
   width instead of leaving a hole where the figure would have been. */
.nv-faqp-hero-grid:has(> :last-child:nth-child(1)) {
    grid-template-columns: minmax(0, 1fr);
}

.nv-faqp-title {
    margin: 18px 0 0;
    font-size: clamp(34px, 4.6vw, 58px);
    line-height: 1.08;
    font-weight: 700;
    letter-spacing: -.03em;
    text-wrap: balance;
}

/* The sweep is drawn BEHIND the closing word rather than around it, so the
   letters keep their own colour whatever the operator's brand turns out to be —
   the same reasoning as the catalogue's, which is why the geometry matches. */
.nv-faqp-mark {
    position: relative;
    display: inline-block;
}

.nv-faqp-mark-swipe {
    position: absolute;
    inset-inline: -6px;
    bottom: 8%;
    z-index: 0;
    height: 36%;
    border-radius: 6px;
    background: var(--nv-brand);
    transform: skewX(-6deg);
}

.nv-faqp-mark-text {
    position: relative;
    z-index: 1;
}

.nv-faqp-lead {
    margin: 18px 0 0;
    max-width: 60ch;
    font-size: 16px;
    line-height: 1.7;
    color: var(--nv-ink-soft);
}

/* ── The one figure ─────────────────────────────────────────────────────────── */

.nv-faqp-figure {
    padding: 18px;
    border-radius: 20px;
    background: var(--nv-ink);
    border: 1px solid var(--nv-ink);
    box-shadow: 0 12px 34px rgba(0, 0, 0, .12);
}

.nv-faqp-figure-n {
    margin: 0;
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -.02em;
    line-height: 1.15;
    color: var(--nv-brand);
}

.nv-faqp-figure-l {
    margin: 4px 0 0;
    font-size: 12px;
    color: color-mix(in srgb, var(--nv-white) 72%, var(--nv-ink));
}

/* ── Search ─────────────────────────────────────────────────────────────────── */

.nv-faqp-tools {
    position: relative;
    display: flex;
    margin-top: 34px;
}

.nv-faqp-search {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 6px 6px 20px;
    border-radius: 999px;
    background: var(--nv-white);
    border: 1px solid var(--nv-line);
    box-shadow: 0 14px 40px rgba(0, 0, 0, .08);
}

.nv-faqp-search-i {
    display: inline-flex;
    color: var(--nv-muted);
}

.nv-faqp-search input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    font: inherit;
    font-size: 14.5px;
    color: var(--nv-ink);
    padding: 10px 0;
}

.nv-faqp-search input:focus {
    outline: none;
}

.nv-faqp-search input::placeholder {
    color: var(--nv-muted);
}

/* The native clear cross is the browser's own and lands on the pill's ink;
   hidden so the counter is the only thing in that corner. */
.nv-faqp-search input::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
}

.nv-faqp-count {
    flex: 0 0 auto;
    padding: 11px 16px;
    border-radius: 999px;
    background: var(--nv-soft);
    color: var(--nv-ink-soft);
    font-size: 12.5px;
    font-weight: 600;
    white-space: nowrap;
}

/* ── Body ───────────────────────────────────────────────────────────────────── */

/* `padding-block`, NEVER the `padding` shorthand: this element also carries
   `.nv-wrap`, whose whole job is the page's side gutter, and a shorthand here
   sets the horizontal sides to zero. The page then runs edge to edge and the
   rail — which pokes 4px out of its own box to give its shadows room — spills
   past the viewport. The symptom reads as "the grid is too wide", which is why
   it is worth naming: nothing is too wide, the gutter was overwritten. */
.nv-faqp-body {
    padding-block: clamp(26px, 3.4vw, 40px) clamp(48px, 6vw, 84px);
}

/* ── Topics ─────────────────────────────────────────────────────────────────── */

.nv-faqp-topics {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    padding-bottom: 26px;
}

.nv-faqp-topic {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 9px 16px;
    border-radius: 999px;
    border: 1px solid var(--nv-line);
    background: var(--nv-white);
    color: var(--nv-ink);
    font: inherit;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
    transition: background .25s, color .25s, border-color .25s;
}

.nv-faqp-topic:hover {
    border-color: var(--nv-brand);
}

.nv-faqp-topic[aria-pressed='true'] {
    background: var(--nv-ink);
    border-color: var(--nv-ink);
    color: var(--nv-white);
}

.nv-faqp-topic-n {
    font-size: 11.5px;
    font-weight: 700;
    color: var(--nv-muted);
}

.nv-faqp-topic[aria-pressed='true'] .nv-faqp-topic-n {
    color: var(--nv-brand);
}

/* ── Layout: questions + rail ───────────────────────────────────────────────── */

.nv-faqp-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 32px;
    align-items: start;
}

/* One column when the rail was dropped (no questions to sit beside), so the
   accordion or the empty state takes the width instead of leaving a gap. */
.nv-faqp-layout:has(> :last-child:nth-child(1)) {
    grid-template-columns: minmax(0, 1fr);
}

.nv-faqp-main {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* ── Rail ───────────────────────────────────────────────────────────────────── */

.nv-faqp-rail {
    position: sticky;
    top: 100px;
    display: flex;
    flex-direction: column;
    gap: 16px;

    /* A sticky column taller than the viewport puts its own overflow out of
       reach, so it carries a ceiling and scrolls itself. The negative margin and
       matching padding give the cards' shadows room inside that scroller. */
    max-height: calc(100vh - 124px);
    margin: -4px;
    padding: 4px;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* THE CARDS MUST NOT SHRINK. A flex column with a ceiling squeezes its items
   before it agrees to scroll, and these cards clip their own overflow — so the
   column would quietly make the last one shorter than its contents and cut its
   button off. It reads as a design choice rather than a defect, which is exactly
   why it is stated; the column scrolls, the cards keep their height. */
.nv-faqp-rail > * {
    flex: 0 0 auto;
}

.nv-faqp-help {
    position: relative;
    overflow: hidden;
    padding: 24px;
    border-radius: 24px;
    background: var(--nv-ink);
    color: var(--nv-white);
}

.nv-faqp-help-orb {
    position: absolute;
    inset-inline-end: -70px;
    top: -90px;
    width: 220px;
    height: 220px;
    border-radius: 50%;
    background: var(--nv-brand);

    /* A wash, not a disc. Solid, it lands on the card's own button — the exact
       collision the catalogue's reseller slab was carrying, where brand yellow
       sat on brand yellow and the call to action disappeared. */
    opacity: .5;
    filter: blur(8px);
    pointer-events: none;
}

.nv-faqp-help-in {
    position: relative;
    z-index: 1;
}

.nv-faqp-help-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 14px;
    background: color-mix(in srgb, var(--nv-white) 12%, transparent);
    color: var(--nv-brand);
}

.nv-faqp-help-t {
    margin: 14px 0 0;
    font-size: 17px;
    font-weight: 700;
    letter-spacing: -.01em;
}

.nv-faqp-help-s {
    margin: 8px 0 0;
    font-size: 13.5px;
    line-height: 1.7;
    color: color-mix(in srgb, var(--nv-white) 72%, var(--nv-ink));
}

.nv-faqp-help-cta {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 18px;
    padding: 12px 20px;
    border-radius: 999px;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
    font-size: 13.5px;
    font-weight: 700;
    text-decoration: none;
    transition: transform .25s;
}

.nv-faqp-help-cta:hover {
    transform: translateY(-2px);
}

.nv-faqp-next {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 18px 20px;
    border-radius: 20px;
    border: 1px solid var(--nv-line);
    background: var(--nv-white);
    box-shadow: 0 10px 30px rgba(0, 0, 0, .05);
    color: var(--nv-ink);
    text-decoration: none;
    transition: border-color .25s, transform .25s;
}

.nv-faqp-next:hover {
    border-color: var(--nv-brand);
    transform: translateY(-2px);
}

.nv-faqp-next-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 12px;
    background: var(--nv-soft);
    color: var(--nv-ink);
}

.nv-faqp-next-t {
    display: block;
    font-size: 14px;
    font-weight: 700;
}

/* `--nv-ink-soft`, not `--nv-muted`: measured on the card this sits on, muted
   comes out at 4.29:1 in light and 3.87:1 in dark, and this is 12.5px text, so
   the bar is 4.5. Muted is the right token for a label beside something that
   carries the meaning; this line IS the meaning of the card. */
.nv-faqp-next-s {
    display: block;
    margin-top: 2px;
    font-size: 12.5px;
    color: var(--nv-ink-soft);
}

/* ── Empty states ───────────────────────────────────────────────────────────── */

.nv-faqp-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: clamp(46px, 7vw, 80px) 24px;
    border-radius: 24px;
    border: 1px dashed var(--nv-line);
    background: var(--nv-white);
    text-align: center;
}

.nv-faqp-empty-i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--nv-soft);
    color: var(--nv-muted);
}

.nv-faqp-empty-t {
    margin: 12px 0 0;
    font-size: 17px;
    font-weight: 700;
}

.nv-faqp-empty-s {
    margin: 0 0 16px;
    font-size: 14px;
    color: var(--nv-muted);
}

/* ── Narrow ─────────────────────────────────────────────────────────────────── */

@media (max-width: 1000px) {
    /* The rail goes UNDER the questions rather than beside them. It keeps its
       cards — support is the reason someone reads this page to the end — but
       drops the sticky, which on a short screen would pin a card over the
       answers the visitor is reading. */
    .nv-faqp-layout {
        grid-template-columns: minmax(0, 1fr);
    }

    .nv-faqp-rail {
        position: static;
        max-height: none;
        overflow: visible;
        flex-direction: row;
        flex-wrap: wrap;
    }

    .nv-faqp-rail > * {
        flex: 1 1 280px;
    }
}

@media (max-width: 760px) {
    .nv-faqp-hero-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Same proportion argument as the catalogue's orb — see the note in
       parts/93-services.css. */
    .nv-faqp-orb {
        width: 220px;
        height: 220px;
        inset-inline-end: -90px;
        top: -110px;
        opacity: .22;
    }

    /* The figure reads as a strap under the lead rather than a card floating
       alone at full width. */
    .nv-faqp-figure {
        justify-self: start;
    }
}

@media (max-width: 560px) {
    /* The counter leaves the pill: at this width it takes the room the query
       itself needs, and the result count is restated by the list below it. */
    .nv-faqp-count {
        display: none;
    }

    .nv-faqp-search {
        padding: 6px 16px;
    }
}

/* ── Legal / CMS pages ────────────────────────────────────────────────────────
   /terms, /cookie-policy and every /p/{slug} the operator writes — which is
   where the Privacy Policy and the Refund Policy live, i.e. the two footer links
   a visitor is most likely to open before paying anybody.

   These screens could not be dressed at all until the core passed them through
   theme_view(). Before that a buyer installed a design that redrew their whole
   site and the first click on the footer walked the visitor out of it: the
   header was this theme's, the page body was the product's, and in dark mode
   that was THREE different blacks stacked in one screenshot — the shell's
   #262929 bar, a green-cast #0a140f page from the compiled bundle, and a #161616
   footer. The gutter did not line up either: the heading sat at 16px while the
   logo above it sat at 40.

   NOTHING ABOUT THE PROSE IS DECLARED HERE. The article's reading component
   (`.nv-art-body` > `.nv-art-prose`, parts/91-article.css) is what the markup
   composes, so headings, lists, quotes, code and links are the same twenty-four
   rules a blog post uses. A second copy would be two typographies drifting apart
   the first time one of them is touched — which is precisely how the footer
   spacing broke two sprints ago.

   THE PREFIX IS `nv-legal-`, and the check was done before writing: it appears
   in no other part of this stylesheet. One concatenated sheet means a class name
   carrying two meanings is not reuse, it is the later file silently restyling
   the earlier page (see the note at the top of 94-faq-page.css).

   THIS PAGE IS NOT THE LANDING, so the base layer's page rules are scoped to
   `body.lp` and do not reach here: the font, the colour and the smoothing are
   declared on `.nv-legal-page` itself. */

/* Release the layout's own rail for this page, matched by what is inside it
   rather than by its address — the same technique the FAQ page uses. This is
   what fixes the gutter: the shell's rail is 1200px with a fixed 16px pad, and
   `.nv-wrap` below is the theme's own (1180px content inside a --nv-pad that
   resolves to the same 40px the header and footer use), so the heading finally
   lines up with the logo above it. A browser without :has() keeps the shell's
   rail: narrower than drawn, never broken. */
body[data-rf-theme='nativa'] main:has(> .nv-legal-page) {
    max-width: none;
    padding: 0;
}

.nv-legal-page {
    background: var(--nv-paper);

    /* A block formatting context: without it the last paragraph's bottom margin
       collapses out through <main> onto the body and paints the shell's own grey
       between this page and the dark footer. Same trap as the FAQ page. */
    display: flow-root;

    color: var(--nv-ink);
    font-family: var(--nv-font);
    text-align: start;
    -webkit-font-smoothing: antialiased;

    /* The page must reach the footer even when the operator has written three
       lines of terms, or the shell's own background shows below it as a band. */
    min-height: 60vh;
}

.nv-legal {
    padding-block: clamp(40px, 6vw, 72px) clamp(56px, 7vw, 96px);
}

.nv-legal-head {
    margin-bottom: clamp(28px, 4vw, 44px);
    padding-bottom: clamp(20px, 3vw, 28px);
    border-bottom: 1px solid var(--nv-line);

    /* The rule spans the reading column, not the full 1180: a hairline running
       the whole width over a 720px column reads as a page divider rather than as
       this heading's underline. */
    max-width: 720px;
}

.nv-legal-title {
    margin: 0;
    /* One step below the article's headline. A policy is not a story: it takes
       the same reading measure but should not announce itself like a feature. */
    font-size: clamp(30px, 4.4vw, 46px);
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--nv-ink);
    text-wrap: balance;
}

.nv-legal-meta {
    margin: 12px 0 0;
    font-size: 14px;
    color: var(--nv-muted);
}

/* The published-but-empty state. It is the operator's own doing, so it reads as
   "nothing written yet" rather than as a page that failed to load. */
.nv-legal-empty {
    margin: 0;
    color: var(--nv-muted);
    font-style: italic;
}

/* ── Reseller funnel (/reseller-signup) ───────────────────────────────────────
   The page that SELLS panels: a warm full-bleed hero carrying the promise strip
   and the proof slab, then the live plan cards alongside the form in one screen
   so nobody has to scroll back to check what they picked.

   WHY IT IS HERE AT ALL. This was the last public surface no design could reach,
   and the most expensive one to leave behind: a buyer installs a theme that
   redraws their whole site, and the single page whose job is to turn a visitor
   into a paying reseller came out wearing the product's body inside this
   design's header and footer.

   THE PREFIX IS `nv-su-`, checked against every other part before a line was
   written. One concatenated stylesheet means a class name carrying two meanings
   is not reuse — it is the later file silently restyling the earlier page, which
   is exactly how the article's card geometry drifted when `nv-cat-` meant both
   "category" and "catalogue" (see the top of 93-services.css).

   THIS PAGE IS NOT THE LANDING, so the base layer's page rules — the font, the
   resets, the reduced-motion clause — are scoped to `body.lp` and never reach
   here. Everything is declared on `.nv-su` itself and every rule below is scoped
   to it, so the blog, the FAQ, the catalogue and the legal pages that share this
   stylesheet are left exactly as they were.

   DARK MODE IS AT THE FOOT OF THIS FILE rather than in 92-dark.css, for the same
   reason the catalogue's is at the foot of its own: the parts are concatenated in
   name order, so a rule for `.nv-su-*` written in 92 would be overridden by this
   file. Almost nothing needs saying there — every surface below is painted with
   a token, and the tokens are what the dark layer re-declares. */

/* Release the layout's 1200px rail for this page only, matched by what is inside
   it rather than by its address. A browser without :has() keeps the rail:
   narrower than drawn, never broken. */
body[data-rf-theme='nativa'] main:has(> .nv-su) {
    max-width: none;
    padding: 0;
}

.nv-su {
    background: var(--nv-paper);

    /* A block formatting context: without it the last block's bottom margin
       collapses out through <main> onto the body and paints the shell's own grey
       between this page and the dark footer. Same trap as the FAQ page. */
    display: flow-root;

    color: var(--nv-ink);
    font-family: var(--nv-font);
    font-size: 15px;
    text-align: start;
    -webkit-font-smoothing: antialiased;

    /* The page must reach the footer even on a short installation — one free
       plan and no upgrade tiers — or the shell's own background shows below it
       as a band. */
    min-height: 60vh;

    /* One step down the grey ramp for THIS page's small print, scoped here
       rather than changed at the token — the same remedy /services and the FAQ
       page already carry, for the same measured reason.
       Why at all: every 11–13px label on this page (the column kicker, the
       "Catalogue only" tag, the upgrade prices, the address hint, the sign-in
       line) is drawn in --nv-muted (#7a7a7a), which measures 4.03–4.29:1 on
       white and on the warm paper. The threshold at that size is 4.5, so seven
       strings sat just under it. --nv-ink-4 (#6b6b6b) clears both surfaces, and
       it is a shade the design already uses — nothing was invented to pass a
       number.
       Why scoped: the same token paints the landing page, where the type it
       colours is 14–16px and comfortably above the line. Moving it globally
       would repaint approved work to fix something that only exists at 12px. */
    --nv-muted: var(--nv-ink-4);
}

.nv-su *,
.nv-su *::before,
.nv-su *::after {
    box-sizing: border-box;
}

.nv-su :focus-visible {
    outline: 2px solid var(--nv-brand);
    outline-offset: 2px;
}

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

.nv-su-hero {
    position: relative;
    overflow: hidden;
    background: linear-gradient(180deg, var(--nv-paper) 0%, var(--nv-paper-2) 100%);
    padding: clamp(44px, 6vw, 76px) 0 clamp(32px, 4vw, 48px);
}

.nv-su-orb {
    position: absolute;
    inset-inline-end: -140px;
    top: -160px;

    /* Sized against the viewport, not in fixed pixels: a 420px accent is a glow
       in the corner of a desktop and the BACKGROUND of a 390px phone, where the
       brand yellow stops being a highlight and washes the text it sits behind. */
    width: clamp(220px, 34vw, 420px);
    height: clamp(220px, 34vw, 420px);
    border-radius: 50%;

    /* The brand colour, so the orb is the operator's yellow and not ours. */
    background: var(--nv-brand);
    opacity: .35;
    filter: blur(10px);
    pointer-events: none;
}

.nv-su-hero-grid {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 32px;
    align-items: end;
}

.nv-su-title {
    margin: 18px 0 0;
    font-size: clamp(34px, 4.6vw, 58px);
    line-height: 1.08;
    font-weight: 700;
    letter-spacing: -.03em;
    color: var(--nv-ink);
    text-wrap: balance;
}

/* The brand sweep under the tail of the headline. It is a band across the lower
   36% of the line, NOT a highlight box — which is why the text above it keeps
   its own colour instead of being repainted to fight a yellow background. */
.nv-su-mark {
    position: relative;
    display: inline-block;
    white-space: nowrap;
}

/* The same numbers as every other sweep in this package — the blog listing, the
   article, the catalogue, the FAQ page — and not numbers of its own: a visitor
   meets this ornament on five pages, and a band sitting two pixels lower on one
   of them reads as a mistake rather than as a variation. Its DARK rule is
   shared with those four in 92-dark.css, where dropping the band below the
   baseline is declared once for all of them. */
.nv-su-mark-swipe {
    position: absolute;
    inset-inline: -6px;
    bottom: 8%;
    z-index: 0;
    height: 36%;
    border-radius: 6px;
    background: var(--nv-brand);
    transform: skewX(-6deg);
}

.nv-su-mark-text {
    position: relative;
    z-index: 1;
}

.nv-su-lead {
    margin: 18px 0 0;
    max-width: 52ch;
    font-size: 16px;
    line-height: 1.65;
    color: var(--nv-ink-soft);
}

.nv-su-perks {
    margin: 22px 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 10px 22px;
}

.nv-su-perks li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 500;
    color: var(--nv-ink-soft);
}

.nv-su-tick {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

/* The proof slab. `ink` + `white` is the design's contrast pair, and in dark
   mode it INVERTS on its own — a light slab with dark type, as legible as it was
   drawn — which is why neither is overridden at the foot of this file. */
.nv-su-proof {
    align-self: end;
    padding: 22px 24px;
    border-radius: 22px;
    background: var(--nv-ink);
    color: var(--nv-white);
    box-shadow: var(--nv-shadow-md);
}

.nv-su-proof-n {
    margin: 0;
    font-size: clamp(30px, 3.4vw, 40px);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -.02em;
    color: var(--nv-brand);
}

.nv-su-proof-l {
    margin: 8px 0 0;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.45;

    /* Not --nv-muted: this slab does not invert with the page, so the grey ramp
       would paint light-mode grey on ink. The surface's own text colour, softened
       by transparency, stays right in both modes. */
    color: color-mix(in srgb, var(--nv-white) 72%, transparent);
}

/* ── Body ─────────────────────────────────────────────────────────────────── */

.nv-su-body {
    padding-block: clamp(32px, 4vw, 52px) clamp(56px, 7vw, 96px);
}

.nv-su-grid {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: clamp(20px, 3vw, 32px);
    align-items: start;
}

.nv-su-col-k {
    margin: 0 0 12px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--nv-muted);
}

/* ── Plan cards ───────────────────────────────────────────────────────────── */

.nv-su-plans {
    display: flex;
    flex-direction: column;
}

.nv-su-plan {
    display: block;
    width: 100%;
    margin-bottom: 12px;
    padding: 18px;
    border: 1.5px solid var(--nv-line);
    border-radius: 20px;
    background: var(--nv-white);
    box-shadow: var(--nv-shadow-sm);
    text-align: start;
    font-family: inherit;
    color: inherit;
    cursor: pointer;
    transition: border-color .25s, box-shadow .25s, transform .25s var(--nv-ease);
}

.nv-su-plan:hover {
    transform: translateY(-2px);
    border-color: var(--nv-line-2);
}

.nv-su-plan.is-on {
    border-color: var(--nv-brand);
    box-shadow: 0 16px 40px color-mix(in srgb, var(--nv-brand) 18%, transparent);
}

.nv-su-plan-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

.nv-su-plan-id {
    display: block;
}

.nv-su-plan-n {
    display: block;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -.01em;
}

.nv-su-plan-p {
    display: block;
    margin-top: 3px;
    font-size: 13px;
    color: var(--nv-muted);
}

.nv-su-plan-p b {
    font-weight: 700;
    color: var(--nv-ink);
}

/* The chosen mark. Always in the layout, invisible until the card is picked: a
   tick that appears on click would reflow the heading beside it every time. */
.nv-su-plan-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1.5px solid var(--nv-line-2);
    color: transparent;
    transition: background .2s, border-color .2s, color .2s;
}

.nv-su-plan.is-on .nv-su-plan-mark {
    border-color: var(--nv-brand);
    background: var(--nv-brand);
    color: var(--nv-on-brand);
}

.nv-su-plan-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 12px;
}

.nv-su-plan-lines {
    display: flex;
    flex-direction: column;
    gap: 7px;
    margin-top: 12px;
    font-size: 13px;
    line-height: 1.45;
    color: var(--nv-ink-soft);
}

.nv-su-plan-lines > span {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.nv-su-plan-lines .nv-su-tick {
    width: 18px;
    height: 18px;
    margin-top: 1px;
}

/* ── "Grow whenever you want" ─────────────────────────────────────────────── */

.nv-su-grow {
    margin-top: 8px;
    padding: 18px;
    border: 1.5px dashed var(--nv-line-2);
    border-radius: 20px;
}

.nv-su-grow-t {
    margin: 0;
    font-size: 14px;
    font-weight: 700;
}

.nv-su-grow-s {
    margin: 6px 0 0;
    font-size: 13px;
    line-height: 1.55;
    color: var(--nv-muted);
}

.nv-su-grow-list {
    margin: 14px 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.nv-su-grow-list li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font-size: 13px;
    font-weight: 600;
}

.nv-su-grow-p {
    font-weight: 500;
    color: var(--nv-muted);
    white-space: nowrap;
}

/* ── The form ─────────────────────────────────────────────────────────────── */

.nv-su-card {
    padding: clamp(22px, 3vw, 30px);
    border: 1.5px solid var(--nv-line);
    border-radius: 24px;
    background: var(--nv-white);
    box-shadow: var(--nv-shadow);
}

.nv-su-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 20px;
}

.nv-su-card-t {
    margin: 0;
    font-size: clamp(20px, 2.2vw, 26px);
    font-weight: 800;
    letter-spacing: -.02em;
}

/* Computed by the page, not claimed by the operator: the funnel only contracts a
   free tier, so this is printed from the plans and disappears when an install
   with no free public plan falls back to a paid one. */
.nv-su-free {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 999px;
    background: var(--nv-soft);
    color: var(--nv-deeper);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
}

.nv-su-field {
    margin-bottom: 16px;
}

.nv-su-lab {
    display: block;
    margin-bottom: 6px;
    font-size: 13px;
    font-weight: 600;
    color: var(--nv-ink);
}

.nv-su-in {
    width: 100%;
    padding: 12px 14px;
    border: 1.5px solid var(--nv-line-2);
    border-radius: 12px;
    background: var(--nv-paper-2);
    color: var(--nv-ink);
    font-family: inherit;
    font-size: 15px;
    transition: border-color .2s, box-shadow .2s, background .2s;
}

.nv-su-in::placeholder {
    color: var(--nv-muted-2);
}

.nv-su-in:focus {
    outline: none;
    border-color: var(--nv-brand);
    background: var(--nv-white);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--nv-brand) 22%, transparent);
}

.nv-su-in.is-bad {
    border-color: #d94a3d;
}

/* The subdomain field and its suffix read as ONE control: the visitor is typing
   the left half of an address whose right half they cannot change. */
.nv-su-host {
    display: flex;
    align-items: stretch;
}

.nv-su-host .nv-su-in {
    border-start-end-radius: 0;
    border-end-end-radius: 0;
}

.nv-su-host-s {
    display: inline-flex;
    align-items: center;
    padding: 0 14px;
    border: 1.5px solid var(--nv-line-2);
    border-inline-start: 0;
    border-start-end-radius: 12px;
    border-end-end-radius: 12px;
    background: var(--nv-soft);
    color: var(--nv-deeper);
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
}

.nv-su-pair {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 16px;
}

.nv-su-hint {
    margin: 6px 0 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--nv-muted);
}

.nv-su-err {
    margin: 6px 0 0;
    font-size: 12px;
    font-weight: 500;
    color: #d94a3d;
}

.nv-su-terms {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-top: 4px;
    font-size: 14px;
    line-height: 1.5;
    color: var(--nv-ink-soft);
    cursor: pointer;
}

.nv-su-terms input {
    flex: none;
    width: 17px;
    height: 17px;
    margin-top: 2px;
    accent-color: var(--nv-brand);
}

.nv-su-terms a {
    color: var(--nv-ink);
    text-decoration: underline;
    text-decoration-color: var(--nv-brand);
    text-underline-offset: 3px;
    font-weight: 600;
}

.nv-su-go {
    width: 100%;
    margin-top: 20px;
}

.nv-su-go[disabled] {
    opacity: .7;
    cursor: progress;
}

.nv-su-foot {
    margin: 14px 0 0;
    text-align: center;
    font-size: 13px;
    color: var(--nv-muted);
}

.nv-su-foot a {
    color: var(--nv-ink);
    font-weight: 600;
    text-decoration: underline;
    text-decoration-color: var(--nv-brand);
    text-underline-offset: 3px;
}

/* ── Narrow ───────────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
    .nv-su-hero-grid,
    .nv-su-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    /* The proof slab stops being a column and becomes a strip under the copy. */
    .nv-su-proof {
        display: flex;
        align-items: baseline;
        gap: 12px;
    }

    .nv-su-proof-l {
        margin: 0;
    }
}

@media (max-width: 560px) {
    .nv-su-pair {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ── Dark ─────────────────────────────────────────────────────────────────── */
/* Two rules, because everything above paints with a token and the dark layer
   re-declares the tokens. What it cannot re-declare is a literal. */

/* The error red was picked for a white card; on the night surface it drops to
   3.1:1. One step lighter clears the threshold without becoming a second red. */
html.dark [data-rf-theme='nativa'] .nv-su-err,
html.dark [data-rf-theme='nativa'] .nv-su-in.is-bad {
    --nv-su-bad: #ff8b7e;
}

html.dark [data-rf-theme='nativa'] .nv-su-err {
    color: var(--nv-su-bad);
}

html.dark [data-rf-theme='nativa'] .nv-su-in.is-bad {
    border-color: var(--nv-su-bad);
}

/* The field background is a shade ABOVE the card in light mode (a warm paper
   tint on white) and has to be a shade BELOW it at night, or an input on a
   #262929 card paints itself lighter than the card and reads as a disabled
   control rather than an empty one. */
html.dark [data-rf-theme='nativa'] .nv-su-in {
    background: var(--nv-paper);
}

html.dark [data-rf-theme='nativa'] .nv-su-in:focus {
    background: var(--nv-paper-2);
}
