/* =============================================================================
   NETZERO AQUA — v2 DESIGN SYSTEM
   =============================================================================
   Built to the Home Page Development Specification v1.0.

   The guiding sentence from that spec, which every decision below answers to:

       "Do not interpret this as a conventional aquaculture corporate website.
        Netzero AQUA should look and behave like a premium climate-tech /
        data-intelligence platform serving the aquaculture industry."

   SCOPE
   -----
   This file owns tokens, typography, layout, buttons, cards, the global
   header and the global footer. Page-specific sections live in their own
   stylesheet (css/na-home.css and so on). The header and footer are defined
   ONCE, here, because the spec is explicit that they must not be redesigned
   per page.

   PREFIX
   ------
   Everything is namespaced `na-`. The logged-in app shells use `nz-` and
   `shell-`; the two systems share a repository and must never share a
   selector. Loading this file cannot change how dashboard.html looks.

   COLOUR, MEASURED
   ----------------
   The brand is blue #004AF7 on navy #00243C, both sampled from
   img/logo/logo-lockup.png. The ratios below were computed, not estimated.

       #FFFFFF on #00243C   →  15.94:1   body text on the brand navy
       #4C82FF on #00243C   →   4.51:1   the lifted blue on navy: AA, the
                                         darkest the sampled blue goes and
                                         still clears 4.5:1
       #4C82FF on #FFFFFF   →   3.42:1   FAILS AA for body text — dark grounds only
       #004AF7 on #FFFFFF   →   6.32:1   the blue that IS safe as text on white
       #FFFFFF on #004AF7   →   6.32:1   white on a filled primary button
       #004AF7 on #00243C   →   2.52:1   fails even as a boundary — never here
       #3BD304 on #00243C   →   7.97:1   the nav underline, on the bar
       #3BD304 on #FFFFFF   →   2.00:1   FAILS everything — never on light
       #0F172A on #F4F7FC   →  15.3:1    body text on the light ground

   THE RULE THAT MATTERS
   ---------------------
   One brand blue, two working values, and they are not interchangeable.

   #004AF7 is the brand blue, sampled from the ΛQUΛ wordmark. It is a
   LIGHT-GROUND colour: 6.32:1 on white and 5.89:1 on the tinted page, which
   makes it small text, a fill, a border and the primary button — but only
   2.52:1 on the navy, which is below even the 3:1 floor for a UI boundary.
   Put it on a dark section as text and it fails.

   #4C82FF is that blue lifted until it carries on navy, at 4.51:1 — same hue
   (222°), raised in lightness. It is the dark-ground value: eyebrows, figures,
   icons, rules, any text on a dark section. On white it measures 3.42:1 and
   fails body text, so it never appears there.

   It was #80A6FF (6.69:1) until it was pulled back toward the wordmark. 4.51:1
   is AA and no more — there is no headroom left. If anything on a dark ground
   needs to be lighter for legibility, lift THAT element, do not lift this
   token: every step toward #004AF7 from here drops below AA.

   Sending either one to the other's ground is the mistake this note exists
   to prevent.

   WHY BLUE
   --------
   The highlight was lime through the first build. It is #004AF7 now: the
   product is about water, and the mark is AQUA. The token names moved with
   the values — a token called --na-lime holding a blue is a trap for the next
   person to edit this file.

   That blue was #0462EE for one build — chosen by eye, before the current
   lockup existed. It is now #004AF7, sampled straight from the ΛQUΛ wordmark.
   The two are close enough that the change reads as a sharpening rather than
   a rebrand, and the sampled one is the better colour on paper as well:
   6.32:1 on white against the old 5.27:1.

   The one green that stays is the status green, --na-ok. "Optimal" sits in a
   row with watch amber, high-risk orange and critical red; recolouring it
   blue would break a traffic light that farmers read at a glance.

   WHY THERE IS ALSO A GREEN (added later)
   ---------------------------------------
   The logo ring green came back for ONE element: the nav underline hairline.
   It is --na-lime, defined below beside the blues.

   This is not a reversal of the paragraph above. Blue is still the brand
   highlight and still owns every fill, ground, border, button, figure and
   section accent — the nav glide pill and the current-page wash included.
   Green is a 2px line and nothing more. If you are reaching for --na-lime for
   a background or a text colour, you are adding a second brand colour: use
   the blue.

   If you are adding a green here for any reason other than a pointer or
   current-page state, you are adding a second brand colour. Use the blue.
   ========================================================================== */

:root {
    /* ---- Brand. Sampled from img/logo/logo-lockup.png, same values the
            app shell uses in css/nz-palette.css. ---- */
    --na-dark:        #00243C;   /* the wordmark ground   */
    --na-dark-2:      #001830;   /* its darker shade      */
    --na-aqua:        #4C82FF;   /* #004AF7 lifted just enough for dark grounds */
    --na-blue:        #3874FF;   /* secondary, for data only */
    --na-light:       #F4F7FC;

    /* ---- Derived navies, from the same sampling ---- */
    --na-dark-3:      #002448;   /* raised surface on dark  */
    --na-dark-4:      #0A3A5C;   /* hover on a dark surface */
    --na-dark-line:   rgba(255, 255, 255, 0.10);
    --na-dark-line-2: rgba(76, 130, 255, 0.28);

    /* ---- Derived blues ----
            --na-aqua      fills, borders, icons, large figures, ANY text on navy
            --na-aqua-text small text on a light ground. Not interchangeable —
                           see the rule in the header. ---- */
    --na-aqua-deep:   #004AF7;   /* the brand blue: fills, buttons */
    --na-aqua-text:   #004AF7;   /* 6.32:1 on white, 5.89:1 on the page */
    --na-aqua-glow:   rgba(76, 130, 255, 0.16);
    --na-aqua-wash:   rgba(76, 130, 255, 0.06);
    --na-blue-deep:   #0039BF;

    /* ---- The underline green ----
            Sampled from the ring of the current lockup, img/logo/logo-lockup.png.
            The ring of the older logo3.png was #84D860, a muted lime; this
            one is considerably more saturated. The underline follows the mark
            that is actually on screen, so if the lockup is replaced again,
            re-sample it here rather than nudging by eye.

            It has exactly ONE use: the 2px hairline that grows under a nav
            link. Nothing else — no fills, no grounds, no hover text, no
            borders. Blue owns all of those.

            7.97:1 on the navy it sits on. It is 2.0:1 on white and fails AA
            at every size there, which is a second reason it stays a hairline
            on a dark bar and nothing else. ---- */
    --na-lime:        #3BD304;   /* nav underline only */

    /* ---- Light surfaces ---- */
    --na-page:        #F4F7FC;
    --na-surface:     #FFFFFF;
    --na-surface-2:   #EEF2F9;
    --na-line:        #E5EAF2;
    --na-line-2:      #CBD5E1;

    /* ---- Text ---- */
    --na-ink:         #0F172A;   /* 13.7:1 on --na-page */
    --na-ink-2:       #475569;   /* 7.1:1  — secondary  */
    /* v1's #64748B measures 4.76:1 on white — but this site's light ground is
       the tinted #F4F7FC, where it drops to 4.43 and fails AA for the small
       print that uses it (form hints, table headers, the placeholder notes).
       Two steps darker clears 4.5 on every surface actually in use. */
    --na-ink-3:       #5D6B80;   /* 5.04 page · 4.82 surface-2 · 5.41 white */
    --na-on-dark:     #FFFFFF;
    --na-on-dark-2:   rgba(255, 255, 255, 0.74);
    --na-on-dark-3:   rgba(255, 255, 255, 0.52);

    /* ---- Status. Pond and alert states, shared with the dashboards.
            Deliberately NOT the brand blue: a blue "optimal" badge beside a
            blue highlight reads as decoration rather than as state, and it
            would break the traffic light it sits in — optimal, watch, high
            risk, critical. These stay green / amber / orange / red. ---- */
    --na-ok:          #21925C;   /* 3.7:1 on the tinted page; #2FA96B measured 2.79 */
    --na-watch:       #E0A32E;
    --na-risk:        #E4703A;
    --na-critical:    #DC4A45;
    --na-nodata:      #7C8B8E;

    /* The same five, lifted for use as TEXT on a navy card. The base values
       are tuned for fills and dots and sit at 3.8–5.2:1 on #002448, which is
       under AA for the 11px status labels; these clear it. Fills keep the
       base values — only type uses these. */
    --na-ok-text:       #4FC98A;
    --na-watch-text:    #EDBB55;
    --na-risk-text:     #F08A5A;
    --na-critical-text: #F0736E;
    --na-nodata-text:   #9AA9AC;

    /* ---- Type ---- */
    --na-font-display: "Space Grotesk", "Inter", system-ui, -apple-system,
                       "Segoe UI", sans-serif;
    --na-font-body:    "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
    --na-font-mono:    "IBM Plex Mono", ui-monospace, "SF Mono", Menlo,
                       Consolas, monospace;

    /* A modular scale, 1.25, capped so a 60px headline does not become 90px
       on a 4K monitor. clamp() means no breakpoint owns the type. */
    --na-t-eyebrow: 0.75rem;
    --na-t-small:   0.875rem;
    --na-t-body:    1rem;
    --na-t-lead:    clamp(1.0625rem, 0.98rem + 0.4vw, 1.25rem);
    --na-t-h4:      clamp(1.125rem, 1.05rem + 0.35vw, 1.375rem);
    --na-t-h3:      clamp(1.375rem, 1.2rem + 0.75vw, 1.875rem);
    --na-t-h2:      clamp(1.875rem, 1.5rem + 1.7vw, 3rem);
    --na-t-h1:      clamp(2.375rem, 1.7rem + 3.1vw, 4.25rem);
    --na-t-display: clamp(2.75rem, 1.8rem + 4.2vw, 5.25rem);

    /* ---- Geometry ---- */
    --na-wrap:      1280px;   /* spec: 1200–1280 max content width */
    --na-wrap-tight: 1080px;
    --na-r:         16px;
    --na-r-sm:      10px;
    --na-r-lg:      24px;
    --na-r-pill:    999px;

    /* ---- Rhythm. One vertical unit for every section. ---- */
    --na-section:   clamp(4.5rem, 3rem + 6vw, 8rem);
    --na-gap:       clamp(1rem, 0.7rem + 1.2vw, 1.75rem);

    /* ---- Elevation. Tinted with the primary dark; pure black over a
            teal-dark palette reads as grey sludge. ---- */
    --na-shadow-sm: 0 1px 2px rgba(0, 36, 60, 0.06);
    --na-shadow:    0 6px 20px rgba(0, 36, 60, 0.08);
    --na-shadow-lg: 0 18px 48px rgba(0, 36, 60, 0.14);
    --na-shadow-xl: 0 32px 80px rgba(0, 36, 60, 0.22);
    --na-glow:      0 0 0 1px rgba(76, 130, 255, 0.30),
                    0 20px 60px rgba(76, 130, 255, 0.10);

    /* ---- Motion. One curve everywhere. Mixed easings read as sloppiness
            even when nobody can name why. ---- */
    --na-ease:   cubic-bezier(0.22, 0.61, 0.36, 1);
    --na-fast:   0.16s;
    --na-normal: 0.32s;
    --na-slow:   0.6s;

    /* The header BOX, used by every hero to clear itself. It tracks the
       floating bar rather than being a second number to keep in step. */
    --na-header-h: var(--na-bar);
}

@media (prefers-reduced-motion: reduce) {
    :root { --na-fast: 0s; --na-normal: 0s; --na-slow: 0s; }
}

/* =============================================================================
   BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    scroll-padding-top: calc(var(--na-header-h) + 16px);
}

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

body {
    margin: 0;
    background: var(--na-page);
    color: var(--na-ink);
    font-family: var(--na-font-body);
    font-size: var(--na-t-body);
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
[hidden] { display: none !important; }

h1, h2, h3, h4 {
    font-family: var(--na-font-display);
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.02em;
    margin: 0 0 0.5em;
    text-wrap: balance;
}

h1 { font-size: var(--na-t-h1); }
h2 { font-size: var(--na-t-h2); }
h3 { font-size: var(--na-t-h3); }
h4 { font-size: var(--na-t-h4); letter-spacing: -0.01em; }

/* The trademark mark on "Climate-Smart Shrimp™". At the browser default of
   0.83em it lands at 16px inside a 40px heading and reads as a word rather
   than a mark. */
h1 sup, h2 sup, h3 sup, h4 sup {
    font-size: 0.36em;
    top: -0.95em;
    letter-spacing: 0;
}

p  { margin: 0 0 1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

::selection { background: var(--na-aqua); color: var(--na-dark); }

:focus-visible {
    outline: 2px solid var(--na-aqua);
    outline-offset: 3px;
    border-radius: 4px;
}

.na-skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 999;
    background: var(--na-dark);
    color: #fff;
    padding: 12px 20px;
    border-radius: 0 0 var(--na-r-sm) 0;
}
.na-skip:focus { left: 0; }

.na-sr {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* =============================================================================
   LAYOUT
   ========================================================================== */

.na-wrap {
    width: 100%;
    max-width: var(--na-wrap);
    margin-inline: auto;
    padding-inline: clamp(1.25rem, 0.8rem + 2vw, 2.5rem);
}

.na-wrap--tight { max-width: var(--na-wrap-tight); }

.na-section { padding-block: var(--na-section); position: relative; }
.na-section--tight { padding-block: calc(var(--na-section) * 0.62); }

/* The two grounds. Every section is one or the other — never a third. */
.na-section--light { background: var(--na-page); color: var(--na-ink); }
.na-section--white { background: var(--na-surface); color: var(--na-ink); }
.na-section--dark  { background: var(--na-dark);  color: var(--na-on-dark); }
.na-section--deep  { background: var(--na-dark-2); color: var(--na-on-dark); }

.na-section--dark h1, .na-section--dark h2,
.na-section--dark h3, .na-section--dark h4,
.na-section--deep h1, .na-section--deep h2,
.na-section--deep h3, .na-section--deep h4 { color: var(--na-on-dark); }

/* A one-pixel aqua hairline that separates dark sections without a border
   that reads as a box. */
.na-section--seam { border-top: 1px solid var(--na-dark-line); }

/* =============================================================================
   SECTION HEADINGS
   ========================================================================== */

.na-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.6em;
    font-family: var(--na-font-body);
    font-size: var(--na-t-eyebrow);
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--na-aqua-text);
    margin: 0 0 1rem;
}
.na-eyebrow::before {
    content: "";
    width: 26px;
    height: 2px;
    background: var(--na-aqua);
    flex: none;
}
.na-section--dark .na-eyebrow,
.na-section--deep .na-eyebrow,
.na-hero .na-eyebrow,
.na-phero .na-eyebrow { color: var(--na-aqua); }

.na-head { max-width: 46rem; margin-bottom: clamp(2rem, 1.4rem + 2vw, 3.5rem); }
.na-head--center { margin-inline: auto; text-align: center; }
.na-head--center .na-eyebrow { justify-content: center; }

.na-head p {
    font-size: var(--na-t-lead);
    color: var(--na-ink-2);
    margin-top: 0.75rem;
}
.na-section--dark .na-head p,
.na-section--deep .na-head p { color: var(--na-on-dark-2); }

/* A heading whose second line is the quiet half. Used by the spec repeatedly:
   "Aquaculture is productive. / But its environmental performance is
   difficult to measure." */
.na-head h2 .na-soft { color: var(--na-ink-3); display: block; }
.na-section--dark .na-head h2 .na-soft { color: var(--na-on-dark-3); }

/* =============================================================================
   BUTTONS
   ========================================================================== */

.na-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.55em;
    font-family: var(--na-font-body);
    font-size: 0.9375rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: -0.005em;
    padding: 1rem 1.5rem;
    border-radius: var(--na-r-pill);
    border: 1px solid transparent;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--na-fast) var(--na-ease),
                border-color var(--na-fast) var(--na-ease),
                color var(--na-fast) var(--na-ease),
                transform var(--na-fast) var(--na-ease),
                box-shadow var(--na-fast) var(--na-ease);
}

.na-btn:active { transform: translateY(1px); }

/* Any icon inside a button. An inline <svg> with only a viewBox defaults to
   100% x 100%, which inside a flex button means "as large as you'll let me" —
   so the size is set here once rather than remembered at every call site. */
.na-btn svg { width: 18px; height: 18px; flex: none; }
.na-btn--lg svg { width: 19px; height: 19px; }
.na-btn--sm svg { width: 16px; height: 16px; }

.na-btn__arrow {
    transition: transform var(--na-normal) var(--na-ease);
    flex: none;
}
.na-btn:hover .na-btn__arrow { transform: translateX(3px); }

/* Primary — the brand blue with white on it, identical on light and dark
   sections. The only button that is ever filled, so there is exactly one
   obvious next action per section. */
.na-btn--primary {
    background: var(--na-aqua-deep);
    color: #fff;
    box-shadow: 0 8px 24px rgba(4, 98, 238, 0.34);
}
.na-btn--primary:hover {
    background: #1B72F5;
    box-shadow: 0 12px 32px rgba(4, 98, 238, 0.44);
}

/* Secondary on a dark ground */
.na-btn--ghost {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.24);
    color: #fff;
}
.na-btn--ghost:hover {
    background: rgba(255, 255, 255, 0.10);
    border-color: rgba(255, 255, 255, 0.42);
}

/* Secondary on a light ground */
.na-btn--outline {
    background: transparent;
    border-color: var(--na-line-2);
    color: var(--na-ink);
}
.na-btn--outline:hover {
    border-color: var(--na-aqua-deep);
    background: var(--na-aqua-wash);
    color: var(--na-aqua-text);
}

/* Solid dark, for light sections that need a strong CTA without aqua */
.na-btn--ink {
    background: var(--na-dark);
    color: #fff;
}
.na-btn--ink:hover { background: var(--na-dark-4); }

.na-btn--sm { padding: 0.7rem 1.1rem; font-size: 0.875rem; }
.na-btn--lg { padding: 1.125rem 1.875rem; font-size: 1rem; }

.na-btns {
    display: flex;
    flex-wrap: wrap;
    gap: 0.875rem;
    align-items: center;
}

/* A text link that behaves like a card CTA: "Explore BlueSat →" */
.na-link {
    display: inline-flex;
    align-items: center;
    gap: 0.45em;
    font-weight: 600;
    font-size: 0.9375rem;
    color: var(--na-aqua-text);
    text-decoration: none;
    transition: gap var(--na-fast) var(--na-ease);
}
.na-link:hover { gap: 0.75em; text-decoration: underline; text-underline-offset: 3px; }
.na-section--dark .na-link,
.na-section--deep .na-link { color: var(--na-aqua); }

/* =============================================================================
   CARDS
   ========================================================================== */

.na-card {
    position: relative;
    background: var(--na-surface);
    border: 1px solid var(--na-line);
    border-radius: var(--na-r);
    padding: clamp(1.5rem, 1.2rem + 1vw, 2rem);
    transition: transform var(--na-normal) var(--na-ease),
                border-color var(--na-normal) var(--na-ease),
                box-shadow var(--na-normal) var(--na-ease);
}

/* The spec's hover rule, everywhere: card rises slightly, border highlights.
   4px, not 12px. "Premium and subtle." */
.na-card--hover:hover {
    transform: translateY(-4px);
    border-color: var(--na-aqua-deep);
    box-shadow: var(--na-shadow-lg);
}

.na-card--dark {
    background: var(--na-dark-3);
    border-color: var(--na-dark-line);
    color: var(--na-on-dark);
}
.na-card--dark.na-card--hover:hover {
    background: var(--na-dark-4);
    border-color: var(--na-dark-line-2);
    box-shadow: var(--na-glow);
}

.na-card h3, .na-card h4 { margin-bottom: 0.5rem; }
.na-card p { color: var(--na-ink-2); font-size: 0.9375rem; }
.na-card--dark p { color: var(--na-on-dark-2); }

/* Glass. Used over imagery only — over a flat colour it is just a grey box. */
.na-glass {
    background: rgba(0, 24, 48, 0.52);
    -webkit-backdrop-filter: blur(18px) saturate(140%);
    backdrop-filter: blur(18px) saturate(140%);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--na-r);
    color: #fff;
}

/* The step number that opens a card: 01, 02, 03 */
.na-num {
    font-family: var(--na-font-mono);
    font-size: 0.8125rem;
    font-weight: 500;
    letter-spacing: 0.08em;
    color: var(--na-aqua-text);
    display: block;
    margin-bottom: 0.75rem;
}
.na-card--dark .na-num,
.na-section--dark .na-num,
.na-section--deep .na-num { color: var(--na-aqua); }

/* Icon plate */
.na-ico {
    width: 46px;
    height: 46px;
    display: grid;
    place-items: center;
    border-radius: 12px;
    background: var(--na-aqua-wash);
    border: 1px solid rgba(76, 130, 255, 0.24);
    color: var(--na-aqua-text);
    margin-bottom: 1.125rem;
    transition: transform var(--na-normal) var(--na-ease),
                background var(--na-normal) var(--na-ease);
}
.na-ico svg { width: 22px; height: 22px; }
.na-card--hover:hover .na-ico { transform: scale(1.08); }

.na-card--dark .na-ico,
.na-section--dark .na-ico,
.na-section--deep .na-ico {
    background: rgba(76, 130, 255, 0.10);
    border-color: rgba(76, 130, 255, 0.28);
    color: var(--na-aqua);
}

/* Capability list inside a card */
.na-list {
    list-style: none;
    margin: 1rem 0 0;
    padding: 0;
    display: grid;
    gap: 0.4rem;
    font-size: 0.875rem;
    color: var(--na-ink-2);
}
.na-card--dark .na-list, .na-section--dark .na-list { color: var(--na-on-dark-2); }
.na-list li {
    display: flex;
    gap: 0.6em;
    align-items: baseline;
}
.na-list li::before {
    content: "";
    width: 5px; height: 5px;
    border-radius: 50%;
    background: var(--na-aqua-deep);
    flex: none;
    transform: translateY(-2px);
}
.na-section--dark .na-list li::before,
.na-card--dark .na-list li::before { background: var(--na-aqua); }

/* Badges */
.na-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    padding: 0.35em 0.7em;
    border-radius: var(--na-r-pill);
    border: 1px solid currentColor;
}
.na-badge::before {
    content: "";
    width: 6px; height: 6px; border-radius: 50%;
    background: currentColor;
}
.na-badge--ok       { color: var(--na-ok-text); }
.na-badge--watch    { color: var(--na-watch-text); }
.na-badge--risk     { color: var(--na-risk-text); }
.na-badge--critical { color: var(--na-critical-text); }
.na-badge--nodata   { color: var(--na-nodata-text); }

/* The spec is emphatic that illustrative numbers must not read as claims.
   This is the visible half of that promise; js/na-metrics.js is the other. */
/* A block, not an inline-flex row: in a flex container every text run becomes
   its own flex item, so a note containing <code> rendered as three items with
   the container's gap punched through the middle of the sentence. The icon is
   positioned instead. */
.na-note {
    display: block;
    position: relative;
    padding-left: 1.5em;
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--na-ink-3);
    margin-top: 1.25rem;
}
.na-note::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.2em;
    width: 14px; height: 14px;
    border-radius: 50%;
    border: 1.5px solid currentColor;
    background:
        linear-gradient(currentColor, currentColor) center 3px / 1.5px 2px no-repeat,
        linear-gradient(currentColor, currentColor) center 7.5px / 1.5px 4px no-repeat;
}
.na-section--dark .na-note,
.na-section--deep .na-note { color: var(--na-on-dark-3); }

/* =============================================================================
   GRIDS
   ========================================================================== */

.na-grid { display: grid; gap: var(--na-gap); }
.na-grid--2 { grid-template-columns: repeat(2, 1fr); }
.na-grid--3 { grid-template-columns: repeat(3, 1fr); }
.na-grid--4 { grid-template-columns: repeat(4, 1fr); }
.na-grid--5 { grid-template-columns: repeat(5, 1fr); }

@media (max-width: 1100px) {
    .na-grid--5 { grid-template-columns: repeat(3, 1fr); }
    .na-grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 860px) {
    .na-grid--3 { grid-template-columns: repeat(2, 1fr); }
    .na-grid--5 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
    .na-grid--2, .na-grid--3, .na-grid--4, .na-grid--5 {
        grid-template-columns: 1fr;
    }
}

/* Horizontal swipe carousel. The spec asks for this on mobile for the five
   intelligence layers and the seven-step journeys. Applied by adding
   .na-swipe at the breakpoint where the grid would otherwise stack. */
@media (max-width: 860px) {
    .na-swipe {
        display: grid;
        /* grid-template-columns MUST be cleared. The .na-grid--N rules above
           set an explicit template, and an explicit template still governs the
           first N items even once grid-auto-flow is column — so cards 1 and 2
           kept their 2-up widths and cards 3+ went into 78vw implicit columns
           off the right edge, clipped and unreachable. This one line is the
           difference between a carousel and three invisible cards. */
        grid-template-columns: none;
        grid-auto-flow: column;
        grid-auto-columns: minmax(268px, 78vw);
        gap: 1rem;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        /* Bleed to the viewport edge so a card is visibly cut off — the only
           reliable signal that a row scrolls. */
        margin-inline: calc(-1 * clamp(1.25rem, 0.8rem + 2vw, 2.5rem));
        padding-inline: clamp(1.25rem, 0.8rem + 2vw, 2.5rem);
        padding-block: 4px;
    }
    .na-swipe::-webkit-scrollbar { display: none; }
    .na-swipe > * { scroll-snap-align: start; }
}

/* =============================================================================
   HEADER — the floating pill
   =============================================================================
   This is the v1 header, rebuilt on the na- tokens: a rounded glass island
   that floats clear of the viewport edges rather than a bar welded to the top.
   The parts, and why each one is there:

     · the pill        a 74px capsule inside the wrap, so page content shows
                       past it on both sides — that gap is the whole effect
     · the dapple      three slow blurred shapes drifting inside the glass,
                       like canopy light on water. Long, non-dividing periods
                       so the pattern never visibly repeats
     · the glide       one pill that slides to whatever is hovered, falling
                       back to the current page. One moving element, not a
                       background painted on every link
     · the progress    a water level along the bottom edge of the glass

   TWO THINGS THE ORIGINAL LEARNED THE HARD WAY, KEPT HERE
   -------------------------------------------------------
   1. The pill needs `overflow: hidden` to clip the dapple to its own radius.
      That also clips anything absolutely positioned inside it — so the mobile
      sheet is positioned against .na-wrap, which sits OUTSIDE the pill, and
      escapes the clip.

   2. v1's note: the contracted pill had a max-width, and adding a link past
      what that width fits made the last one silently disappear. This nav
      carries eight items rather than six, so the contraction is height-only.
      Nothing here can quietly eat a nav item.
   ========================================================================== */

:root { --na-bar: 88px; }   /* 14px of clearance + a 74px pill */

.na-header {
    position: fixed;
    inset: 0 0 auto;
    z-index: 100;
    height: var(--na-bar);
    padding-top: 14px;
    background: none;
    border: 0;
    transition: padding-top .32s cubic-bezier(.2, .8, .2, 1);
}

.na-header.is-stuck { padding-top: 8px; }

.na-header .na-wrap {
    position: relative;   /* the containing block for the mobile sheet */
}

/* ---- the island ---- */

.na-bar {
    position: relative;
    display: flex;
    align-items: center;
    gap: 16px;
    height: 74px;
    padding: 0 22px;
    border-radius: 999px;
    background: rgba(0, 30, 50, 0.66);
    border: 1px solid rgba(76, 130, 255, 0.16);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
    box-shadow: 0 10px 30px rgba(0, 16, 28, 0.22),
                inset 0 1px 0 rgba(255, 255, 255, 0.07);
    overflow: hidden;            /* clips the dapple and the progress line */
    transition: height .32s cubic-bezier(.2, .8, .2, 1),
                background .32s ease,
                border-color .32s ease,
                box-shadow .32s ease;
}

/* Contracted. Height only — see note 2 above. */
.na-header.is-stuck .na-bar {
    height: 60px;
    background: rgba(0, 26, 44, 0.88);
    border-color: rgba(76, 130, 255, 0.26);
    box-shadow: 0 14px 38px rgba(0, 16, 28, 0.38),
                inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

/* ---- dappled canopy light ----
   z-index 0 and positioned, so it paints above ordinary in-flow content. The
   logo and the burger are in normal flow, so without an explicit lift the
   dark half of the dapple lands on top of the mark and greys it out. */

.na-dapple {
    position: absolute;
    inset: -60% -20%;
    z-index: 0;
    pointer-events: none;
}
.na-dapple span {
    position: absolute;
    border-radius: 50%;
    filter: blur(18px);
}
.na-dapple span:nth-child(1) {
    width: 46%; height: 190%;
    left: 4%; top: -40%;
    background: rgba(0, 14, 26, 0.30);
    animation: na-dapple-a 29s ease-in-out infinite alternate;
}
.na-dapple span:nth-child(2) {
    width: 34%; height: 170%;
    left: 52%; top: -30%;
    background: rgba(0, 12, 24, 0.26);
    animation: na-dapple-b 41s ease-in-out infinite alternate;
}
.na-dapple span:nth-child(3) {
    width: 40%; height: 200%;
    left: 26%; top: -50%;
    background: radial-gradient(circle, rgba(76, 130, 255, 0.30) 0%, transparent 68%);
    filter: blur(24px);
    animation: na-dapple-c 53s ease-in-out infinite alternate;
}

@keyframes na-dapple-a {
    from { transform: translate3d(-14%, 0, 0) scale(1); }
    to   { transform: translate3d(22%, 0, 0) scale(1.25); }
}
@keyframes na-dapple-b {
    from { transform: translate3d(16%, 0, 0) scale(1.2); }
    to   { transform: translate3d(-20%, 0, 0) scale(1); }
}
@keyframes na-dapple-c {
    from { transform: translate3d(-10%, 0, 0) scale(.9); opacity: .55; }
    to   { transform: translate3d(18%, 0, 0) scale(1.3); opacity: 1; }
}

/* The one looping animation on the site. Reduced motion turns it off and
   leaves the light where it is. */
@media (prefers-reduced-motion: reduce) {
    .na-dapple span { animation: none; }
}

/* ---- logo ---- */

/* ---- the lockup --------------------------------------------------------
   The lockup carries a white outline around AQUA, which is what lets a navy
   wordmark sit on a navy header without a plate behind it. Nothing is drawn
   under it — no background, no padding, no ring.
   ---------------------------------------------------------------------- */

.na-logo {
    position: relative;
    z-index: 2;
    flex: none;
    display: flex;
    align-items: center;
    transition: transform .3s ease;
}
.na-logo img {
    height: 52px;
    width: auto;
    display: block;
    transition: height .32s cubic-bezier(.2, .8, .2, 1);
}
.na-logo:hover { transform: translateY(-2px); }
.na-header.is-stuck .na-logo img { height: 40px; }

.na-bar__spacer { flex: 1; }

/* ---- links ---- */

.na-nav {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 2px;
}

.na-nav__link {
    position: relative;
    z-index: 1;
    display: block;
    padding: 9px 14px;
    border-radius: 8px;
    font-size: 0.9375rem;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.78);
    text-decoration: none;
    white-space: nowrap;
    transition: color .15s ease;
}
.na-nav__link:hover { color: #fff; }
.na-nav__link.is-on { color: #fff; }

/* The waterline. Grows from the centre outward — a surface spreading, not a
   bar wiping in from one side. */
.na-nav__link::after {
    content: "";
    position: absolute;
    left: 14px; right: 14px; bottom: 4px;
    height: 2px;
    border-radius: 2px;
    background: var(--na-lime);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform .34s cubic-bezier(.2, .85, .25, 1);
}
.na-nav__link:hover::after,
.na-nav__link.is-on::after { transform: scaleX(1); }

/* ---- the gliding indicator ----
   Sits behind the links. Only rendered once JS has measured a target, so it
   never flashes at the origin on load. */

.na-glide {
    position: absolute;
    left: 0;
    top: 50%;
    height: 38px;
    margin-top: -19px;
    border-radius: 999px;
    background: rgba(76, 130, 255, 0.16);
    border: 1px solid rgba(76, 130, 255, 0.34);
    box-shadow: 0 0 18px rgba(76, 130, 255, 0.18);
    pointer-events: none;
    opacity: 0;
    z-index: 0;
    transition: transform .42s cubic-bezier(.34, 1.4, .5, 1),
                width .42s cubic-bezier(.34, 1.4, .5, 1),
                opacity .22s ease;
}
.na-glide.is-live { opacity: 1; }

/* Without the glide (no JS, reduced motion) the active item still needs a
   ground of its own. */
.na-nav__link.is-on { background: rgba(76, 130, 255, 0.14); }
.na-has-glide .na-nav__link.is-on { background: none; }

/* ---- reading progress ---- */

.na-progress {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 2.5px;
    transform: scaleX(0);
    transform-origin: left center;
    /* Green, not blue. This is a pointer — it says how far through the page you
       are — and a pointer is the one job the brand green holds. It reads on the
       navy bar at 7.97:1, the strongest pairing in the system. */
    background: linear-gradient(90deg,
                var(--na-lime) 0%, #6BE83C 60%, #B6F59B 100%);
    opacity: .9;
    pointer-events: none;
    z-index: 2;
}

/* ---- CTA ---- */

.na-header__cta {
    position: relative;
    z-index: 2;
    flex: none;
    overflow: hidden;
}
/* A slow shine across the button — light on a wet surface. Pure transform,
   so it costs nothing while nobody is hovering. */
.na-header__cta::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0;
    left: -60%;
    width: 45%;
    background: linear-gradient(100deg,
        transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100%);
    transform: skewX(-18deg);
    transition: left .55s cubic-bezier(.3, .8, .3, 1);
}
.na-header__cta:hover::before { left: 115%; }
@media (prefers-reduced-motion: reduce) {
    .na-header__cta::before { display: none; }
}

/* The nav carries its own "Book a Pilot" for the mobile sheet. Above the
   breakpoint that duty belongs to .na-header__cta, so the duplicate is
   hidden — two identical primary buttons in one bar is a bug, not emphasis,
   and inside a pill that clips it is also what pushes the row off the edge. */
@media (min-width: 1201px) {
    .na-nav > .na-btn { display: none; }
}

/* Between the breakpoint and a comfortably wide screen the row is only just
   fitting. Tightening the links buys ~90px, which is the difference between
   "tight" and "the last item is inside the clip". */
@media (min-width: 1201px) and (max-width: 1420px) {
    .na-nav__link { padding-inline: 10px; font-size: 0.875rem; }
    .na-nav__link::after { left: 10px; right: 10px; }
    .na-bar { gap: 10px; padding-inline: 16px; }
}

/* ---- burger ---- */

.na-burger {
    position: relative;
    z-index: 2;
    display: none;
    flex: none;
    margin-left: auto;
    width: 44px; height: 44px;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 999px;
    color: #fff;
    cursor: pointer;
}
.na-burger svg { width: 22px; height: 22px; }
.na-burger__close { display: none; }
.na-burger[aria-expanded="true"] .na-burger__open  { display: none; }
.na-burger[aria-expanded="true"] .na-burger__close { display: block; }

/* =============================================================================
   HEADER — mobile sheet
   =============================================================================
   The breakpoint is 1200px, not 900px as in v1: this nav carries eight items
   where v1 carried six, and below about 1200 the row stops fitting inside the
   pill. Since the pill clips, "stops fitting" would mean a link silently
   disappearing rather than wrapping.
   ========================================================================== */

@media (max-width: 1200px) {
    .na-burger { display: flex; }
    .na-bar__spacer { display: none; }
    .na-header__cta { display: none; }

    .na-bar { padding: 0 10px 0 18px; gap: 8px; }

    /* The sheet hangs below the pill.
       Getting this to render took two goes, and the reason is worth keeping:
       the pill has `backdrop-filter`, and backdrop-filter — exactly like
       transform and filter — makes an element the containing block for its
       positioned descendants INCLUDING position:fixed ones. So the pill's
       `overflow: hidden` clipped the sheet away whether it was absolute or
       fixed. The DOM reported it 306x513 and visible; the screen showed
       nothing.

       The fix is to stop clipping on mobile rather than to fight the
       containing block: the dapple is the only thing that needed the clip,
       and it is decoration this pill is too small to show anyway. */
    .na-bar { overflow: visible; }
    .na-dapple { display: none; }

    /* Unclipped, the progress hairline would poke out past the 999px corners,
       so it is inset to sit inside the curve. */
    .na-progress { inset-inline: 18px; border-radius: 2px; }

    .na-nav {
        position: absolute;
        top: calc(100% + 10px);
        left: 0; right: 0;
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        padding: 12px;
        border: 1px solid rgba(76, 130, 255, 0.18);
        border-radius: 22px;
        /* Solid, not translucent-plus-blur. The sheet is a descendant of an
           element that already has a backdrop-filter, and inside that backdrop
           root the page behind kept showing through a 0.97 alpha. A menu you
           can read the hero through is not a menu. Solid also drops a second
           blur layer on the device least able to afford one. */
        background: #001C2E;
        box-shadow: 0 20px 46px rgba(0, 16, 28, 0.42);
        max-height: calc(100dvh - var(--na-bar) - 34px);
        overflow-y: auto;
        overscroll-behavior: contain;

        opacity: 0;
        visibility: hidden;
        transform: translateY(-8px);
        transition: opacity var(--na-normal) var(--na-ease),
                    transform var(--na-normal) var(--na-ease),
                    visibility 0s linear var(--na-normal);
    }
    .na-nav.is-open {
        opacity: 1;
        visibility: visible;
        transform: none;
        transition-delay: 0s;
    }

    .na-nav__link {
        padding: 13px 16px;
        font-size: 1rem;
        border-radius: 13px;
    }
    .na-nav__link::after { left: 16px; right: auto; width: 20px; bottom: 8px; }
    .na-nav .na-btn { margin-top: 8px; width: 100%; }

    /* The glide is a pointer affordance. On a touch sheet there is no hover,
       and a pill sliding between items nobody is pointing at is noise. */
    .na-glide { display: none; }
    .na-has-glide .na-nav__link.is-on { background: rgba(76, 130, 255, 0.14); }

    body.na-nav-open { overflow: hidden; }
}

/* =============================================================================
   FOOTER
   ========================================================================== */

.na-footer {
    background: var(--na-dark-2);
    color: var(--na-on-dark-2);
    padding-block: clamp(3.5rem, 2.5rem + 4vw, 5.5rem) 2rem;
    font-size: 0.9375rem;
}

.na-footer__grid {
    display: grid;
    grid-template-columns: 1.85fr repeat(4, 1fr);
    gap: clamp(1.75rem, 1rem + 3vw, 3rem);
}

@media (max-width: 1040px) {
    .na-footer__grid { grid-template-columns: 1fr 1fr 1fr; }
    .na-footer__brand { grid-column: 1 / -1; max-width: 34rem; }
}
@media (max-width: 620px) {
    .na-footer__grid { grid-template-columns: 1fr 1fr; }
}

/* The footer lockup carries the mark at the one place on the page where
   nothing else is competing for attention, so it is sized to be read rather
   than to be tucked away. 64px put it below the width of the column it sits
   in and left the paragraph looking like the main element of the block. */
.na-footer__brand img {
    height: clamp(76px, 4vw + 48px, 104px);
    width: auto;
    display: block;
    margin-bottom: 1.5rem;
}

.na-footer__brand p { color: var(--na-on-dark-3); max-width: 30rem; }

.na-footer h4 {
    font-family: var(--na-font-body);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #fff;
    margin-bottom: 1rem;
}

.na-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.na-footer a {
    color: var(--na-on-dark-2);
    text-decoration: none;
    transition: color var(--na-fast) var(--na-ease);
}
.na-footer a:hover { color: var(--na-aqua); }

.na-footer__base {
    margin-top: clamp(2.5rem, 2rem + 2vw, 4rem);
    padding-top: 1.5rem;
    border-top: 1px solid var(--na-dark-line);
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    align-items: center;
    font-size: 0.8125rem;
    color: var(--na-on-dark-3);
}
.na-footer__base nav {
    margin-left: auto;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
}

/* =============================================================================
   MOTION
   =============================================================================
   Two behaviours, both one-shot: fade-up on entry, and counters that run once.
   The spec forbids continuous animation, so nothing here loops.

   .na-reveal is inert until JS adds .na-io — so a page with JS disabled or
   still loading shows all of its content rather than a blank column. That
   ordering matters more than the animation does.
   ========================================================================== */

.na-io .na-reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity var(--na-slow) var(--na-ease),
                transform var(--na-slow) var(--na-ease);
    will-change: opacity, transform;
}
.na-io .na-reveal.is-in { opacity: 1; transform: none; }

/* Children of a revealed group stagger by index, set as --i in the markup. */
.na-io .na-reveal[style*="--i"] { transition-delay: calc(var(--i) * 70ms); }

@media (prefers-reduced-motion: reduce) {
    .na-io .na-reveal { opacity: 1 !important; transform: none !important; }
}

/* Cards inside a horizontal carousel start outside the viewport horizontally,
   so the observer never fires for them until they are swiped in — and a card
   that fades in *as you drag it* reads as lag. Inside a swipe row the reveal
   is simply off. */
@media (max-width: 860px) {
    .na-io .na-swipe > .na-reveal { opacity: 1; transform: none; }
}

/* A counter's slot is reserved with tabular figures so the layout does not
   jitter from 0 to 1,000+ as it counts. */
.na-count { font-variant-numeric: tabular-nums; }

/* =============================================================================
   PRINT
   ========================================================================== */

@media print {
    .na-header, .na-footer, .na-btns, .na-burger { display: none !important; }
    body { background: #fff; color: #000; }
    .na-section--dark, .na-section--deep { background: #fff !important; color: #000 !important; }
}

/* Mobile corrections live in css/na-mobile.css, which loads LAST on every
   page. They have to: several of them override values set in na-blocks.css
   and the per-page stylesheets, and at equal specificity the file that loads
   later wins. Putting them here looked tidier and silently did nothing. */
