/* FONTS:START */
/* --- Self-hosted web fonts ---
 *
 * site.css has always asked for Inter, Space Grotesk and IBM Plex Mono, but
 * nothing ever loaded them -- there was no @font-face rule and no link to a
 * font service anywhere on the site, so every visitor fell through to Arial
 * and whatever their browser calls "monospace". The typography was decorative
 * intent with no delivery behind it.
 *
 * Served from our own origin rather than a font CDN: one less DNS lookup and
 * TLS handshake on first paint, no third party in the critical path, and no
 * request to another host carrying the visitor's IP.
 *
 * Latin and latin-ext only, and the two variable families are stored once
 * rather than once per weight. Regenerate with tools/fetch-fonts.py; do not
 * hand-edit between the markers.
 */

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('assets/fonts/inter-var-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('assets/fonts/inter-var-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Space Grotesk';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('assets/fonts/space-grotesk-var-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'Space Grotesk';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('assets/fonts/space-grotesk-var-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('assets/fonts/ibm-plex-mono-400-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('assets/fonts/ibm-plex-mono-400-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('assets/fonts/ibm-plex-mono-500-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('assets/fonts/ibm-plex-mono-500-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('assets/fonts/ibm-plex-mono-600-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('assets/fonts/ibm-plex-mono-600-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('assets/fonts/ibm-plex-mono-700-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('assets/fonts/ibm-plex-mono-700-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* FONTS:END */

/* --- Colour, in one place ---------------------------------------------------
 * Every colour on the site used to be a literal, repeated: #fff 95 times,
 * #5e7538 85 times, #6e6e73 60. That was survivable while there was one
 * appearance to hold. There are now two.
 *
 * The site never had a dark mode. It had no prefers-color-scheme rule
 * anywhere, so Chrome on Android applied its own Auto Dark Theme -- an
 * algorithmic inversion that decides per element what a colour should become.
 * It turned the hero's green gradient headline into near-black on near-black.
 * Declaring color-scheme below is what switches that off: a page that says it
 * handles both schemes is left alone to handle them.
 *
 * The names are semantic, not descriptive -- --c-surface, not --c-white --
 * because the whole point is that the value changes and the meaning does not.
 * Anything used only on a band that is dark in BOTH schemes -- the
 * .vx-section--ink slab, the greens and greys written for it, the product
 * photo plates -- is deliberately still a literal: it is not a colour that
 * has two states.
 */
:root {
    /* Both, so the browser stops force-darkening and so form controls,
       scrollbars and selection follow the scheme without being restyled. */
    color-scheme: light dark;

    /* Surfaces, lightest use first. */
    --c-canvas: #fff;          /* the page */
    --c-band: #f5f5f7;         /* an alternating section */
    --c-surface: #fff;         /* a card */
    --c-surface-2: #fafafa;    /* a panel inside a card, a table stripe */
    --c-tint: #f4f6f1;         /* a green-tinted selected row */
    --c-tint-2: #f6f7f4;
    --c-tint-3: #f5f7f0;
    /* The slab that is dark in both schemes. Deeper than the canvas in dark
       so it keeps reading as the band that stands apart, which is the only
       job it has. Everything written for it -- white text, the light green
       eyebrow, the pale grey lead -- then goes on working untouched. */
    --c-inkband: #1d1d1f;

    /* Type. */
    --c-ink: #1d1d1f;
    --c-sub: #6e6e73;
    --c-faint: #86868b;
    --c-quiet: #4a4a4f;
    --c-placeholder: #757579;

    /* The green. Two of them, because the accent is asked to do two
       different jobs: it is text on a light background, and it is the fill
       under white button text. In dark mode those pull opposite ways -- the
       text has to get lighter to stay legible, and a fill that gets lighter
       needs DARK text on it, not white. One token could not do both, which is
       what makes a naive inversion produce unreadable buttons. */
    --c-accent: #5e7538;
    --c-accent-deep: #4b5e2d;
    --c-accent-fill: #5e7538;
    --c-accent-fill-hover: #4b5e2d;
    --c-on-accent: #fff;
    --c-accent-line: rgba(94, 117, 56, .45);
    --c-accent-ring: rgba(113, 138, 69, .25);
    --c-accent-glow: rgba(94, 117, 56, .14);
    --c-accent-rule: rgba(94, 117, 56, .35);
    --c-mark: #dfe9c8;         /* the search-hit highlight */

    /* The gradient headline. Every stop has to clear 3:1 on the background it
       actually runs on, so the dark scheme cannot reuse these: #4b5e2d on a
       near-black page is 1.6:1, which is the "hard places." in the report. */
    --c-grad-1: #4b5e2d;
    --c-grad-2: #628039;
    --c-grad-3: #72913f;

    /* Hairlines and washes, by weight rather than by opacity, because the
       opacity that reads as a hairline on white is not the one that reads as
       a hairline on near-black -- and black-on-black is no line at all. */
    --c-line-soft: rgba(0, 0, 0, .06);
    --c-line-thin: rgba(0, 0, 0, .08);
    --c-line: rgba(0, 0, 0, .10);
    --c-line-mid: rgba(0, 0, 0, .14);
    --c-line-firm: rgba(0, 0, 0, .18);
    --c-line-hard: rgba(0, 0, 0, .22);
    --c-wash: rgba(0, 0, 0, .06);
    --c-wash-strong: rgba(0, 0, 0, .12);

    /* Chrome over the page. */
    --c-header: rgba(255, 255, 255, .82);
    --c-header-panel: rgba(255, 255, 255, .98);
    --c-scrim: rgba(20, 20, 22, .45);

    --c-danger: #b3261e;
    --c-danger-bg: #fdf1f0;
    --c-danger-ring: rgba(179, 38, 30, .12);

    /* The full-screen photo viewer. Its own pair, because it is neither the
       page nor the plate: the photograph inside it keeps its white
       background, and the surround has to frame that rather than match it.
       Left white in the dark scheme it was a full-screen flash on a tap. */
    --c-lightbox: rgba(255, 255, 255, .97);
    --c-lightbox-btn: rgba(255, 255, 255, .9);
    --c-lightbox-btn-hover: #fff;

    /* The photo plate. White in BOTH schemes and on purpose: every product
       photograph and every manufacturer logo on this site is shot or drawn on
       white, so a plate that goes dark underneath one does not darken the
       picture -- it puts a glowing white rectangle in the middle of a dark
       card. Keeping the plate white is what the catalogues that do this well
       all do. */
    --c-plate: #fff;
    /* The faint grey square a catalogue photograph is padded against, inside
       the white plate. A second value, not a shade of the first, so the two
       stay in the relationship the light scheme has them in. */
    --c-plate-soft: #f5f5f7;

    /* The older names, kept because markup and three stylesheets ask for
       them by name. Aliases now, so they move with the scheme instead of
       having to be changed twice. The !important they used to carry is gone:
       on a custom property it would have beaten the dark block below, and a
       token that cannot be overridden is not a token. */
    --color-bg-primary: var(--c-canvas);
    --color-bg-secondary: var(--c-band);
    --color-surface: var(--c-surface-2);
    --color-text-primary: var(--c-ink);
    --color-text-secondary: var(--c-sub);
    --color-text-muted: var(--c-sub);
    --color-accent: var(--c-accent);
    --color-border: var(--c-line);
    --bg-base: var(--c-canvas);
    --bg-pure: var(--c-canvas);
    --bg-accent: var(--c-band);
    --text-primary: var(--c-ink);
    --text-secondary: var(--c-sub);
    --tech-blue: var(--c-accent);
}
* { box-sizing:border-box; }
html { scroll-behavior:auto; background:var(--c-canvas); }
/* Focused form fields should clear the fixed masthead. Individual sections
   set their own scroll margin; a global one would count that space twice. */
input, select, textarea { scroll-margin-top:110px; }
@media (max-width:768px) {
    /* 16px also prevents iOS zooming the page when a field receives focus. */
    .rfq-field input, .rfq-field textarea,
    .apply-field input, .apply-field select, .apply-field textarea,
    .catalog-search input { font-size:16px !important; }
    .rfq-grid, .apply-grid, .shop-routes { grid-template-columns:minmax(0,1fr) !important; }
}
/* In-page jumps (catalogue category chips, "All products") glide instead of
   snapping. Disabled below for anyone who asked for reduced motion. */
@media (prefers-reduced-motion:no-preference) { html { scroll-behavior:smooth; } }
body { margin:0; background:var(--c-canvas) !important; color:var(--c-ink) !important; font-family:Inter,Arial,sans-serif !important; }
body::selection { background:var(--c-accent-fill); color:var(--c-on-accent); }
header, #nav-header { position:fixed !important; top:0 !important; left:0 !important; z-index:100 !important; display:flex !important; align-items:center !important; justify-content:space-between !important; width:100% !important; height:84px !important; padding:0 8% !important; background:var(--c-header) !important; border-bottom:1px solid var(--c-line) !important; backdrop-filter:saturate(180%) blur(20px); }
header > nav { margin-left:auto; }
.nav-toggle { display:none; }
header .logo img { filter:none; }
header .logo img, header > a > img, header a > img { display:block; width:auto !important; height:48px !important; max-height:48px !important; }
/* Every page gets this header and nothing else. Pages used to carry their own
   copies that disagreed on padding, gap, font and hover treatment, so the bar
   visibly changed shape while moving between pages. */
header > nav { display:flex; gap:clamp(1.15rem,1.75vw,2.5rem); align-items:center; margin-left:auto; }
.nav-link { font-family:'IBM Plex Mono',monospace !important; font-size:.7rem !important; font-weight:500 !important; letter-spacing:.12em !important; text-decoration:none !important; text-transform:uppercase; color:var(--c-sub) !important; transition:color .2s ease; }
/* No underlines anywhere: hover and the current page are both shown by colour
   alone, which stays consistent across every page and needs no layout space. */
.nav-link::after, .nav-link::before { content:none !important; }
.nav-link:hover, .nav-link:focus-visible { color:var(--c-accent) !important; }
/* Not colour alone: WCAG 1.4.1 rules out using colour as the only visual
   means of conveying information, and a weight change is easy to miss on a
   small uppercase mono label. The underline is the signal that survives
   greyscale, low vision and most colour-vision deficiencies. */
.nav-link.is-current, .nav-link[aria-current="page"] { color:var(--c-ink) !important; font-weight:600 !important; text-decoration:underline !important; text-underline-offset:6px; text-decoration-thickness:2px; text-decoration-color:var(--c-accent); }
.nav-link.is-current:hover, .nav-link[aria-current="page"]:hover { color:var(--c-accent) !important; }
/* Contact is the last item and the one action the header asks for, so on a
   wide screen it is drawn as a button. In the mobile panel it is a row like
   the others; the panel is already a list of choices. */
@media (min-width:1025px) {
    header > nav .nav-link:last-child { padding:.7rem 1.15rem; border-radius:999px; background:var(--c-accent-fill); color:var(--c-on-accent) !important; }
    header > nav .nav-link:last-child:hover, header > nav .nav-link:last-child:focus-visible { background:var(--c-accent-fill-hover); color:var(--c-on-accent) !important; }
    header > nav .nav-link:last-child[aria-current="page"], header > nav .nav-link:last-child.is-current { color:var(--c-on-accent) !important; text-decoration-color:var(--c-on-accent); }
}
a:focus-visible, button:focus-visible, [tabindex]:focus-visible { outline:2px solid var(--c-accent); outline-offset:4px; }
/* Off-screen until focused, then pinned over the header. Moved rather than
   hidden with display:none, which would take it out of the tab order and
   defeat the point. */
.skip-link { position:fixed; top:0; left:0; z-index:200; padding:.85rem 1.4rem; transform:translateY(-120%); background:var(--c-inkband); color:#fff; font:600 .8rem 'IBM Plex Mono',monospace; letter-spacing:.06em; text-decoration:none; transition:transform .15s ease; }
.skip-link:focus { transform:translateY(0); }
/* The skip target should not draw a focus ring when it receives focus from
   the link -- the visitor asked to go there, they are not navigating it. */
main:focus { outline:none; }
/* Anchor targets must clear the fixed header instead of landing beneath it. */
:target, [id] { scroll-margin-top:104px; }
body.is-locked { overflow:hidden; }
h1,h2,h3,h4,h5 { font-family:'Space Grotesk',Arial,sans-serif !important; font-weight:500 !important; letter-spacing:-.035em; color:var(--c-ink) !important; }
/* The base scale, for a heading no page has claimed. It used to run larger
   than the display size in assets/vx.css -- 98px against 80px at 1440px -- so
   the biggest heading on the site appeared on the four pages that had simply
   forgotten to override it. These are now the same numbers as .vx-display and
   .vx-h2, which makes the fallback the intended size rather than a surprise. */
h1 { font-size:clamp(2.1rem,3.5vw,3.35rem) !important; line-height:1.1 !important; }
h2 { font-size:clamp(1.95rem,3.4vw,2.95rem) !important; line-height:1.1 !important; }
p { line-height:1.75; }
main { overflow:hidden; }
main .h-screen { height:auto !important; min-height:85svh; }
.ecosystem-card { border:2px solid var(--c-line-hard) !important; background:var(--c-surface) !important; }
.ecosystem-card:hover { border-color:var(--c-accent) !important; }
/* A sitemap footer: who we are and how to reach us, then four columns of
   links, then the legal line. The columns are the second way round the site
   after the header, and the only one that names every service. */
.site-footer { padding:clamp(3rem,6vw,4.5rem) 8% 2rem; background:var(--c-band); border-top:1px solid var(--c-line); color:var(--c-sub); font:400 .9rem/1.6 'Inter',system-ui,sans-serif; }
.site-footer__inner { max-width:1440px; margin:0 auto; display:grid; grid-template-columns:minmax(0,1.1fr) minmax(0,2.4fr); gap:2.5rem 4rem; }
.site-footer__name { margin:0 0 .6rem; color:var(--c-ink); font:600 1rem 'Space Grotesk','Inter',sans-serif; }
.site-footer__about { max-width:34ch; margin:0 0 1.25rem; }
.site-footer__contact { display:flex; flex-direction:column; gap:.35rem; font-style:normal; }
.site-footer__nav { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:2rem; }
.site-footer__col { display:flex; flex-direction:column; gap:.55rem; }
.site-footer__head { margin:0 0 .35rem !important; color:var(--c-ink) !important; font:600 .7rem 'IBM Plex Mono',monospace !important; letter-spacing:.12em !important; text-transform:uppercase; }
.site-footer a { color:var(--c-sub); text-decoration:none; }
.site-footer a:hover, .site-footer a:focus-visible { color:var(--c-accent); }
.site-footer__base { grid-column:1 / -1; display:flex; justify-content:space-between; gap:1rem; padding-top:1.5rem; border-top:1px solid var(--c-line); font:500 .72rem 'IBM Plex Mono',monospace; letter-spacing:.04em; }
@media (max-width:1024px) {
    .site-footer__inner { grid-template-columns:1fr; }
    .site-footer__nav { grid-template-columns:repeat(2,minmax(0,1fr)); }
}
main > section { border-bottom:1px solid var(--c-line-thin); }

/* --- One page rhythm across the site ---------------------------------------
   What is left of a compatibility layer that used to hold eleven selectors.
   Pages had mixed 8%/10% gutters and heroes that were variously vertical-centred
   inside 70vh/60vh boxes or padded from the top, so the headline landed in a
   different place on almost every page. Those page structures are gone now --
   they were rewritten onto .vx-hero and .vx-section, which set their own
   padding -- and the rules that propped them up went with them. The two that
   remain are the ones whose markup is still its own: the product pages and the
   category guides. */
main > section, .guide-hero, .guide-section,
.product-hero, .product-body-section {
    padding-left:8% !important; padding-right:8% !important;
}
/* The same top padding as .vx-hero, so a product page and a category page
   start their heading on the same line as everything else. */
.guide-hero, .product-hero {
    display:block !important; height:auto !important; min-height:0 !important;
    padding-top:clamp(7rem,12vw,10rem) !important;
}
.bg-white, .bg-\[var\(--bg-pure\)\] { background:var(--c-canvas) !important; }
.bg-\[var\(--bg-accent\)\], .bg-\[var\(--bg-base\)\] { background:var(--c-band) !important; }
.text-\[var\(--text-secondary\)\] { color:var(--c-sub) !important; }
.text-\[var\(--tech-blue\)\] { color:var(--c-accent) !important; }
.border, .border-gray-100 { border-color:var(--c-line) !important; }
.hero-grid,.hero-about { background-image:none !important; }
.status-overlay, .back-link, .text-xs { font-family:'IBM Plex Mono',monospace !important; letter-spacing:.12em; }
.cap-card,.project-card,.delivery-card { border-radius:18px !important; background:var(--c-surface) !important; border-color:var(--c-line) !important; box-shadow:none !important; }
.cap-card:hover,.project-card:hover,.delivery-card:hover { border-color:var(--c-line-firm) !important; transform:translateY(-4px) !important; box-shadow:0 18px 40px rgba(0,0,0,.08) !important; }
.cap-image,.hero-project-image,.gallery-image { filter:saturate(.72) contrast(1.08); border-radius:0 !important; }
.project-card { border-left:1px solid var(--c-line-mid) !important; min-height:12rem; }
.project-card:hover { border-left-color:var(--c-accent) !important; background:var(--c-surface-2) !important; }
.partner-card { padding:2rem !important; }
section .reveal, section .reveal-node { will-change:transform,opacity; }
@media (max-width:1024px) {
    .nav-toggle { display:flex; align-items:center; justify-content:center; width:42px; height:42px; margin-left:auto; padding:0; border:1px solid var(--c-line-mid); border-radius:50%; background:var(--c-surface); color:var(--c-ink); cursor:pointer; }
    .nav-toggle__lines, .nav-toggle__lines::before, .nav-toggle__lines::after { display:block; width:17px; height:1.5px; border-radius:1px; background:currentColor; content:""; transition:transform .2s ease,opacity .2s ease; }
    .nav-toggle__lines { position:relative; }
    .nav-toggle__lines::before { position:absolute; top:-6px; left:0; }
    .nav-toggle__lines::after { position:absolute; top:6px; left:0; }
    header.nav-is-open .nav-toggle__lines { background:transparent; }
    header.nav-is-open .nav-toggle__lines::before { transform:translateY(6px) rotate(45deg); }
    header.nav-is-open .nav-toggle__lines::after { transform:translateY(-6px) rotate(-45deg); }
    header nav { position:fixed !important; top:calc(84px + env(safe-area-inset-top)) !important; left:12px !important; right:12px !important; display:none !important; flex-direction:column !important; align-items:stretch !important; gap:0 !important; margin:0 !important; padding:8px !important; border:1px solid var(--c-line); border-radius:16px; background:var(--c-header-panel); box-shadow:0 16px 35px rgba(0,0,0,.12); }
    header.nav-is-open nav { display:flex !important; }
    header nav .nav-link { display:block; padding:14px 12px; border-radius:10px; font-size:.72rem !important; letter-spacing:.1em !important; }
    header nav .nav-link:hover, header nav .nav-link:focus-visible { background:var(--c-band); }
    header nav .nav-link.is-current, header nav .nav-link[aria-current="page"] { background:var(--c-band); }
}
@media (max-width:768px) {
    header, #nav-header { height:72px !important; padding:0 20px !important; }
    header .logo img, header > a > img, header a > img { height:40px !important; max-height:40px !important; }
    header nav { top:calc(72px + env(safe-area-inset-top)) !important; }
    :target, [id] { scroll-margin-top:88px; }
    main > section { padding-left:20px !important; padding-right:20px !important; }
    h1 { font-size:clamp(2.45rem,11vw,3.4rem) !important; }
    .site-footer { padding:2.5rem 20px 1.5rem; }

}
@media (prefers-reduced-motion:reduce) { *,*::before,*::after { scroll-behavior:auto !important; transition-duration:.01ms !important; animation-duration:.01ms !important; animation-iteration-count:1 !important; } }

/* --- The dark scheme --------------------------------------------------------
 * Values only. Every rule on the site is written once, against the tokens
 * above, and this block moves them -- so there is no second stylesheet to
 * keep in step and no selector here that can fall out of date when a
 * component changes.
 *
 * Not an inversion. The light palette's ordering is kept rather than
 * mirrored: the canvas sits in the middle, the alternating band is recessed
 * below it, a card is raised above it, and the statement slab stays the
 * deepest thing on the page, exactly as it is the darkest thing on the page
 * in light mode. Inverting instead would have turned that slab into a white
 * sheet in a dark room.
 *
 * The greys are warm-neutral rather than pure black: #000 against a bright
 * photograph is a harder edge than any of these photographs want, and the
 * text sits at #e6e9ec rather than #fff because pure white on near-black is
 * the combination that smears while it scrolls.
 */
@media (prefers-color-scheme: dark) {
    :root {
        --c-canvas: #16191d;
        --c-band: #101216;
        --c-surface: #1c2026;
        --c-surface-2: #212630;
        --c-tint: #1e2618;
        --c-tint-2: #1c2118;
        --c-tint-3: #1a2016;
        --c-inkband: #0a0c0f;

        --c-ink: #e6e9ec;
        --c-sub: #a6acb5;
        --c-faint: #8a9099;
        --c-quiet: #b9bfc7;
        --c-placeholder: #8a9099;

        /* 9.4:1 on the canvas as text, 8.8:1 on a card; as a fill it
           carries #12180a at 9.7:1, which is the pairing white text on this
           green could not have given -- that is 1.8:1. */
        --c-accent: #a8c96b;
        --c-accent-deep: #c6df90;
        --c-accent-fill: #a8c96b;
        --c-accent-fill-hover: #c6df90;
        --c-on-accent: #12180a;
        --c-accent-line: rgba(168, 201, 107, .45);
        --c-accent-ring: rgba(168, 201, 107, .30);
        --c-accent-glow: rgba(168, 201, 107, .18);
        --c-accent-rule: rgba(168, 201, 107, .40);
        --c-mark: #3c4a24;

        --c-grad-1: #9dbf5e;
        --c-grad-2: #b6d47c;
        --c-grad-3: #cfe6a0;

        --c-line-soft: rgba(255, 255, 255, .07);
        --c-line-thin: rgba(255, 255, 255, .10);
        --c-line: rgba(255, 255, 255, .13);
        --c-line-mid: rgba(255, 255, 255, .17);
        --c-line-firm: rgba(255, 255, 255, .24);
        --c-line-hard: rgba(255, 255, 255, .30);
        --c-wash: rgba(255, 255, 255, .08);
        --c-wash-strong: rgba(255, 255, 255, .16);

        --c-header: rgba(22, 25, 29, .86);
        --c-header-panel: rgba(28, 32, 38, .98);
        --c-scrim: rgba(0, 0, 0, .62);

        --c-lightbox: rgba(9, 11, 14, .96);
        --c-lightbox-btn: rgba(42, 47, 55, .92);
        --c-lightbox-btn-hover: #333a43;

        --c-danger: #ffb4ab;
        --c-danger-bg: rgba(255, 180, 171, .10);
        --c-danger-ring: rgba(255, 180, 171, .18);
    }

    /* Both manufacturer marks are dark artwork on transparency -- blu-sub.svg
       is drawn in #1b1e26 -- so on a dark card they are a hole where a logo
       should be. A plate under the mark is the treatment that keeps the
       brand's own colours; recolouring it with a filter would not. */
    .brand-mark__logo, .px-partner__logo {
        background: var(--c-plate);
        border-radius: 4px;
        padding: 1px;
    }

    /* The photographs are lit for a white page. Taking a little brightness
       out of them stops a full-bleed hero reading as a lightbox on a dark
       one; the existing saturate/contrast grade is left alone. */
    .vx-hero__media img, .vx-card__media img:not([src*="brands"]) {
        filter: brightness(.92);
    }

    /* The select arrow is a data: URI, so it cannot hold a var(). The whole
       image is restated with the light-scheme grey swapped for one that
       clears 3:1 against the field it now sits on. */
    .apply-field select {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23a6acb5' stroke-width='1.6'/%3E%3C/svg%3E");
    }

    /* Tailwind's own colour utilities are compiled literals in a generated
       file, so they cannot be tokenised at the source. There are three left
       in the markup; they are corrected here rather than by editing a build
       artefact that the next compile would overwrite. */
    .border-black { border-color: var(--c-line-hard) !important; }
    .border-slate-200 { border-color: var(--c-line) !important; }
    .text-slate-200, .text-slate-300 { color: var(--c-sub) !important; }
}

/* ---- Breadcrumb on the top-level pages ----
   These carried BreadcrumbList markup describing a Home / <page> trail while
   showing the reader nothing, so the markup asserted a structure the page did
   not have. Two steps, in the same monospace register the rest of the
   navigation furniture uses. */
.vx-crumb { margin:0 0 1.15rem; }
.vx-crumb ol { display:flex; flex-wrap:wrap; align-items:center; gap:.15rem .5rem; margin:0; padding:0; list-style:none; font:500 .78rem 'IBM Plex Mono',ui-monospace,monospace; }
.vx-crumb li { display:flex; align-items:center; gap:.5rem; color:var(--c-sub); }
.vx-crumb li:not(:last-child)::after { content:"/"; opacity:.45; }
.vx-crumb a { color:var(--c-sub); text-decoration:none; }
.vx-crumb a:hover { color:var(--c-accent); text-decoration:underline; text-underline-offset:2px; }
.vx-crumb [aria-current="page"] { color:var(--c-ink); }
@media (max-width:768px) { .vx-crumb ol { font-size:.72rem; } }
