/* ═══════════════════════════════════════════════════════════════════
   V2 COMPONENTS
   Additions and variants for next-website-v2 only.
   Rules here use ONLY existing custom properties from styles.css and the
   .v2 palette overrides in styles-v2.css. No new colours, no new fonts,
   no new spacing values.
   ═══════════════════════════════════════════════════════════════════ */


/* ─── NAV: 8 items + 2 actions ─────────────────────────────────────
   The base bar was built for 7 items and one button. Three adjustments
   make the new set fit without changing the bar's design language:
   smaller mark, tighter gap, and one solid action instead of two.      */

.v2 .nav-logo-img { height: 52px; }

.v2 .nav-menu { gap: var(--s-6); }

.v2 .nav-menu a,
.v2 .nav-cta,
.v2 .nav-signin { white-space: nowrap; }

/* Secondary action: text link, sits immediately before the solid button */
.v2 .nav-signin {
    font-family: var(--font-body);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--dark);
    text-decoration: none;
    margin-left: var(--s-4);
    transition: color var(--t-fast);
}
.v2 .nav-signin:hover { color: var(--teal); }

/* Hamburger takes over earlier so the bar never crowds on tablets */
@media (max-width: 1100px) {
    .v2 .nav-menu,
    .v2 .nav-signin { display: none; }
    .v2 .nav-toggle { display: flex; }
}


/* ─── HERO: action row ─────────────────────────────────────────────
   The base hero carries no CTA. The new content needs two. Uses the
   existing button components unchanged.                               */

.v2 .hero-cta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
    margin-top: var(--s-6);
}

/* Hero eligibility footnote - small, quiet, sits under the actions */
.v2 .hero-footnote {
    margin-top: var(--s-5);
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    line-height: 1.6;
    letter-spacing: 0.02em;
    color: var(--gray-lite);
    max-width: 34em;
}


/* ─── HERO CARD 2: flatten the bar graphic ─────────────────────────
   The 12 bars are kept (the markup contract requires exactly 12) but
   their heights are levelled. Ascending bars read as a growth chart,
   and no figures are being published, so they must read as texture.    */

.v2 .layer-bars span:nth-child(1)  { height: 46%; }
.v2 .layer-bars span:nth-child(2)  { height: 62%; }
.v2 .layer-bars span:nth-child(3)  { height: 38%; }
.v2 .layer-bars span:nth-child(4)  { height: 70%; }
.v2 .layer-bars span:nth-child(5)  { height: 50%; }
.v2 .layer-bars span:nth-child(6)  { height: 58%; }
.v2 .layer-bars span:nth-child(7)  { height: 42%; }
.v2 .layer-bars span:nth-child(8)  { height: 66%; }
.v2 .layer-bars span:nth-child(9)  { height: 54%; }
.v2 .layer-bars span:nth-child(10) { height: 34%; }
.v2 .layer-bars span:nth-child(11) { height: 60%; }
.v2 .layer-bars span:nth-child(12) { height: 48%; }


/* ─── STAT CARD: title + description variant ───────────────────────
   The base card renders an index number and a large figure. The three
   ecosystem pillars are not a sequence and carry no figure, so both are
   suppressed and the label is promoted to the card title.              */

.v2 .stat-card--pillar .stat-num,
.v2 .stat-card--pillar .stat-value { display: none; }

.v2 .stat-card--pillar .stat-title {
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--dark);
    margin-bottom: var(--s-2);
}

.v2 .stat-card--pillar .stat-desc {
    font-size: 0.9375rem;
    line-height: 1.8;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
}

/* Owner default: side-by-side cards align their first body line even
   when one title wraps and its neighbour does not. */
.v2 .stat-card--pillar .stat-title { min-height: 2.6em; }

/* When a pillar card carries an action, the description stretches so the
   buttons in a row all sit on the same baseline. */
.v2 .stat-card--pillar { display: flex; flex-direction: column; }
.v2 .stat-card--pillar .stat-desc { flex: 1 1 auto; }

/* Icon above the card title, sitting on the same left edge as the title.
   The card is a flex column, so the icon is pinned with align-self and
   flex:none, otherwise it would be stretched to the full card width and
   squashed vertically when the row runs short of space. The width and
   height attributes on the tag itself reserve the space before the file
   arrives, so the title does not jump as the page loads. */
.v2 .stat-card--pillar .pillar-icon {
    display: block;
    width: 64px;
    height: 64px;
    align-self: flex-start;
    flex: 0 0 auto;
    margin-bottom: var(--s-4);
}


/* ─── PILLAR ROW: three across, collapsing cleanly ─────────────────  */

.v2 .pillar-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s-8);
}
@media (max-width: 900px) {
    .v2 .pillar-row { grid-template-columns: 1fr; }
    .v2 .stat-card--pillar .stat-title { min-height: 0; }
}


/* ─── STATUS CHIP: "Coming Soon" ───────────────────────────────────  */

.v2 .status-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    font-family: var(--font-mono);
    font-size: 0.625rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--teal-deep);
    background: var(--teal-pale);
    border: 1px solid var(--bcd);
    border-radius: 999px;
    padding: var(--s-1) var(--s-3);
}
.v2 .status-chip::before {
    content: "";
    width: 5px; height: 5px;
    border-radius: 50%;
    background: var(--teal);
}


/* ─── STEP ROW: numbered horizontal steps ──────────────────────────
   Promoted from how-it-works.html's local block, reduced to the row
   form the homepage snapshot needs.                                    */

/* OWNER DEFAULT: columns of justified text need real breathing room.
   Narrow columns + justified text produce ugly word gaps and make
   neighbouring columns read as one block. Wider gutters, looser lines. */
.v2 .step-row {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--s-10);
    margin-top: var(--s-10);
}
.v2 .step-item { position: relative; padding-top: var(--s-6); }
.v2 .step-item::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: var(--border-soft);
}
.v2 .step-item-num {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.1em;
    color: var(--teal);
    display: block;
    margin-bottom: var(--s-3);
}
.v2 .step-item h3 {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--dark);
    margin-bottom: var(--s-4);
    min-height: 2.6em;
}
.v2 .step-item p {
    font-size: 0.9375rem;
    line-height: 1.8;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
}
@media (max-width: 900px) {
    .v2 .step-row { grid-template-columns: 1fr; gap: var(--s-6); }
    .v2 .step-item h3 { min-height: 0; }
}


/* ─── REASON LIST: two-column bullet set ───────────────────────────  */

.v2 .reason-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-3) var(--s-8);
    margin-top: var(--s-6);
}
.v2 .reason-item {
    position: relative;
    padding-left: var(--s-6);
    font-size: 0.9375rem;
    line-height: 1.7;
    color: var(--gray);
}
.v2 .reason-item::before {
    content: "";
    position: absolute;
    left: 0; top: 0.62em;
    width: 7px; height: 7px;
    border-radius: 2px;
    background: var(--teal);
    transform: rotate(45deg);
}
@media (max-width: 700px) {
    .v2 .reason-grid { grid-template-columns: 1fr; }
}


/* ─── PLAN PREVIEW CARDS ───────────────────────────────────────────  */

.v2 .plan-preview {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s-5);
    margin-top: var(--s-8);
}
.v2 .plan-card {
    background: var(--white);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-md);
    padding: var(--s-6);
    position: relative;
}
.v2 .plan-card-name {
    font-family: var(--font-display);
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--dark);
    margin-bottom: var(--s-2);
}
.v2 .plan-card-desc {
    font-size: 0.9375rem;
    line-height: 1.65;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
    min-height: 4.9em;
}
.v2 .plan-card-price {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    color: var(--gray-lite);
    border-top: 1px solid var(--border-hairline);
    padding-top: var(--s-4);
    margin-top: var(--s-4);
}
@media (max-width: 900px) {
    .v2 .plan-preview { grid-template-columns: 1fr; }
    .v2 .plan-card-desc { min-height: 0; }
}


/* ─── SECTION HELPERS ──────────────────────────────────────────────  */

/* OWNER DEFAULT: a justified paragraph spans the SAME width as the
   heading above it. Left and right edges must line up with the title.
   The narrower max-width that used to sit here broke that alignment. */
.v2 .section-intro {
    max-width: none;
    font-size: 1.0625rem;
    line-height: 1.8;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
    margin-top: var(--s-5);
}

/* Owner default: justified body copy, words never broken across lines */
.v2 .section-intro,
.v2 .stat-desc,
.v2 .plan-card-desc,
.v2 .step-item p,
.v2 .lead { hyphens: none; word-break: normal; overflow-wrap: normal; }


/* ─── OWNER DEFAULT: legible text on filled panels ─────────────────
   Any panel with a dark or saturated fill carries light text, and the
   reverse. .anchor-bar sets colour on the container, but a nested <p>
   picks up the global paragraph colour instead of inheriting it, which
   left the text almost invisible on the blue fill.                    */

.v2 .anchor-bar,
.v2 .anchor-bar p,
.v2 .anchor-bar span,
.v2 .anchor-bar strong {
    color: var(--white);
}
.v2 .anchor-bar p {
    margin: 0;
    line-height: 1.7;
    text-align: center;
    max-width: 62em;
    margin-left: auto;
    margin-right: auto;
}
.v2 .commit-bar,
.v2 .commit-bar .label,
.v2 .commit-bar .text { color: var(--white); }


/* ─── UTILITY: visually hidden, still read by screen readers ───────  */

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}


/* ═══════════════════════════════════════════════════════════════════
   INNER-PAGE COMPONENTS
   Added for the 8 inner pages. Same custom properties, same type scale
   and same spacing scale as the homepage. No new colours, no new fonts.
   ═══════════════════════════════════════════════════════════════════ */


/* ─── PAGE HERO: inner-page opening block ──────────────────────────
   OWNER DEFAULT D5: the lead paragraph must span the SAME width as the
   h1 above it. The base rule left the lead at 720px under a 900px
   heading, so its right edge stopped short of the title's.            */

.v2 .page-hero .lead {
    max-width: 900px;
    font-size: 1.125rem;
    line-height: 1.8;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
    -webkit-hyphens: none;
    word-break: normal;
    overflow-wrap: normal;
}

/* A one-line standalone lead should not be stretched by justification */
.v2 .page-hero .lead.lead-short { text-align: left; }

.v2 .page-hero .hero-cta { margin-top: var(--s-8); }

/* CONTRAST + CONSISTENCY: the homepage hero recolours its corner stamps
   to the deep blue (8.82:1). The page-hero rules only repositioned them,
   so they kept the pale grey default and measured 2.95:1 on the pale
   gradient. Match the homepage treatment. */
.v2 .page-hero .v2-stamp--abs.v2-stamp--tl,
.v2 .page-hero .v2-stamp--abs.v2-stamp--tr { color: var(--teal-deep); }

/* Quiet eligibility note under a hero action row */
.v2 .page-note {
    margin-top: var(--s-6);
    max-width: 900px;
    font-size: 0.875rem;
    line-height: 1.8;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
    -webkit-hyphens: none;
}


/* ─── FIGURE FRAME: labelled empty placeholder ─────────────────────
   Used where a real screenshot does not exist yet. It must read as a
   deliberate reserved slot, never as a broken image.                  */

.v2 .fig-frame {
    position: relative;
    margin-top: var(--s-10);
    background: var(--surface);
    border: 1px dashed var(--border-soft);
    border-radius: var(--radius-md);
    aspect-ratio: 16 / 9;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--s-8);
}
.v2 .fig-frame--wide { aspect-ratio: 21 / 9; }
.v2 .fig-frame-label {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--gray);
    text-align: center;
    line-height: 1.9;
    max-width: 34em;
}
.v2 .fig-frame-label span {
    display: block;
    color: var(--teal-deep);
    margin-bottom: var(--s-2);
}
@media (max-width: 700px) {
    .v2 .fig-frame { aspect-ratio: 4 / 3; padding: var(--s-6); }
    .v2 .fig-frame--wide { aspect-ratio: 4 / 3; }
}


/* ─── PLACEHOLDER VALUE: visibly non-final ─────────────────────────
   Any unconfirmed price or fact renders in this treatment so it can
   never be mistaken for a real published value.                       */

.v2 .placeholder-val {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--gray);
    background: var(--surface);
    border: 1px dashed var(--border-soft);
    border-radius: 3px;
    padding: var(--s-1) var(--s-3);
    line-height: 1.6;
    white-space: nowrap;
}


/* ─── NOTICE LIST: important-information bullets ───────────────────  */

.v2 .notice-list {
    list-style: none;
    margin-top: var(--s-6);
    display: grid;
    gap: var(--s-4);
}
.v2 .notice-list li {
    position: relative;
    padding-left: var(--s-8);
    font-size: 1rem;
    line-height: 1.8;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
    -webkit-hyphens: none;
}
.v2 .notice-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.72em;
    width: 14px;
    height: 1px;
    background: var(--teal);
}


/* ─── ACTIVATION STEPS: vertical numbered rail ─────────────────────
   Ported from the original how-it-works page and reduced to the parts
   these pages use. Connector rail + circular step numbers.            */

.v2 .activation-steps {
    display: flex;
    flex-direction: column;
    margin-top: var(--s-12);
    position: relative;
}
.v2 .activation-steps::before {
    content: "";
    position: absolute;
    top: var(--s-10);
    bottom: var(--s-10);
    left: 31px;
    width: 2px;
    background: var(--border-soft);
    z-index: 0;
    pointer-events: none;
}
.v2 .activation-step {
    display: grid;
    grid-template-columns: 64px 1fr;
    gap: var(--s-8);
    padding: var(--s-10) 0;
    border-bottom: 1px solid var(--border-hairline);
    position: relative;
    align-items: start;
}
.v2 .activation-step:first-child { border-top: 1px solid var(--border-hairline); }

.v2 .step-circle {
    width: 64px;
    height: 64px;
    background: var(--teal);
    color: var(--white);
    font-family: var(--font-mono);
    font-size: 1rem;
    font-weight: 500;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    flex-shrink: 0;
    position: relative;
    z-index: 1;
}
.v2 .step-content h3 {
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--dark);
    margin-bottom: var(--s-4);
    line-height: 1.2;
}
/* A step that carries no body line should not leave a trailing gap */
.v2 .step-content h3:last-child { margin-bottom: 0; }
.v2 .step-content p {
    font-size: 1.0625rem;
    line-height: 1.8;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
    -webkit-hyphens: none;
    word-break: normal;
    overflow-wrap: normal;
}
@media (max-width: 640px) {
    .v2 .activation-step { grid-template-columns: 48px 1fr; gap: var(--s-5); padding: var(--s-8) 0; }
    .v2 .step-circle { width: 48px; height: 48px; font-size: 0.875rem; }
    .v2 .activation-steps::before { left: 23px; }
    .v2 .step-content h3 { font-size: 1.25rem; }
    /* Narrow-column escape removed - owner precedence ruling 2026-08-07.
       The mirror rule outranks gap width: see the policy block at the
       end of this file. */
}


/* ─── FAQ ACCORDION ────────────────────────────────────────────────
   Ported from the original faq.html local block. Promoted here so
   every page that needs an accordion shares one definition.           */

.v2 .faq-group { margin-top: var(--s-12); }
.v2 .faq-group:first-of-type { margin-top: var(--s-10); }

/* Rendered as an <h3> so screen-reader users can jump between groups.
   The class overrides every heading default, so it looks identical. */
.v2 .faq-group-label {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.4;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--teal-deep);
    margin-bottom: var(--s-6);
    padding-bottom: var(--s-3);
    border-bottom: 1px solid var(--teal);
    display: inline-block;
}

.v2 .faq-item { border-bottom: 1px solid var(--border-hairline); }
.v2 .faq-item:first-of-type { border-top: 1px solid var(--border-hairline); }

.v2 .faq-question {
    width: 100%;
    text-align: left;
    padding: var(--s-6) 0;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--s-6);
    cursor: pointer;
    background: none;
    border: none;
    font-family: var(--font-display);
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--dark);
    line-height: 1.4;
    transition: color var(--t-fast);
}
.v2 .faq-question:hover,
.v2 .faq-question.open { color: var(--teal); }
.v2 .faq-question:focus-visible {
    outline: 2px solid var(--teal);
    outline-offset: 3px;
}

.v2 .faq-icon {
    position: relative;
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    border: 1.5px solid currentColor;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 2px;
    transition: background var(--t-fast), border-color var(--t-fast);
}
.v2 .faq-icon::before,
.v2 .faq-icon::after {
    content: "";
    position: absolute;
    background: currentColor;
}
.v2 .faq-icon::before { width: 10px; height: 1.5px; }
.v2 .faq-icon::after  { width: 1.5px; height: 10px; transition: transform var(--t-base), opacity var(--t-fast); }

.v2 .faq-question.open .faq-icon { background: var(--teal); border-color: var(--teal); }
.v2 .faq-question.open .faq-icon::before,
.v2 .faq-question.open .faq-icon::after { background: var(--white); }
.v2 .faq-question.open .faq-icon::after { transform: rotate(90deg); opacity: 0; }

.v2 .faq-answer { display: none; padding-bottom: var(--s-8); }
.v2 .faq-answer.open { display: block; }

/* OWNER DEFAULT D7: the answer column is narrower than the page, so it
   gets the loose 1.8 line-height and a clear gap from its question. */
.v2 .faq-answer p {
    font-size: 1rem;
    line-height: 1.8;
    color: var(--gray);
    margin-bottom: var(--s-4);
    max-width: 62em;
    text-align: justify;
    hyphens: none;
    -webkit-hyphens: none;
    word-break: normal;
    overflow-wrap: normal;
}
.v2 .faq-answer p:last-child { margin-bottom: 0; }
.v2 .faq-answer strong { color: var(--dark); font-weight: 600; }

.v2 .faq-answer ul {
    margin: var(--s-3) 0 var(--s-4) var(--s-6);
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
}
.v2 .faq-answer ul li {
    font-size: 1rem;
    line-height: 1.7;
    color: var(--gray);
}
.v2 .faq-answer ul li::marker { color: var(--teal); }

@media (max-width: 768px) {
    .v2 .faq-question { font-size: 1rem; }
}


/* ─── PLAN DETAIL CARDS ────────────────────────────────────────────  */

.v2 .plan-detail-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s-8);
    margin-top: var(--s-10);
}
.v2 .plan-detail {
    position: relative;
    background: var(--white);
    border: 1px solid var(--border-soft);
    border-top: 3px solid var(--teal);
    border-radius: var(--radius-md);
    padding: var(--s-8);
    display: flex;
    flex-direction: column;
}
.v2 .plan-detail-name {
    font-family: var(--font-display);
    font-size: 1.375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--dark);
}
/* OWNER DEFAULT D2: equal heading + tagline heights so every feature
   list in the row starts on the same line. */
.v2 .plan-detail-for {
    font-size: 0.9375rem;
    line-height: 1.8;
    color: var(--gray);
    margin-top: var(--s-3);
    min-height: 3.6em;
}
.v2 .plan-detail-price {
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--teal-deep);
    border-top: 1px solid var(--border-hairline);
    border-bottom: 1px solid var(--border-hairline);
    padding: var(--s-4) 0;
    margin-bottom: var(--s-5);
}
.v2 .feature-list {
    list-style: none;
    display: grid;
    gap: var(--s-3);
}
.v2 .feature-list li {
    position: relative;
    padding-left: var(--s-6);
    font-size: 0.9375rem;
    line-height: 1.8;
    color: var(--gray);
}
.v2 .feature-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.68em;
    width: 7px;
    height: 7px;
    border-radius: 2px;
    background: var(--teal);
    transform: rotate(45deg);
}
@media (max-width: 900px) {
    .v2 .plan-detail-row { grid-template-columns: 1fr; }
    .v2 .plan-detail-for { min-height: 0; }
}


/* ─── ENQUIRY ROUTE CARDS: four across ─────────────────────────────  */

.v2 .contact-cards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* OWNER DEFAULT D2: route names reserve equal height so every
   description below them starts on the same line. */
.v2 .contact-card .value { min-height: 2.4em; }
.v2 .contact-card .desc {
    line-height: 1.8;
    text-align: justify;
    hyphens: none;
    -webkit-hyphens: none;
}
.v2 .contact-card .placeholder-val { margin-top: var(--s-4); }
@media (max-width: 1100px) {
    .v2 .contact-cards--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
    .v2 .contact-cards--4 { grid-template-columns: 1fr; }
    .v2 .contact-card .value { min-height: 0; }
}


/* ─── FORMS: preview only, never submitted ─────────────────────────
   There is no backend behind this build. The form states that plainly
   before it is touched, and again on submit - it never fakes success. */

.v2 .form-block {
    position: relative;
    margin-top: var(--s-8);
    background: var(--surface);
    border: 1px solid var(--border-soft);
    border-top: 3px solid var(--teal);
    border-radius: var(--radius-md);
    padding: var(--s-8);
}
.v2 .form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-5) var(--s-8);
}
.v2 .form-grid--single { grid-template-columns: 1fr; max-width: 520px; }
.v2 .field--full { grid-column: 1 / -1; }

.v2 .field label {
    display: block;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--teal-deep);
    margin-bottom: var(--s-2);
}
.v2 .field input,
.v2 .field select,
.v2 .field textarea {
    width: 100%;
    font-family: var(--font-body);
    font-size: 0.9375rem;
    color: var(--dark);
    background: var(--white);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    padding: var(--s-3) var(--s-4);
    line-height: 1.6;
    transition: border-color var(--t-fast);
}
.v2 .field textarea { min-height: 132px; resize: vertical; }
.v2 .field input:focus,
.v2 .field select:focus,
.v2 .field textarea:focus {
    outline: 2px solid var(--teal);
    outline-offset: 1px;
    border-color: var(--teal);
}
/* CONTRAST: the pale grey placeholder colour measures 2.95:1 on white,
   which is below the 4.5:1 minimum. Placeholders here carry real
   guidance ("you@example.com"), so they use the body grey (5.86:1). */
.v2 .field input::placeholder,
.v2 .field textarea::placeholder { color: var(--gray); opacity: 1; }

.v2 .form-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-4);
    margin-top: var(--s-6);
}
.v2 .form-preview-note {
    margin-top: var(--s-5);
    padding-top: var(--s-5);
    border-top: 1px solid var(--border-hairline);
    font-size: 0.875rem;
    line-height: 1.8;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
    -webkit-hyphens: none;
}
.v2 .form-status {
    margin-top: var(--s-4);
    padding: var(--s-4) var(--s-5);
    background: var(--teal-pale);
    border-left: 3px solid var(--teal);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font-size: 0.9375rem;
    line-height: 1.8;
    color: var(--teal-deep);
}
.v2 .form-status[hidden] { display: none; }

@media (max-width: 700px) {
    .v2 .form-grid { grid-template-columns: 1fr; }
    .v2 .form-block { padding: var(--s-6); }
}


/* ─── FOOTER: five groups + social row ─────────────────────────────
   Four link columns kept; social moves into the brand column so the
   grid does not need a fifth narrow track.                             */

.v2 .footer-social {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-3);
    margin-top: var(--s-4);
}
.v2 .footer-social a {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--gray-lite);
    text-decoration: none;
    transition: color var(--t-fast);
}
.v2 .footer-social a:hover { color: var(--teal); }


/* ─── MEMBERSHIP: two levels side by side ──────────────────────────
   Replaces the three-plan row. Two columns give each membership room
   for a longer feature list without the cramped feel of three.        */

.v2 .membership-row {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-8);
    margin-top: var(--s-10);
}
.v2 .plan-preview--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* The paid level carries a quiet emphasis, using existing variables only */
.v2 .plan-detail--paid { border-color: var(--teal); }

@media (max-width: 900px) {
    .v2 .membership-row,
    .v2 .plan-preview--two { grid-template-columns: 1fr; }
}


/* ─── NAV DROPDOWN: Products ───────────────────────────────────────
   Owner-approved design 2026-08-05: closed by default, opens on CLICK
   only. The panel hangs from the bar's bottom edge, centred under the
   word Products - square top corners so it reads as attached to the
   bar, rounded bottom corners. Slightly wider than the trigger word.
   Closes on second click, Escape, or any click outside.               */

.v2 .nav-menu .has-drop { position: relative; }

.v2 .nav-menu .drop-trigger {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    white-space: nowrap;
    cursor: pointer;
    background: none;
    border: none;
    font: inherit;
    color: inherit;
    padding: 0;
}
.v2 .drop-caret {
    width: 0; height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid currentColor;
    opacity: 0.6;
    transition: transform var(--t-fast);
}
.v2 .has-drop.open .drop-caret { transform: rotate(180deg); }

.v2 .drop-menu {
    display: none;
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-top: 21px;              /* reaches the bar's bottom edge */
    min-width: 150px;
    background: var(--white);
    border: 1px solid var(--border-soft);
    border-top: none;
    border-radius: 0 0 10px 10px;
    padding: var(--s-1);
    list-style: none;
    box-shadow: var(--shadow-card);
    z-index: 60;
}
.v2 .has-drop.open .drop-menu { display: block; }

.v2 .drop-menu li { margin: 0; }
.v2 .drop-menu a {
    display: block;
    padding: var(--s-2) var(--s-3);
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--dark);
    text-decoration: none;
    white-space: nowrap;
    text-align: left;
    transition: background var(--t-fast), color var(--t-fast);
}
.v2 .drop-menu a:hover { background: var(--teal-pale); color: var(--teal-deep); }

/* Mobile: the dropdown flattens into a labelled group */
.v2 .nav-mobile-label {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--gray-lite);
    padding: var(--s-4) 0 var(--s-1);
}


/* ─── PILLAR ROW: four across ──────────────────────────────────────  */

.v2 .pillar-row--four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) {
    .v2 .pillar-row--four { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
    .v2 .pillar-row--four { grid-template-columns: 1fr; }
}

/* The forward-looking card reads as open-ended, not as a live product */
.v2 .stat-card--future {
    background: transparent;
    border-style: dashed;
}


/* ─── MODEL NOTE: quiet subtext under a capability set ─────────────  */

.v2 .model-note {
    margin-top: var(--s-6);
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.02em;
    color: var(--gray-lite);
    text-align: left;
}


/* ─── BENEFIT FIGURE: the one published percentage ─────────────────
   Owner decision 2026-08-05. The figure is stated, but the qualifier
   sits with it and is not visually demotable - a maximum with no
   conditions attached is the claim a regulator asks you to prove.    */

.v2 .benefit-figure {
    margin-top: var(--s-8);
    padding: var(--s-6) var(--s-8);
    background: var(--teal-pale);
    border: 1px solid var(--bcd);
    border-left: 4px solid var(--teal);
    border-radius: var(--radius-md);
}
.v2 .benefit-figure-value {
    display: block;
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 3.4vw, 2.5rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.1;
    color: var(--teal-deep);
}
.v2 .benefit-figure-label {
    display: block;
    font-size: 1rem;
    font-weight: 500;
    color: var(--dark);
    margin-top: var(--s-2);
}
.v2 .benefit-figure-note {
    margin-top: var(--s-4);
    padding-top: var(--s-4);
    border-top: 1px solid var(--bcd);
    font-size: 0.875rem;
    line-height: 1.8;
    color: var(--gray);
    text-align: justify;
    hyphens: none;
}


/* ─── PILLAR STRIP: "More products ahead" ──────────────────────────
   Owner-approved 2026-08-05: the forward-looking item is not a fourth
   card. It is one slim full-width dashed strip under the three product
   cards, text on a single line, no separator between title and text.  */

.v2 .pillar-strip {
    margin-top: var(--s-5);
    border: 1.5px dashed var(--bcd);
    border-radius: var(--radius-md);
    padding: var(--s-4) var(--s-6);
    display: flex;
    align-items: baseline;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-4);
    text-align: center;
}
.v2 .pillar-strip-title {
    font-family: var(--font-display);
    font-size: 1.0625rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--dark);
    white-space: nowrap;
}
.v2 .pillar-strip-text {
    font-size: 0.9375rem;
    line-height: 1.7;
    color: var(--gray);
}


/* ─── MEET NEXT AI: illustration beside the copy ───────────────────
   Matches the proportions of the live site's story section: a narrow
   text column and a large illustration filling the remaining width.
   The text column is capped at 560px, roughly 37% narrower than the
   full-width column it replaced, and the graphic takes whatever is
   left (about 575px in a 1200px container).

   Mobile is deliberately unchanged from the approved version: below
   1025px the grid collapses to one column and DOM order gives heading,
   intro, graphic, points, button, with the points in two columns down
   to 700px exactly as before.                                          */

.v2 .ai-split {
    display: grid;
    grid-template-columns: minmax(0, 560px) minmax(0, 1fr);
    grid-template-areas:
        "intro art"
        "body  art";
    column-gap: var(--s-16);
    row-gap: var(--s-8);
    align-items: start;
    margin-top: var(--s-10);
}
.v2 .ai-split-intro { grid-area: intro; }
.v2 .ai-split-body  { grid-area: body; }
.v2 .ai-illustration {
    grid-area: art;
    align-self: center;
}
.v2 .ai-illustration img {
    width: 100%;
    height: auto;
    display: block;
}
.v2 .ai-split .reason-grid { margin-top: 0; }
.v2 .ai-split-intro .section-intro { margin-bottom: 0; }

/* Mirrored variant: illustration on the LEFT, copy on the right. Same
   proportions as the standard split, columns simply swapped. Mobile is
   untouched because the mobile rules re-declare grid-template-areas. */
.v2 .ai-split--mirror {
    grid-template-columns: minmax(0, 1fr) minmax(0, 560px);
    grid-template-areas:
        "art intro"
        "art body";
}

/* Desktop only: the points run as a single stacked list so the text
   column stays narrow and the illustration keeps its width. */
@media (min-width: 1025px) {
    .v2 .ai-split .reason-grid {
        grid-template-columns: 1fr;
        gap: var(--s-3);
    }

    /* The two source graphics have different proportions (1040x754 and
       1040x943), so at equal width the electricity one rendered about
       110px taller and the sections read as mismatched. Both art boxes
       are pinned to the same ratio and each image is fitted inside it,
       so the two illustrations render at identical height with no
       distortion and nothing cropped. Desktop only: the mobile rules
       below 1025px are left exactly as approved. */
    .v2 .ai-split .ai-illustration img {
        aspect-ratio: 1040 / 754;
        object-fit: contain;
    }
}

/* Single column below 1025px: heading, intro, graphic, then the points */
@media (max-width: 1024px) {
    .v2 .ai-split {
        grid-template-columns: 1fr;
        grid-template-areas: "intro" "art" "body";
        row-gap: var(--s-10);
    }
    .v2 .ai-illustration {
        max-width: 420px;
        margin-left: auto;
        margin-right: auto;
    }
}

/* Phones and tablets, section 04 only: the graphic sits between the
   heading and the paragraph rather than after the paragraph. The
   heading, eyebrow and paragraph normally travel together inside one
   wrapper, so the wrapper is flattened with display:contents and its
   three children become rows in their own right. That is what lets the
   graphic slot in between them.

   Row spacing is handed to the individual rows so the existing rhythm
   is kept exactly: 20px under the heading and 40px around the graphic,
   the same figures the approved layout already used. Section 03 keeps
   its approved order, and nothing above 1024px is affected. */
@media (max-width: 1024px) {
    .v2 .ai-split--mirror {
        grid-template-areas: "eyebrow" "head" "art" "para" "body";
        row-gap: 0;
    }
    .v2 .ai-split--mirror > .ai-split-intro { display: contents; }

    .v2 .ai-split--mirror .eyebrow {
        grid-area: eyebrow;
        justify-self: start;
    }
    .v2 .ai-split--mirror .display-lg { grid-area: head; }
    .v2 .ai-split--mirror .ai-illustration {
        grid-area: art;
        margin-top: var(--s-10);
    }
    .v2 .ai-split--mirror .section-intro {
        grid-area: para;
        margin-top: var(--s-10);
    }
    .v2 .ai-split--mirror .ai-split-body {
        grid-area: body;
        margin-top: var(--s-10);
    }
}


/* ─── FAQ: always-visible protective statements ───────────────────
   The accordion shows one answer at a time, so anything opened by
   default closes the moment a visitor clicks another question. The
   two protective answers a customer most needs to see are therefore
   not accordions at all: statement plus answer, always rendered.    */

.v2 .faq-statement {
    padding: var(--s-6) 0 0;
    font-family: var(--font-display);
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--dark);
    line-height: 1.4;
}
.v2 .faq-answer--static {
    display: block;
    padding-top: var(--s-3);
}

/* Non-actionable button: an action that is announced but not yet live.
   Looks like a button, is not clickable, and never pretends to work.  */
.v2 .btn-disabled {
    background: var(--surface);
    color: var(--gray);
    border: 1px dashed var(--bcd);
    cursor: default;
    pointer-events: none;
}


/* ─── HERO STACK: the occluded back card ──────────────────────────
   The front cards cover the lower half of the back card, which cut
   its list items mid-word ("Merc...", "Mem..."). The back card now
   carries only a header and a status line, both of which sit above
   the overlap, so the stack reads as layered rather than broken.   */

.v2 .layer-card--3 .layer-card-body { padding-bottom: 0; }


/* ═══════════════════════════════════════════════════════════════════
   AUDIT FIXES - 2026-08-06 (revision 2)
   Revision 1 was verified by an independent design review and four of
   its rules did not do what they claimed. Each block below names both
   the original finding and why the first attempt missed.
   ═══════════════════════════════════════════════════════════════════ */


/* ─── FINDING 23: justified text in columns too narrow to carry it ──
   Justification stretched word gaps to 9.7x a normal space. Revision 1
   only covered phones and was outranked on inner-page hero paragraphs
   by a more specific existing rule, so five of eight pages stayed
   broken, and narrow DESKTOP columns were never addressed at all
   (contact cards measured 8.99x in a 225px column).

   Revision 2 answered that by never justifying card text at any width.
   Owner ruling, 2026-08-07: that blanket was too broad - the standing
   default is that paragraphs in text boxes ARE justified (Dex owner
   default D1, adopted 2026-08-04). The narrow-column escape in the
   approved change plan applies per column, per breakpoint - not to
   "cards" as a category. So: box paragraphs justify on desktop, where
   their columns are wide enough to absorb the slack; everything stays
   left below 1025px, matching the site-wide mobile pattern.
   Hyphenation stays off throughout - justification is whole-word
   spacing only.                                                      */

/* ─── MIRROR RULE: ONE ALIGNMENT PER BLOCK, ALL WIDTHS ────────────
   Owner precedence ruling, final, 2026-08-07. Supersedes every
   justification block above, including the measured revision 3.

   THE RULE: every paragraph that is justified on desktop is
   justified at every width, phones included. The mirror rule
   outranks the 2x word-gap threshold wherever the two conflict.
   The threshold is REPORT-ONLY from here on - it may be measured
   and recorded, never acted on, and never used to excuse a block.

   There is therefore no breakpoint in this block, by design. No
   media query may reintroduce one for text-align. The four
   narrow-column escapes that used to live further up this file
   (step content at 640px, FAQ answers at 768px, contact cards at
   640px, form note at 700px) were deleted under this ruling, not
   overridden - an override would have left them to be "fixed" back
   in later by someone reading them as live rules.

   Accepted and on the record: at 390px the worst gaps reach roughly
   15x a normal space (about 62px) in the 294px pillar card column,
   and the median paragraph runs near 3.7x. The owner has seen these
   figures and accepts them. Do not left-align anything to soften
   them. Hyphenation stays off - whole-word spacing only, so no word
   is ever broken across a line.

   Not paragraphs, so not covered by the ruling: .reason-item and
   .notice-list li are bullet labels and .hero-footnote is a single
   footnote line. They were left-aligned on desktop, so under the
   mirror rule they stay left-aligned at every width.              */

.v2 .section-intro,
.v2 .ai-split .section-intro,
.v2 .section > .container > .fade-in > .section-intro,
.v2 .page-note,
.v2 .page-hero .page-note,
.v2 .anchor-bar p,
.v2 .faq-answer p,
.v2 .lead,
.v2 .page-hero .lead,
.v2 .page-hero .lead.lead-short,
.v2 .split p.lead,
.v2 .split p.lead.text-italic,
.v2 .stat-desc,
.v2 .stat-card--pillar .stat-desc,
.v2 .plan-card-desc,
.v2 .plan-detail p,
.v2 .plan-detail li,
.v2 .benefit-figure p,
.v2 .contact-card .desc,
.v2 .step-item p,
.v2 .step-content p,
.v2 .model-note,
.v2 .form-preview-note {
    text-align: justify;
    hyphens: none;
    -webkit-hyphens: none;
    word-break: normal;
    overflow-wrap: normal;
}

/* Bullet labels and the footnote line: left at every width, which is
   what they already were on desktop. Mirror rule satisfied. */
.v2 .reason-item,
.v2 .notice-list li,
.v2 .hero-footnote {
    text-align: left;
    hyphens: none;
    -webkit-hyphens: none;
}


/* ─── FINDING 25: desktop text spans the full section width (C2.1)
   History: lines originally ran to 133 characters; revision 1 capped
   the paragraph alone and broke D5; revision 2 capped heading and
   paragraph together at 34rem (544px rendered, 59-68 characters);
   revision 3 widened the shared cap to 47.5rem (760px, 85-96
   characters). The owner rejected both capped revisions on sight:
   inside a 1232px container whose anchor bars, card grids and rules
   all run edge to edge, ANY narrower prose column reads as sentences
   cut halfway across the screen, with a dead area on the right.

   Owner ruling, 2026-08-07: alignment with the section outranks the
   character-count target. Heading, intro and note therefore span
   exactly the container width, level with every other full-width
   element - checklist C2.1. D5 holds trivially because heading and
   paragraph now share the same edges by construction. The explicit
   max-width: none also neutralises .page-note's base 900px cap, which
   would otherwise leave a note narrower than its heading on desktop.

   Headings keep balanced line-wrapping: between 1025px and about
   1300px the container is narrower than several headings' one-line
   width, and greedy filling drops a lone word onto the second line
   ("Grow With the NEXT / Ecosystem"). balance redistributes existing
   break points only - words are never split, so the no-hyphenation
   rule is unaffected; unsupported browsers just wrap greedily.

   Applies to full-width sections only. The two approved split
   sections run their copy inside .ai-split, not as a direct child of
   .fade-in, so the child combinator leaves their column untouched.  */

@media (min-width: 1025px) {
    .v2 .section > .container > .fade-in > .display-lg,
    .v2 .section > .container > .fade-in > .section-intro,
    .v2 .section > .container > .fade-in > .page-note {
        max-width: none;
    }

    .v2 .section > .container > .fade-in > .display-lg {
        text-wrap: balance;
    }
}


/* ─── FINDING 25b: reason lists read as a pair, not as two outer edges
   .reason-grid inherited the full 1232px container, so its two 600px
   tracks pushed the columns apart: on the homepage NEXT Credits list
   the left column's text ended at 391px and the right column began at
   736px, leaving 345px of dead space between them. Measured across the
   six full-width lists the gap ran 302-458px.

   Owner instruction: these lists sit close together as a readable
   pair, not spread to the outer edges - so unlike the prose above
   (FINDING 25), the grid keeps a 47.5rem cap. Every bullet fits its
   364px column on a single line, so nothing wraps. Track width and
   gap are still derived - two equal tracks separated by the existing
   --s-8 - so no new spacing value is introduced. Scoped with the same
   child combinator, which excludes the approved .ai-split lists;
   those are already forced to a single column above 1025px.        */

@media (min-width: 1025px) {
    .v2 .section > .container > .fade-in > .reason-grid {
        max-width: 47.5rem;
    }
}


/* ─── FINDING 24: card rows sharing a body baseline ────────────────
   A wrapping heading pushed its own card body 12 to 17px below its
   neighbours. Revision 1 reserved 2.6em, but the headings inherit a
   loose line-height, so two lines actually occupy about 3.2em and the
   reservation fell short. Line-height is now stated explicitly, which
   makes the reservation deterministic rather than inherited.        */

.v2 .stat-card--pillar .stat-title,
.v2 .plan-detail-name,
.v2 .plan-card-name,
.v2 .contact-card .value {
    line-height: 1.3;
    min-height: 2.6em;
}

/* Contact cards additionally align their footer pill across the row. */
.v2 .contact-card { display: flex; flex-direction: column; }
.v2 .contact-card .desc { flex: 1 1 auto; }

@media (max-width: 900px) {
    .v2 .stat-card--pillar .stat-title,
    .v2 .plan-detail-name,
    .v2 .plan-card-name,
    .v2 .contact-card .value { min-height: 0; }
}


/* ─── FINDING 26: text contrast, corrected ─────────────────────────
   Three styles measured 2.95:1 on white. Revision 1 darkened the
   shared --gray-lite token, which fixed those three and simultaneously
   dropped the footer from 4.9:1 to 2.57:1, because the same token is
   used on the dark footer panel. Darkening text on a dark fill makes
   it worse. That is owner default D6: check the RENDERED result.

   The token is therefore darkened only where the surface is light,
   and the footer keeps a light value of its own.                     */

.v2 { --gray-lite: #5B6875; }

.v2 footer,
.v2 .footer-brand-tag,
.v2 .footer-disclaimer,
.v2 .footer-bottom,
.v2 footer ul a,
.v2 .footer-social a { --gray-lite: #B9C4CE; }

.v2 .footer-brand-tag,
.v2 .footer-disclaimer,
.v2 .footer-bottom,
.v2 footer ul a,
.v2 .footer-social a { color: #B9C4CE; }


/* ─── FINDING 27/28: current-page marker on the Products trigger ───
   The three product pages carried the marker in their markup but
   nothing styled it, so with the menu closed those pages showed no
   current-page indicator anywhere. Matches the .active treatment on
   ordinary nav links.                                                */

.v2 .nav-menu .drop-trigger--active { color: var(--teal); }
.v2 .nav-menu .has-drop { position: relative; }
.v2 .nav-menu .drop-trigger--active::after {
    content: "";
    position: absolute;
    bottom: -6px;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--teal);
}


/* ─── FINDING 30: tap targets below 44px ──────────────────────────
   Verified passing at 44px. Retained unchanged.                     */

.v2 .nav-toggle {
    min-width: 44px;
    min-height: 44px;
    align-items: center;
    justify-content: center;
}
.v2 .nav-mobile ul li a {
    min-height: 44px;
    display: flex;
    align-items: center;
}
.v2 footer ul li a,
.v2 .footer-social a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}


/* ─── FINDING 35: hero stack back card ────────────────────────────  */

.v2 .layer-card--3 .layer-card-body { padding-bottom: 0; }
