.nav {
    position: fixed; top: 0; left: 0; right: 0; z-index: 200;
    background: rgba(251,252,253,0.85);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--border-soft);
    height: 64px;
}
.nav-inner {
    max-width: 1180px; margin: 0 auto; height: 100%;
    padding: 0 24px;
    display: flex; align-items: center; justify-content: space-between; gap: 24px;
}
.nav-logo { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.nav-logo img { height: 32px; width: auto; filter: brightness(0); }
.nav-logo span { font-size: 0.88rem; font-weight: 800; letter-spacing: 0.16em; color: var(--ink); }
.nav-links { display: flex; align-items: center; gap: 28px; }
.nav-links a {
    font-size: 0.85rem; font-weight: 500; color: var(--text-2);
    text-decoration: none; transition: color 0.2s ease;
}
.nav-links a:hover { color: var(--ink); }
.nav-links a[aria-current="page"] { color: var(--ink); }
.nav-right { display: flex; align-items: center; gap: 12px; }
.nav-login {
    font-size: 0.85rem; font-weight: 600; color: var(--text-2);
    text-decoration: none; padding: 9px 16px; border-radius: 9px;
    transition: color 0.2s ease, background 0.2s ease;
}
.nav-login:hover { color: var(--ink); background: var(--bg-soft); }
button.nav-login { background: none; border: none; cursor: pointer; font-family: inherit; }
.nav-cta {
    display: inline-flex; align-items: center;
    font-family: inherit; font-size: 0.85rem; font-weight: 600;
    background: var(--ink); color: white;
    padding: 10px 20px; border-radius: 9px;
    border: none; cursor: pointer; text-decoration: none;
    transition: background 0.2s ease;
}
/* `color` is restated as a guard. Until BAR-1444, page.css's own `a:hover`
   below set color: var(--ink) at (0,1,1), which outranks `.nav-cta` at
   (0,1,0). On index the nav CTA was then a <button> and never matched that
   rule, so this only ever broke on the subpages — the same trap that hit
   .btn-primary in 2e4b484 and .nav-mobile-cta in 063254a. a:hover sets no
   colour now; the guard stays in case it ever does again.
   Measured after this fix: white on #1d3340 is 13.13:1. */
.nav-cta:hover { background: #1d3340; color: white; }
.nav-burger {
    display: none; background: none; border: none; cursor: pointer;
    padding: 8px; color: var(--ink);
}
.nav-mobile {
    display: none;
    position: fixed; top: 64px; left: 0; right: 0; z-index: 199;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 12px 24px 20px;
    box-shadow: var(--shadow-pop);
}
.nav-mobile.open { display: block; }
.nav-mobile a {
    display: block; padding: 12px 4px;
    font-size: 0.95rem; font-weight: 500; color: var(--ink);
    text-decoration: none; border-bottom: 1px solid var(--border-soft);
}
.nav-mobile button:not(.nav-mobile-cta) {
    display: block; width: 100%; text-align: left;
    padding: 12px 4px;
    font-size: 0.95rem; font-weight: 500; color: var(--ink);
    background: none; border: none; border-bottom: 1px solid var(--border-soft);
    font-family: inherit; cursor: pointer;
}
/* `.nav-mobile a` (0,1,1) beats `.btn-primary` (0,1,0) on six properties,
   so the CTA has to restate them here, where the selector is (0,2,0).
   Without this it renders as a navy block with a near-black label at
   1.29:1 — invisible, on every page, on mobile only, which is why it
   survived this long. */
.nav-mobile .nav-mobile-cta {
    margin-top: 16px; width: 100%;
    display: flex;
    padding: 13px 26px;
    color: white;
    font-size: 0.9rem;
    font-weight: 600;
    border-bottom: none;
}
@media (max-width: 1000px) {
    .nav-links { display: none; }
    .nav-login { display: none; }
    .nav-cta { display: none; }
    .nav-burger { display: block; }
    /* The fixed tab goes where the nav goes. Below this width it would
       sit on top of body copy rather than beside it, so the burger menu
       carries "Contact us" instead - the same link, in the place a
       reader is already looking for navigation. Change one and change
       the other: partials/nav.html's .nav-mobile block is the pair. */
    .contact-tab { display: none; }
}

/* ===== Section layout ===== */
/* 56px vertical, 32px horizontal, flat rather than clamped. The clamp
   existed to tame a large desktop value on small screens; a flat value
   needs no taming. Two adjacent sections each contribute the vertical
   padding, so the gap between any two is 112px. Widened from 32px on
   2026-09-08 (232968d) as part of the index rhythm work — the comment
   said 32px and 64px for a while after the code said otherwise. */
.section { padding: 56px 32px; scroll-margin-top: 64px; }
/* The nav is fixed at 64px, so this padding is what separates it from the
   first line of content. 102px leaves a 38px gap. Deliberately not the
   clamp that used to be here: at desktop width 12vw resolved to 140px and
   left 76px of empty space above the breadcrumb. Keep this in step with
   `.content` further down, which carries the same 102px for the six pages
   that have no `.section`. */
main > .section:first-child { padding-top: 102px; }
.section-inner { max-width: 1140px; margin: 0 auto; }
.section-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.68rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.14em;
    color: var(--accent);
    display: inline-flex; align-items: center; gap: 10px;
    margin-bottom: 18px;
}
.section-label::before {
    content: ''; width: 18px; height: 2px;
    background: var(--accent); border-radius: 2px;
}
.section-title {
    font-size: clamp(1.7rem, 3.4vw, 2.4rem);
    font-weight: 700; letter-spacing: -0.028em;
    line-height: 1.18; max-width: 640px;
}

/* ===== CTA band ===== */
.cta-band {
    background: #16304a;
    /* Asymmetric on purpose (aea5773): 88px above the heading, 56px below,
       32px at the sides. The bottom matches `.section`'s own 56px vertical
       padding and the sides match its 32px, so the band sits in the same
       rhythm as everything above it; the extra 32px on top is what sets it
       apart as a terminal block on a dark ground with no following section
       to separate from. It held a heading and a button when this was 48px
       all round; as of 79b3a83 it holds only the heading. */
    padding: 88px 32px 56px;
    position: relative; overflow: hidden;
    scroll-margin-top: 64px;
}
.cta-band::before {
    content: ''; position: absolute; pointer-events: none;
    width: 760px; height: 380px; left: 50%; top: -180px;
    transform: translateX(-50%);
    background: radial-gradient(closest-side, rgba(12,25,41,0.22), transparent);
}
.cta-band-inner { max-width: 720px; margin: 0 auto; text-align: center; position: relative; }
.cta-band h2 {
    font-size: clamp(1.8rem, 3.6vw, 2.5rem);
    font-weight: 800; letter-spacing: -0.03em;
    color: white; line-height: 1.15;
}
.cta-band p { margin-top: 16px; color: rgba(255,255,255,0.55); font-size: 0.98rem; }
/* The closing band holds a heading and nothing else (79b3a83). Button,
   action-row and secondary-button rules lived here until 2026-09-08 and
   were removed when the last band lost its buttons. */

/* Breadcrumb. Present on the ten subpages, absent on index (a trail
   pointing at itself says nothing) and on evidence (pending approval —
   see BAR-1072). Its text is the same string as that page's
   BreadcrumbList `name`: a visible trail that disagrees with the
   structured data is worse than no trail at all.
   The legal pages matter most here — nobody browses to a DPA, they
   arrive at one cold from a checkout link or a procurement email, and
   that is exactly the situation a breadcrumb exists for. */
/* The breadcrumb sits at the same place on every page: 1140px wide,
   centred, whatever the reading column beneath it does. On the
   .section pages the crumb already lives inside a 1140px
   .section-inner, so this is a no-op there; it is what pulls
   about.html's crumb out to the page edge, and what the .content
   break-out below builds on. */
.crumbs { max-width: 1140px; margin: 0 auto 20px; }
.crumbs ol {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 8px; margin: 0; padding: 0; list-style: none;
    font-size: 0.74rem; color: var(--text-3);
}
.crumbs li {
    margin: 0;
    font-size: 0.74rem;
    line-height: 1.6;
    color: var(--text-3);
}
.crumbs li + li::before { content: '/'; margin-right: 8px; opacity: 0.55; }
.crumbs a { color: var(--text-3); text-decoration: none; }
.crumbs a:hover { color: var(--ink); text-decoration: underline; }

/* 102px top for the same reason as `main > .section:first-child`: the nav
   is fixed at 64px, so this leaves a 38px gap. These six pages have no
   `.section`, so that rule cannot reach them and they have to be set
   here too. Change the two together or half the site drifts. */
.content { max-width: 720px; margin: 0 auto; padding: 102px 24px 96px; }

/* The six .content pages have a 672px reading column, so the shared
   1140px cap above cannot reach the page edge on its own — the crumb
   has to break out of the column it sits in. 50% resolves against the
   672px containing block (=336), so -570 puts the left edge at 143,
   the same x as products.html. 1204 is where 1140 stops fitting the
   viewport once a classic scrollbar takes its ~15px; the gutter there
   is about 25px, not the 32px the .section pages use. Measured
   consequence: between roughly 1204 and 1219 this crumb sits up to
   7px left of products.html's and 15px wider. Accepted, because
   moving the threshold to 1220 to close those 7px opens a 225px jump
   at the same width instead. Below 1204 the break-out is dropped and
   the crumb sits with its column. */
@media (min-width: 1204px) {
    .content > .crumbs {
        width: 1140px;
        margin-left: calc(50% - 570px);
    }
}

h1 {
    font-size: clamp(1.7rem, 4vw, 2.3rem);
    font-weight: 800; letter-spacing: -0.03em; line-height: 1.15;
    margin-bottom: 10px;
}
.subtitle {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.78rem; font-weight: 500; letter-spacing: 0.02em;
    color: var(--text-3);
    margin-bottom: 44px;
}

h2 {
    font-size: 1.12rem; font-weight: 700; letter-spacing: -0.01em;
    color: var(--ink);
    margin-top: 44px; padding-top: 28px;
    border-top: 1px solid var(--border-soft);
}
h2:first-of-type { margin-top: 0; padding-top: 0; border-top: none; }

h3 {
    font-size: 0.98rem; font-weight: 700; letter-spacing: -0.005em;
    color: var(--ink);
    margin-top: 26px; margin-bottom: 10px;
}

p, li { font-size: 0.92rem; line-height: 1.75; color: var(--text-2); }
p { margin: 14px 0; }
h2 + p, h3 + p { margin-top: 14px; }
strong { color: var(--ink); font-weight: 700; }

ul, ol { padding-left: 22px; margin: 14px 0; }
li { margin-bottom: 8px; }

a { color: var(--accent); text-decoration-color: var(--accent-mid); text-underline-offset: 2px; }
a:hover { text-decoration-color: currentColor; }

/* ===== Footer (same markup/styling as index.html) ===== */
.footer { background: #16304a; padding: 28px 32px 44px; }
.footer-inner { max-width: 1140px; margin: 0 auto; text-align: left; }
.footer-grid {
    display: grid; grid-template-columns: 1.3fr 1fr 1fr 1fr; gap: 40px;
}
.footer-col { display: flex; flex-direction: column; align-items: flex-start; gap: 7px; }
.footer-brand { gap: 12px; }
.footer-brand-logo { height: 96px; width: auto; filter: brightness(0) invert(1); opacity: 0.9; }
.footer-tagline {
    font-size: 0.82rem; color: rgba(255,255,255,0.55);
    line-height: 1.6; max-width: 15rem;
}
.footer-brand-links { display: flex; flex-direction: column; align-items: flex-start; gap: 7px; }
.footer-col-title {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.64rem; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: rgba(255,255,255,0.62);
    margin-bottom: 2px;
}
.footer-col a {
    font-size: 0.78rem; color: rgba(255,255,255,0.62);
    text-decoration: none; transition: color 0.2s ease;
    display: inline-flex; align-items: center;
}
.footer-col a:hover { color: rgba(255,255,255,0.75); }
.footer-icon-link { gap: 8px; }
.footer-icon-link svg { flex-shrink: 0; }
.footer-address {
    font-size: 0.76rem; color: rgba(255,255,255,0.55); line-height: 1.7;
}
.footer-address strong {
    display: block; margin-bottom: 4px;
    font-size: 0.78rem; font-weight: 600;
    color: rgba(255,255,255,0.62);
    line-height: 1.4;
}
.footer-address { line-height: 1.6; }
.footer-contact .footer-col-title + .footer-address { margin-top: 2px; }
.footer-copy {
    margin-top: 28px; padding-top: 16px;
    border-top: 1px solid rgba(255,255,255,0.07);
    font-size: 0.7rem; color: rgba(255,255,255,0.62);
    display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap;
}
/* Dark-surface override: the global outline (--accent-dark) is near-invisible
   on dark backgrounds (1.3-1.4:1 here, WCAG needs 3:1 for focus indicators).
   There are now four dark surfaces - footer, cta-band, .pricing-card.enterprise
   on index.html (its own override lives in that page's <style>, not here,
   since .pricing-card isn't a shared class), and .zoom-btn in
   assets/replicas.css (its own override lives there, since .zoom-btn isn't a
   shared page-chrome class either) - one past the three that were said to
   justify a --focus-ring token. Still not built here; the threshold hasn't
   just been reached, it's been passed with margin.
   This isn't only a focus-ring problem: --accent-dark is also the anchor
   colour buttons and structure use, and even --accent (turquoise, restored
   2026-09-03) only measures 3.34:1 against --ink - below AA for text. Any
   accent-coloured element on a dark surface needs an explicit white-alpha
   override, not an accent token. See the "Dark surfaces" note under
   Accessibility baseline in redesign/CLAUDE.md. */
.footer a:focus-visible, .footer button:focus-visible,
.cta-band a:focus-visible, .cta-band button:focus-visible {
    outline-color: rgba(255,255,255,0.8);
}

@media (max-width: 768px) {
    .footer-grid { grid-template-columns: 1fr; gap: 36px; }
    .footer-brand { order: 1; }
    .footer-nav { order: 2; }
    .footer-contact { order: 3; }
    .footer-legal { order: 4; }
    .footer-brand-logo { height: 56px; }
}

/* ===== Cookie banner (same markup/styling as index.html) ===== */
.cookie-banner {
    position: fixed; bottom: 20px; left: 20px; z-index: 1001;
    max-width: 420px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    box-shadow: var(--shadow-pop);
    padding: 20px 22px;
    transform: translateY(calc(100% + 40px));
    transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}
.cookie-banner.show { transform: none; }
.cookie-text { font-size: 0.78rem; color: var(--text-2); line-height: 1.6; }
.cookie-actions { display: flex; gap: 10px; margin-top: 14px; }
.cookie-btn {
    font-family: inherit; font-size: 0.76rem; font-weight: 600;
    padding: 9px 20px; border-radius: 9px;
    cursor: pointer; border: none; flex: 1;
    transition: all 0.2s ease;
}
.cookie-accept { background: var(--accent-dark); color: white; }
.cookie-accept:hover { background: var(--accent-darker); }
.cookie-decline { background: transparent; color: var(--text-2); border: 1px solid var(--border); }
.cookie-decline:hover { border-color: #c8d4da; color: var(--ink); }
@media (max-width: 520px) { .cookie-banner { left: 12px; right: 12px; bottom: 12px; max-width: none; } }

.scroll-top {
    position: fixed; right: 24px; bottom: 24px; z-index: 150;
    width: 44px; height: 44px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface); border: 1px solid var(--border);
    color: var(--ink); box-shadow: var(--shadow-pop);
    text-decoration: none;
    opacity: 0; visibility: hidden; transform: translateY(8px);
    transition: opacity 0.2s ease, transform 0.2s ease, border-color 0.2s ease;
}
.scroll-top.show { opacity: 1; visibility: visible; transform: none; }
.scroll-top:hover { border-color: var(--accent-mid); }
@media (prefers-reduced-motion: reduce) {
    .scroll-top { transition: opacity 0.15s ease; }
}

/* Fixed contact tab on the right edge, vertically centred. z-index 150 puts
   it in the same band as .scroll-top: under the nav (200), the mobile menu
   (199) and the modal overlay (1000), so an open modal covers it rather than
   letting it float on top of its own form.

   `color: white` is restated on hover as a guard: page.css's own `a:hover`
   set var(--ink) until BAR-1444, and this is an <a> - the trap that caught
   three button-styled anchors. It sets no colour now; if it ever does again,
   .contact-tab:hover at (0,2,0) still outranks it at (0,1,1). */
.contact-tab {
    position: fixed; right: 0; top: 50%; transform: translateY(-50%);
    z-index: 150;
    writing-mode: vertical-rl;
    background: var(--accent-dark); color: white;
    padding: 18px 9px;
    border-radius: 10px 0 0 10px;
    font-size: 0.74rem; font-weight: 600; letter-spacing: 0.03em;
    text-decoration: none;
    /* The inset white-alpha edge is for the dark grounds: over the footer and
       .cta-band, both #16304a, the tab is otherwise the same navy and loses its
       shape. On light grounds a faint white edge on white barely shows. One
       rule for both, so a tab straddling the boundary is right on each half. */
    box-shadow: var(--shadow-card), inset 0 0 0 1px rgba(255,255,255,0.3);
    transition: padding-right 0.2s ease, background 0.2s ease;
}
.contact-tab:hover {
    background: var(--accent-darker); color: white;
    padding-right: 13px;
}

@media (max-width: 600px) {
    .content { padding: 92px 20px 72px; }
    .scroll-top { right: 16px; bottom: 16px; }
}

/* ===== App window chrome ===== */
/* The window shell - frame, title bar, traffic-light dots, label. Not a
   replica part: two pages are about to use it for two different things, a
   video in index's hero and a replica on products, so it lives with the
   shared scaffolding rather than in replicas.css. Was split between index's
   <style> (.product-window) and replicas.css (.window-*) until this move. */
.product-window {
    margin-top: 10px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    box-shadow: var(--shadow-pop);
    overflow: hidden;
}
.window-bar {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 18px;
    border-bottom: 1px solid var(--border-soft);
    background: var(--bg-soft);
}
.window-dots { display: flex; gap: 6px; }
.window-dots span { width: 10px; height: 10px; border-radius: 50%; background: #dde5ea; }
.window-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.62rem; font-weight: 600; letter-spacing: 0.14em;
    color: var(--text-3);
}

/* ===== Video slots ===== */
/* The slot machinery: frame, <video> shown only once the file has loaded
   (page.js adds .has-video), and the placeholder until then. The animated
   question-and-tools scene in products' first slot is not machinery and
   stays in products.html's own <style>. */
.video-slot {
    position: relative; overflow: hidden;
    border-radius: 12px; border: 1px solid var(--border);
    background:
        linear-gradient(135deg, rgba(12,25,41,0.05), rgba(12,25,41,0.02) 55%, transparent),
        var(--bg-soft);
    aspect-ratio: 16 / 10;
}
.video-slot video {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; display: none;
}
.video-slot.has-video video { display: block; }
.video-slot.has-video .slot-placeholder { display: none; }
.slot-placeholder {
    position: absolute; inset: 0;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 10px;
}
.slot-placeholder img { height: 30px; width: auto; opacity: 0.22; filter: brightness(0); }
.slot-placeholder span {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.6rem; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-3);
}
.slot-placeholder-msg {
    font-family: 'Inter', sans-serif;
    font-size: 0.82rem; font-weight: 500;
    text-transform: none; letter-spacing: normal;
    color: var(--text-2);
}
/* The link over a button that is part of a film (see addFilmCta in page.js).
   It never shows itself, and it is only in the way while page.js says the
   button is on screen. Position and size come from the film's own .cta.json,
   as inline percentages - nothing here may carry a measurement, or the numbers
   would live in two places and one of them would be the stale one. */
.slot-cta { position: absolute; display: block; pointer-events: none; }
.slot-cta.live { pointer-events: auto; cursor: pointer; }

/* The controls on anything that moves: a film's pause and enlarge buttons,
   which page.js adds to every .video-slot[data-src], and the replica's own
   pause and zoom on products. One look for all four - see "Motion on the site"
   in CLAUDE.md. `.zoom-btn` is styled from here rather than from replicas.css,
   which loads later and would otherwise win.
   32px, which is above WCAG 2.2 AA's 24x24 minimum (SC 2.5.8) and small enough
   to sit on a picture without becoming part of it. 44px is the AAA size, and it
   is here too - as an invisible target on touch screens, below.
   The focus ring is white with a navy ring outside it: these sit on moving
   pictures, and either colour alone disappears against half of them. */
.slot-btn, .zoom-btn {
    position: absolute; z-index: 2; padding: 0;
    width: 32px; height: 32px; min-width: 32px; min-height: 32px;
    border-radius: 8px; border: none;
    background: var(--ink); color: #fff;
    box-shadow: 0 2px 8px rgba(11,28,38,0.16);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
}
.slot-btn:hover, .zoom-btn:hover { background: var(--accent-darker); box-shadow: 0 4px 14px rgba(11,28,38,0.28); }
.slot-btn:focus-visible, .zoom-btn:focus-visible {
    outline: 2px solid #fff; outline-offset: 0; box-shadow: 0 0 0 5px var(--ink);
}
.slot-btn svg, .zoom-btn svg { width: 15px; height: 15px; display: block; }
.slot-pause { left: 10px; bottom: 10px; }
/* .zoom-btn is the replica's, and it has to be placed here too: it is
   position: absolute from the rule above, and an absolute element with no
   offsets stays where it fell in the flow. On the replica that is 611px down
   inside a 301px .app-scale with overflow: hidden - out of sight, which is how
   it was published on 2026-10-01 and how it was found. */
.slot-zoom, .zoom-btn { right: 10px; bottom: 10px; }
/* A finger is not a pointer. The button keeps its size and the target grows
   around it, centred, to the 44px AAA size - nothing moves and nothing looks
   different. At 375px the two buttons sit about 250px apart, so the targets
   do not meet. */
@media (pointer: coarse) {
    .slot-btn::after, .zoom-btn::after {
        content: ''; position: absolute; left: 50%; top: 50%;
        width: 44px; height: 44px; transform: translate(-50%, -50%);
    }
}
/* Nothing to pause or enlarge until the file is there. */
.video-slot:not(.has-video) .slot-btn { display: none; }
#film-stage video { width: 100%; height: auto; display: block; border-radius: 10px; }

.video-slot-lg { aspect-ratio: 16 / 9; border-radius: 16px; box-shadow: var(--shadow-pop); max-width: 760px; margin-left: auto; margin-right: auto; }
.video-slot-lg .slot-placeholder img { height: 44px; }
