/* ==========================================================================
   NDX LLC — corporate site stylesheet
   --------------------------------------------------------------------------
   Static. No build step, no framework, no icon font, no external font fetch.
   Works by opening index.html directly from disk and on any static host.

   HOW TO READ THIS FILE
     1.  Tokens (:root)
     2.  Reset and base
     3.  Layout primitives
     4.  Type scale and shared components
     5.  Header and navigation
     6.  Hero
     7.  Problem band (dark slate)
     8.  Steps
     9.  Products
    10.  Feature grid
    11.  Pricing cards
    12.  Plan comparison table
    13.  FAQ
    14.  Closing CTA band
    15.  Footer
    16.  Company sections (services, values, contact)
    17.  Motion, focus and print

   ⚠️  COPY-SAFETY NOTES ARE MARKED "TRUTH:" THROUGHOUT.
       They mark places where the styling exists to support a claim the product
       can actually keep. Read them before you "improve" nearby copy. The single
       hardest rule: the product reads DIGITAL PDFs from their own text layer and
       REFUSES photographs and scans. Nothing on this site may suggest that a
       photo or a scan will work.

   Mobile-first: base rules target the smallest screens, then min-width queries
   add columns. Verified at 320 / 360 / 420 / 640 / 768 / 900 / 1080 / 1440 px.
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   --------------------------------------------------------------------------
   The "brand" block below is copied VERBATIM from the existing brand tokens in
   corp-site/fleet-section.html and must stay in sync with it: the live
   corporate site and the product share the same palette. Do not change these
   five: --ndx-cyan, --ndx-cyan-light, --ndx-cyan-dark, --ndx-slate, --ndx-muted.

   The "extensions" block adds only what a full multi-section site needs and the
   single-section fragment never did: readable cyan TEXT on light backgrounds, a
   light surface scale, and secondary text colours for light backgrounds.

   THE SITE IS NOW DARK. No value in either block above changed: the palette is
   the brand and it is shared with corp-site/fleet-section.html. What changed is
   which surface uses which token, through the "dark theme layer" at the bottom
   of :root. Three band tones replace the old white / #f8fafc alternation:

     --ndx-bg        #0b1120   base: body, hero, .section--white, footer
     --ndx-bg-alt    #111827   .section--dark and .cta-band, plus the glow
     .section--surface          = --ndx-bg-alt raised by --ndx-surface-dark
                                -> #1b2130
     --ndx-card      rgba(255,255,255,.04)  cards, on any band
     --ndx-card-2    rgba(255,255,255,.07)  recessed or secondary cards

   The gap between two neighbouring bands is 1.06:1 (base to slate) and 1.11:1
   (slate to raised) — wider than the 1.05:1 the old white / #f8fafc pair had, so
   the bands stay readable as bands without any band shouting. Every card on top
   of a band is one more --ndx-surface-dark step up. The light-surface scale
   below (--ndx-surface, --ndx-ink*, --ndx-border*, --ndx-cyan-ink) is
   deliberately kept: it is unused on screen and is what @media print falls
   back to.

   Contrast (WCAG 2.1). Computed from the token values; the README carries the
   table measured on the rendered pixels, all 24 pairs of which pass.
     #111827 on #06b6d4 = 7.31:1  → cyan buttons MUST keep dark slate labels.
     #ffffff on #06b6d4 = 2.43:1  → white on cyan FAILS. Never do it.
     #111827 on #0891b2 = 4.82:1  → cyan hover state still passes.
     #0e7490 on #0b1120 = 3.51:1  → cyan-ink on dark FAILS. Never do it.
     #9ca3af on #0b1120 = 7.42:1  → body text on the base band.
     #9ca3af on #111827 = 6.99:1  → body text on the slate band.
     #9ca3af on #1b2130 = 6.33:1  → body text on the raised band.
     #9ca3af on #242a38 = 5.65:1  → body text on a card on the raised band.
     #22d3ee on #0b1120 = 10.42:1 → cyan as text/link on the base band.
     #22d3ee on #1b2130 = 8.89:1  → cyan as text/link on the raised band.
     #ffffff on #0b1120 = 18.83:1 → headings.
   ========================================================================== */
:root {
  /* ---- brand tokens (verbatim from fleet-section.html) ---- */
  --ndx-cyan: #06b6d4;
  --ndx-cyan-light: #22d3ee;
  --ndx-cyan-dark: #0891b2;
  --ndx-blue: #3b82f6;
  --ndx-blue-deep: #2563eb;
  --ndx-slate: #111827;
  --ndx-white: #ffffff;
  --ndx-border: #e5e7eb;
  --ndx-muted: #9ca3af; /* muted text ON DARK SLATE only */

  /* ---- extensions for this multi-section site ---- */
  --ndx-cyan-ink: #0e7490; /* cyan as TEXT on light surfaces (5.36:1 on #fff) */
  --ndx-slate-soft: #1f2937; /* raised card / border surface on dark slate */
  --ndx-slate-deep: #0b1120; /* footer, one step below the slate */
  --ndx-ink: #111827; /* primary text on light = the dark slate */
  --ndx-ink-2: #374151; /* strong secondary text on light (10.31:1) */
  --ndx-ink-muted: #4b5563; /* body/secondary text on light (7.56:1) */
  --ndx-surface: #f8fafc; /* alternating light band */
  --ndx-surface-2: #f1f5f9; /* cards on light */
  --ndx-border-strong: #cbd5e1;
  --ndx-border-dark: rgba(255, 255, 255, 0.14);
  --ndx-border-dark-strong: rgba(255, 255, 255, 0.28);
  --ndx-surface-dark: rgba(255, 255, 255, 0.04);
  --ndx-surface-dark-2: rgba(255, 255, 255, 0.07);

  /* ---- dark theme layer (added when the site went dark) ----
     Names, not new colours. Every screen surface, text role and line in this
     file goes through one of these, so the palette above stays the single
     source of truth for the brand. */
  --ndx-bg: #0c111c; /* = the app's --background (221 39% 8%), so the two sites match */
  --ndx-bg-alt: #111827; /* = the app's --card (221 39% 11%) */
  --ndx-card: var(--ndx-surface-dark); /* rgba(255,255,255,.04) — a card */
  --ndx-card-2: var(--ndx-surface-dark-2); /* rgba(255,255,255,.07) */
  --ndx-hairline: var(--ndx-border-dark); /* separators: 1.48:1, decoration */
  --ndx-hairline-2: var(--ndx-border-dark-strong); /* 2.47:1, still decoration */
  /* The boundary of a CONTROL (button, nav toggle) is the only thing that
     identifies it, so WCAG 2.1 1.4.11 applies to it and it needs 3:1 against
     the surface it sits on. 42% white over --ndx-bg is 4.08:1; neither token
     above reaches 3:1, so neither may be used for a control's outline. */
  --ndx-outline: rgba(255, 255, 255, 0.42);
  --ndx-text: var(--ndx-white); /* headings and primary text */
  --ndx-text-body: #94a3b8; /* = the app's --muted-foreground (215 20% 65%) */
  --ndx-accent: #07b6d5; /* = the app's --primary, NOT the brighter --ndx-cyan-light */

  /* ---- shape, rhythm, type ---- */
  --ndx-radius: 16px;
  --ndx-radius-sm: 12px;
  --ndx-radius-pill: 999px;
  --ndx-container: 1160px;
  --ndx-gutter: clamp(20px, 5vw, 40px);
  --ndx-header-h: 68px;
  --ndx-section-y: clamp(56px, 8vw, 104px);

  /* Inter is referenced BY NAME ONLY and deliberately not fetched from a CDN.
     If the visitor's system has it, it is used; otherwise the native UI font of
     the platform is used. This is the same choice the existing brand fragment
     makes, and it removes a render-blocking third-party request, which is what
     keeps first paint fast on a slow connection. */
  --ndx-font: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    Oxygen, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif;
  --ndx-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas,
    "Liberation Mono", monospace;

  --ndx-shadow-sm: 0 1px 2px rgba(17, 24, 39, 0.06);
  --ndx-shadow-md: 0 10px 30px -12px rgba(17, 24, 39, 0.18);
  --ndx-shadow-cyan: 0 14px 34px -14px rgba(6, 182, 212, 0.5);
  /* The two shadows above are dark-on-dark and do nothing now. Depth on a dark
     surface comes from the card fill and its hairline; this is the one shadow
     that still reads, for the few surfaces that are meant to lift off the page. */
  --ndx-shadow-dark: 0 18px 40px -20px rgba(0, 0, 0, 0.85);

  --ndx-focus: 2px solid var(--ndx-cyan-dark);
  --ndx-focus-dark: 2px solid var(--ndx-cyan-light);
  --ndx-focus-offset: 3px;
}

/* ==========================================================================
   2. RESET AND BASE
   ========================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--ndx-font);
  font-size: 1rem;
  line-height: 1.65;
  /* Body copy is the muted grey, not white: 18.9:1 of white body text on a
     near-black page is a glare, and #9ca3af is 7.30:1 — AA with room to spare.
     White is reserved for headings and for the strongest words in a sentence. */
  color: var(--ndx-text-body);
  background-color: var(--ndx-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden; /* guards the hero glow on very narrow screens */
}

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0;
  line-height: 1.2;
  font-weight: 750;
  letter-spacing: -0.015em;
  text-wrap: balance;
  color: var(--ndx-text); /* 18.86:1 on the base band */
}

h1 {
  font-size: clamp(2rem, 6.2vw, 3.4rem);
  letter-spacing: -0.025em;
}
h2 {
  font-size: clamp(1.6rem, 4.2vw, 2.5rem);
  letter-spacing: -0.02em;
}
h3 {
  font-size: clamp(1.125rem, 2.2vw, 1.375rem);
}
h4 {
  font-size: 1.0625rem;
}

p {
  margin: 0 0 1em;
}
p:last-child {
  margin-bottom: 0;
}

ul,
ol {
  margin: 0;
  padding: 0;
}

a {
  /* TRUTH: a link must be readable as a link. On dark the readable cyan is the
     light one (#22d3ee, 10.46:1 on the base band); --ndx-cyan itself is 7.76:1
     but is reserved for the cyan buttons, where it is a surface, not text.
     --ndx-cyan-ink (#0e7490) was the light-surface answer and is 1.75:1 here:
     it must never appear on a dark surface: 3.51:1. */
  color: var(--ndx-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

a:hover {
  color: var(--ndx-white);
}

img,
svg,
video {
  max-width: 100%;
}

svg {
  display: block;
}

/* Numerals in prices and limits should not shift width between tiers. */
.num {
  font-variant-numeric: tabular-nums;
}

/* Inline SVG sprite holder. It must stay in the layout tree for same-document
   <use href="#..."> to resolve, so it is collapsed to zero size rather than
   given display:none, which breaks <use> in some browsers. */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* ==========================================================================
   3. LAYOUT PRIMITIVES
   ========================================================================== */
.container {
  width: 100%;
  max-width: var(--ndx-container);
  margin-inline: auto;
  padding-inline: var(--ndx-gutter);
}

.section {
  padding-block: var(--ndx-section-y);
  /* Anchored sections must not slide under the sticky header. */
  scroll-margin-top: calc(var(--ndx-header-h) + 16px);
}

.section--tight {
  padding-block: clamp(40px, 6vw, 72px);
}

/* The alternating band. It is NOT a second colour: it is --ndx-bg-alt raised by
   one --ndx-surface-dark, exactly the step a card takes off its band, so the
   whole rhythm is built from the brand slate and the brand's own raised
   surface. Effective colour over nothing but the slate: #1a2130. */
.section--surface {
  background-color: var(--ndx-bg-alt);
  background-image: linear-gradient(
    var(--ndx-surface-dark),
    var(--ndx-surface-dark)
  );
}

.section--white {
  background-color: var(--ndx-bg);
}

/* The slate bands. --ndx-slate is a brand token and this is still the band that
   carries the problem statement and the closing CTA, so it is still the
   interruption in the scroll — but on a dark page the interruption has to be
   LIGHTER than the base, so it is the flat slate plus the cyan and blue glow,
   separated from its neighbours by a hairline. Page rhythm is now
   base → raised → base → slate+glow → raised → slate+glow → base. */
.section--dark {
  position: relative;
  color: var(--ndx-white);
  background-color: var(--ndx-bg-alt);
  border-block: 1px solid var(--ndx-hairline);
  background-image: radial-gradient(
      58% 55% at 8% 0%,
      rgba(6, 182, 212, 0.16) 0%,
      rgba(6, 182, 212, 0) 72%
    ),
    radial-gradient(
      46% 46% at 100% 100%,
      rgba(37, 99, 235, 0.16) 0%,
      rgba(37, 99, 235, 0) 72%
    );
}

.stack > * + * {
  margin-top: 1rem;
}

/* One-off spacing utility, used where a paragraph follows a component rather
   than another paragraph. It lives here instead of as a style attribute on the
   element so that every declaration stays in this file. */
.mt-lg {
  margin-top: 26px;
}

/* ==========================================================================
   4. TYPE SCALE AND SHARED COMPONENTS
   ========================================================================== */

/* --- eyebrow / kicker --- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 18px;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ndx-accent);
}

.eyebrow::before {
  content: "";
  width: 26px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--ndx-cyan), var(--ndx-blue));
}

.section--dark .eyebrow {
  color: var(--ndx-cyan-light);
}

/* --- lead paragraphs --- */
.lead {
  font-size: clamp(1rem, 1.5vw, 1.1875rem);
  line-height: 1.7;
  color: var(--ndx-text-body);
  max-width: 68ch;
}

.section--dark .lead {
  color: var(--ndx-muted);
}

/* --- section heading block --- */
.section-head {
  max-width: 760px;
  margin-bottom: clamp(32px, 5vw, 56px);
}

.section-head--center {
  margin-inline: auto;
  text-align: center;
}

.section-head--center .eyebrow {
  justify-content: center;
}

.section-head--center .lead {
  margin-inline: auto;
}

.section-head h2 {
  margin-bottom: 16px;
}

/* --- badges --- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: var(--ndx-radius-pill);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.badge--new {
  background: rgba(6, 182, 212, 0.14);
  border: 1px solid rgba(6, 182, 212, 0.45);
  color: var(--ndx-accent);
}

.badge--live {
  background: rgba(6, 182, 212, 0.16);
  border: 1px solid rgba(6, 182, 212, 0.5);
  color: var(--ndx-accent);
}

.badge--live .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  /* A graphic, not text: 3:1 is the bar and the light cyan is 10.46:1. */
  background: var(--ndx-cyan-light);
}

.badge--soon {
  background: var(--ndx-card-2);
  border: 1px solid var(--ndx-hairline-2);
  color: var(--ndx-text-body);
}

.section--dark .badge--new,
.section--dark .badge--live {
  color: var(--ndx-cyan-light);
}

/* --- buttons ---
   TRUTH: the label on every cyan button is the dark slate, never white.
   #ffffff on #06b6d4 is 2.43:1 and fails WCAG AA; #111827 is 7.31:1. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 14px 26px;
  border: 1px solid transparent;
  border-radius: var(--ndx-radius-pill);
  font-family: inherit;
  font-size: 1rem;
  font-weight: 650;
  line-height: 1.15;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.btn--primary {
  background: var(--ndx-cyan);
  color: var(--ndx-slate);
  box-shadow: var(--ndx-shadow-cyan);
}

.btn--primary:hover {
  background: var(--ndx-cyan-dark);
  color: var(--ndx-slate);
}

.btn--ghost {
  background: transparent;
  /* The outline IS the button, so 1.4.11 applies to it: 3.94:1. */
  border-color: var(--ndx-outline);
  color: var(--ndx-text);
}

.btn--ghost:hover {
  border-color: var(--ndx-cyan-light);
  color: var(--ndx-accent);
  background: var(--ndx-card-2);
}

/* The dark bands used to need their own ghost button because the page was
   light. Every surface is dark now and the base rule above is already the right
   one; these survive only so the hover on the glow bands matches the base. */
.section--dark .btn--ghost,
.cta-band .btn--ghost {
  border-color: var(--ndx-outline);
  color: var(--ndx-white);
}

.section--dark .btn--ghost:hover,
.cta-band .btn--ghost:hover {
  border-color: var(--ndx-cyan-light);
  color: var(--ndx-cyan-light);
  background: var(--ndx-card-2);
}

.btn--sm {
  min-height: 44px;
  padding: 12px 20px;
  font-size: 0.9375rem;
}

.btn--block {
  width: 100%;
}

.btn-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
}

@media (min-width: 520px) {
  .btn-row {
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
  }
  .btn-row .btn {
    width: auto;
  }
}

/* A bare text link that sits next to buttons and still gets a 44px target. */
.link-cta {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.9375rem;
  font-weight: 650;
  color: var(--ndx-accent);
}

.section--dark .link-cta,
.cta-band .link-cta {
  color: var(--ndx-cyan-light);
}

.section--dark .link-cta:hover,
.cta-band .link-cta:hover {
  color: var(--ndx-white);
}

/* --- small print --- */
.note {
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--ndx-text-body);
  max-width: 80ch;
}

.section--dark .note {
  color: var(--ndx-muted);
}

/* --- inline SVG icon chip --- */
.icon-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 11px;
  background: rgba(6, 182, 212, 0.13);
  border: 1px solid rgba(6, 182, 212, 0.34);
  color: var(--ndx-accent);
}

.icon-chip svg {
  width: 21px;
  height: 21px;
}

.section--dark .icon-chip {
  color: var(--ndx-cyan-light);
}

/* --- tick list --- */
.ticks {
  list-style: none;
  margin: 0;
  padding: 0;
}

.ticks li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--ndx-text-body);
}

.ticks li + li {
  margin-top: 10px;
}

.ticks svg {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  margin-top: 3px;
  color: var(--ndx-accent);
}

.section--dark .ticks li {
  color: var(--ndx-muted);
}

.section--dark .ticks svg {
  color: var(--ndx-cyan-light);
}

/* A tick list item whose lead-in is a bolded fact rather than a feature name.
   The lead-in takes the primary text colour so it reads as the claim; the rest
   stays secondary. */
.ticks li strong {
  color: var(--ndx-text);
  font-weight: 700;
}

.section--dark .ticks li strong {
  color: var(--ndx-white);
}

/* --- two-up panels, used for the accepted / refused input comparison ---
   TRUTH: .panel--stop is not decoration. It is the visual counterpart to the
   accepted panel, and it exists so that "no image reading" is as prominent as
   the feature list. A visitor must not be able to skim past it. */
.split {
  display: grid;
  gap: 20px;
}

@media (min-width: 840px) {
  .split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }
}

.panel {
  padding: 26px 24px;
  border: 1px solid var(--ndx-hairline);
  border-radius: var(--ndx-radius);
  background: var(--ndx-card);
  box-shadow: var(--ndx-shadow-dark);
}

.panel--stop {
  /* Stronger outline than the accepted panel: this panel carries the refusal,
     and the whole point of it is that a visitor cannot skim past it. */
  border-color: var(--ndx-outline);
  background: var(--ndx-card-2);
  box-shadow: none;
}

.panel__head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 20px;
}

.panel__head h3 {
  margin: 0;
}

/* The refused panel's icon chip is deliberately the grey one: it is the
   counterpart of the cyan chip on the accepted panel, and taking the accent off
   it is what makes the two panels read as "this one" and "not this one". */
.panel--stop .icon-chip {
  background: var(--ndx-card-2);
  border-color: var(--ndx-outline);
  color: var(--ndx-muted);
}

.panel--stop .ticks svg {
  color: var(--ndx-text-body);
}

.panel__foot {
  margin: 20px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--ndx-hairline-2);
  font-size: 0.875rem;
  line-height: 1.65;
  color: var(--ndx-text-body);
}

/* ==========================================================================
   5. HEADER AND NAVIGATION
   --------------------------------------------------------------------------
   The mobile panel is driven by app.js, which sets [data-open] and
   aria-expanded. If JavaScript never runs, `html.no-js` (set by the one-line
   script in <head>, removed when JS is available) turns the panel into a
   normal visible list so navigation is never trapped behind a dead button.
   ========================================================================== */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 18px;
  /* The one place the flat cyan is a surface and the slate is its label, the
     same 7.31:1 pair the primary button uses — and unlike the slate it
     replaces, it stands out against a dark page. */
  background: var(--ndx-cyan);
  color: var(--ndx-slate);
  font-weight: 650;
  text-decoration: none;
  border-radius: 0 0 var(--ndx-radius-sm) 0;
}

.skip-link:focus {
  left: 0;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  /* OPAQUE, and that is a deliberate change of two things at once.
     It used to be a translucent, blurred sheet (rgba(255,255,255,.9) + a 10px
     backdrop blur), which is a light-theme device: on a white page a 10% bleed
     of the content underneath is invisible.
     On a dark page it is not, for one specific reason: the logo's near-black
     field is blended with `screen`, and a blend can only reproduce the backdrop
     it is given. Where the header is 92% opaque, the backdrop under the image is
     not the same colour as the header beside it, so the image's box ends up 1-11
     levels off the surrounding pixels while coloured bands scroll underneath —
     measured as an 11/255 step at the image's edge, i.e. the one visible square
     the blend was chosen to avoid. At full opacity the blend is exact.
     The blur is dropped with it, because a blur behind an opaque background does
     nothing but allocate a compositing layer. The header is the same tone as
     --ndx-bg, so it reads as part of the page rather than as a bar across it. */
  background: var(--ndx-bg);
  border-bottom: 1px solid var(--ndx-hairline);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: var(--ndx-header-h);
}

/* --- brand: the real logo, and nothing else ---
   The asset is a stacked lockup: an NDX monogram above the line "Next Digital
   Xperience". The old text wordmark beside it printed that same string a second
   time, in the same words, so the logo replaces the wordmark instead of sitting
   next to it. The company name is not lost: it is the image's alt text, which
   is the link's accessible name. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  padding: 8px 0;
}

/* The asset is 450x450, with the lockup (382x198 px) floating in a near-black
   field that is NOT transparent — the corners sample rgb(1,1,1). Two
   consequences, both handled here rather than by editing the asset:
     1. `mix-blend-mode: screen` maps that near-black field onto whatever is
        behind the image, so the black square disappears against a dark surface
        while the light artwork is preserved. Measured in the README.
     2. The box is cropped to the lockup with object-fit, so the invisible
        padding does not eat the header's height budget. object-fit scales by
        width (the source is square), so the visible source window is
        44 / (84/450) = 236 px tall, centred at y 107..343; the artwork spans
        y 134..331, so nothing is clipped.
   width and height are fixed in CSS and repeated on the element, so the header
   height never depends on when the image decodes. */
.brand__logo {
  display: block;
  width: 58px;
  height: 30px;
  object-fit: cover;
  object-position: 50% 50%;
  mix-blend-mode: screen;
}

.nav {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  padding: 0;
  /* A control's border is the only thing that says it is a control: 3.94:1. */
  border: 1px solid var(--ndx-outline);
  border-radius: var(--ndx-radius-sm);
  background: var(--ndx-card);
  color: var(--ndx-text);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.nav-toggle svg {
  width: 22px;
  height: 22px;
}

.nav-toggle__close {
  display: none;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__open {
  display: none;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__close {
  display: block;
}

.nav-panel {
  display: none;
}

.nav-panel[data-open="true"] {
  display: block;
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  padding: 12px var(--ndx-gutter) 22px;
  /* Opaque on purpose: the panel is a sheet that content scrolls under, and a
     translucent one would put body text behind the nav labels. */
  background: var(--ndx-bg-alt);
  border-bottom: 1px solid var(--ndx-outline);
  box-shadow: var(--ndx-shadow-dark);
}

.nav-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
}

.nav-list a {
  display: flex;
  align-items: center;
  min-height: 46px;
  padding: 10px 4px;
  font-size: 1rem;
  font-weight: 600;
  color: var(--ndx-text);
  text-decoration: none;
  border-bottom: 1px solid var(--ndx-hairline);
}

.nav-list a:hover {
  color: var(--ndx-accent);
}

.nav-list a[aria-current="page"],
.nav-list a[aria-current="true"] {
  color: var(--ndx-accent);
}

.nav-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Without JavaScript the panel is always visible and the toggle is hidden. */
html.no-js .nav-toggle {
  display: none;
}
html.no-js .nav-panel {
  display: block;
  position: static;
  padding: 0;
  border: 0;
  box-shadow: none;
}
html.no-js .nav-list {
  flex-direction: row;
  flex-wrap: wrap;
}
html.no-js .nav-actions {
  flex-direction: row;
}

@media (min-width: 900px) {
  .nav-toggle {
    display: none;
  }

  .nav {
    gap: 22px;
  }

  .nav-panel,
  .nav-panel[data-open="true"] {
    display: flex;
    align-items: center;
    gap: 22px;
    position: static;
    padding: 0;
    border: 0;
    box-shadow: none;
    background: transparent;
  }

  .nav-list {
    flex-direction: row;
    align-items: center;
    gap: 22px;
    margin: 0;
  }

  .nav-list a {
    min-height: 44px;
    padding: 8px 2px;
    font-size: 0.9375rem;
    border-bottom: 2px solid transparent;
  }

  .nav-list a:hover {
    border-bottom-color: var(--ndx-hairline-2);
  }

  .nav-list a[aria-current="page"] {
    border-bottom-color: var(--ndx-cyan);
  }

  .nav-actions {
    flex-direction: row;
    align-items: center;
  }
}

/* ==========================================================================
   6. HERO
   --------------------------------------------------------------------------
   One dominant call to action. The secondary action is a text link, not a
   second button, so there is never a question about which one to press.
   ========================================================================== */
.hero {
  position: relative;
  padding-block: clamp(44px, 7vw, 84px) clamp(52px, 8vw, 96px);
  background-color: var(--ndx-bg);
  /* The two brand glows were written for a white band, where they tinted it
     down; on the base band they tint it up. Same alphas, opposite direction —
     which is why they were left exactly as they were: at 13% and 10% they lift
     the corners by a measured 20 and 14 levels, colouring a dark hero
     noticeably without either accent turning into a glare. */
  background-image: radial-gradient(
      62% 58% at 12% 0%,
      rgba(6, 182, 212, 0.13) 0%,
      rgba(6, 182, 212, 0) 70%
    ),
    radial-gradient(
      48% 48% at 100% 8%,
      rgba(37, 99, 235, 0.1) 0%,
      rgba(37, 99, 235, 0) 72%
    );
}

.hero__grid {
  display: grid;
  gap: clamp(34px, 5vw, 56px);
  align-items: center;
}

.hero h1 {
  margin-bottom: 20px;
}

.hero__lead {
  margin-bottom: 26px;
}

.hero__meta {
  margin-top: 20px;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--ndx-text-body);
}

.hero__meta strong {
  color: var(--ndx-text);
}

@media (min-width: 980px) {
  .hero__grid {
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  }
}

/* --- the "what it reads" callout: the most important box on the site ---
   TRUTH: this states the boundary of the product in the user's own words, in
   the first screen, before any price or feature claim. The product accepts the
   digital PDF issued by the authority and refuses photographs and scans. */
.reads-box {
  display: flex;
  gap: 12px;
  margin-top: 26px;
  padding: 16px 18px;
  border: 1px solid rgba(6, 182, 212, 0.42);
  border-left: 3px solid var(--ndx-cyan);
  border-radius: var(--ndx-radius-sm);
  /* Raised from 6% to 10% when the site went dark: a 6% cyan wash over a white
     band was a visible tint, over a near-black one it was almost nothing, and
     this box is not allowed to recede. Body text on the 10% wash still
     measures 6.45:1 on the base band and 5.37:1 on the raised band. */
  background: rgba(6, 182, 212, 0.1);
}

.reads-box svg {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  color: var(--ndx-accent);
}

.reads-box p {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--ndx-text-body);
}

.reads-box strong {
  color: var(--ndx-text);
}

/* --- illustrative flow card (pure HTML/CSS, no image to download) ---
   TRUTH: labelled "Illustrative example". It must never be dressed up to look
   like a screenshot of a real customer's document. */
.flow {
  margin: 0;
  padding: 20px;
  border: 1px solid var(--ndx-hairline);
  border-radius: var(--ndx-radius);
  background: var(--ndx-card);
  box-shadow: var(--ndx-shadow-dark);
}

.flow__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--ndx-hairline);
}

.flow__title {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 750;
  color: var(--ndx-text);
}

.flow__list {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: flow;
}

.flow__item {
  position: relative;
  display: flex;
  gap: 12px;
  padding-bottom: 16px;
}

.flow__item:last-child {
  padding-bottom: 0;
}

/* connector line between the steps */
.flow__item:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 32px;
  bottom: 0;
  width: 2px;
  background: linear-gradient(
    180deg,
    rgba(6, 182, 212, 0.55),
    rgba(6, 182, 212, 0.12)
  );
}

.flow__num {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(6, 182, 212, 0.14);
  border: 1px solid rgba(6, 182, 212, 0.45);
  color: var(--ndx-accent);
  font-size: 0.8125rem;
  font-weight: 800;
}

.flow__body {
  min-width: 0;
}

.flow__label {
  margin: 4px 0 6px;
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--ndx-text);
}

.flow__fields {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 4px 10px;
  margin: 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--ndx-card-2);
  font-size: 0.8125rem;
  line-height: 1.5;
}

.flow__fields dt {
  color: var(--ndx-text-body);
}

.flow__fields dd {
  margin: 0;
  font-family: var(--ndx-font-mono);
  font-size: 0.8125rem;
  color: var(--ndx-text);
  overflow-wrap: anywhere;
}

.flow__caption {
  margin: 16px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--ndx-hairline);
  font-size: 0.75rem;
  line-height: 1.55;
  color: var(--ndx-text-body);
}

/* ==========================================================================
   7. PROBLEM BAND (dark slate)
   ========================================================================== */
.problem__grid {
  display: grid;
  gap: clamp(28px, 4vw, 48px);
}

@media (min-width: 900px) {
  .problem__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
  }
}

.problem-card {
  padding: 22px;
  border: 1px solid var(--ndx-border-dark);
  border-radius: var(--ndx-radius);
  background: var(--ndx-surface-dark);
}

.problem-card h3 {
  margin-bottom: 10px;
  color: var(--ndx-white);
}

.problem-card p {
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--ndx-muted);
}

/* The 30-day clock is the reason the product exists and the reason overage is
   never blocked. It is stated as a fact about the deadline, not as legal advice. */
.deadline {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 0 0 16px;
  color: var(--ndx-white);
}

.deadline__num {
  font-size: clamp(2.5rem, 7vw, 3.75rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ndx-cyan-light);
}

.deadline__label {
  font-size: 0.9375rem;
  font-weight: 650;
  line-height: 1.4;
  color: var(--ndx-white);
  max-width: 22ch;
}

/* ==========================================================================
   8. STEPS
   ========================================================================== */
.steps {
  display: grid;
  gap: 18px;
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: step;
}

.step {
  position: relative;
  padding: 24px 22px;
  border: 1px solid var(--ndx-hairline);
  border-radius: var(--ndx-radius);
  background: var(--ndx-card);
  box-shadow: var(--ndx-shadow-dark);
}

.step::before {
  counter-increment: step;
  content: counter(step);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-bottom: 14px;
  border-radius: 50%;
  background: rgba(6, 182, 212, 0.14);
  border: 1px solid rgba(6, 182, 212, 0.45);
  color: var(--ndx-accent);
  font-size: 0.875rem;
  font-weight: 800;
}

.step h3 {
  margin-bottom: 10px;
}

.step p {
  font-size: 0.9375rem;
  color: var(--ndx-text-body);
}

@media (min-width: 640px) {
  .steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1040px) {
  .steps {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* ==========================================================================
   9. PRODUCTS
   --------------------------------------------------------------------------
   TRUTH: exactly one card carries the "Live now" badge. Every other product on
   this site carries "Coming soon" plus a plain sentence saying it is not
   available yet and has no release date. Do not remove that sentence, and do
   not add a price, a date, or a trial link to a card that is not live.
   ========================================================================== */
.products-note {
  margin: 0 0 clamp(26px, 4vw, 38px);
  padding: 16px 20px;
  border: 1px solid var(--ndx-hairline-2);
  border-left: 3px solid var(--ndx-cyan);
  border-radius: var(--ndx-radius-sm);
  background: var(--ndx-card-2);
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--ndx-text-body);
}

.products-note strong {
  color: var(--ndx-text);
}

.products {
  display: grid;
  gap: 20px;
}

.product {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 26px 24px;
  border: 1px solid var(--ndx-hairline);
  border-radius: var(--ndx-radius);
  background: var(--ndx-card);
}

.product--live {
  border: 2px solid var(--ndx-cyan);
  box-shadow: var(--ndx-shadow-dark);
}

/* The "not live yet" card is recessed rather than raised: one more step of white
   than a normal card would have made the unavailable product shout louder than
   the live one. */
.product--soon {
  background: var(--ndx-bg-alt);
  border-style: dashed;
}

.product__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.product h3 {
  margin-bottom: 10px;
}

.product__text {
  flex: 1 1 auto;
  margin-bottom: 20px;
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--ndx-text-body);
}

.product--soon h3 {
  color: var(--ndx-muted);
}

.product__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  padding-top: 18px;
  border-top: 1px solid var(--ndx-hairline);
}

@media (min-width: 900px) {
  .products {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ==========================================================================
   10. FEATURE GRID
   ========================================================================== */
.features {
  display: grid;
  gap: 18px;
}

.feature {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 24px 22px;
  border: 1px solid var(--ndx-hairline);
  border-radius: var(--ndx-radius);
  background: var(--ndx-card);
}

.feature .icon-chip {
  margin-bottom: 16px;
}

.feature h3 {
  margin-bottom: 10px;
}

.feature p {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--ndx-text-body);
}

@media (min-width: 640px) {
  .features {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1000px) {
  .features {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ==========================================================================
   11. PRICING CARDS
   --------------------------------------------------------------------------
   TRUTH — the numbers in the markup are not decorative and must not be edited
   without editing the application (saas/src/lib/plans.ts) in the same change:
     price/month   €49 / €149 / €499 / €999
     fines a month  50 / 300 / 2,000 / 6,000
     users (up to)  3 / 10 / 50 / 150
     vehicles (up to) 50 / 300 / 2,000 / 6,000
   Users and vehicles are stated as "up to" because they are coverage language,
   not enforced limits. Only the fine allowance is measured. Never restate them
   as "N vehicles included and enforced".
   ========================================================================== */
.plans {
  display: grid;
  gap: 20px;
  align-items: start;
}

.plan {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 28px 24px;
  border: 1px solid var(--ndx-hairline);
  border-radius: var(--ndx-radius);
  background: var(--ndx-card);
}

.plan--featured {
  border: 2px solid var(--ndx-cyan);
  background: linear-gradient(
    180deg,
    rgba(6, 182, 212, 0.14) 0%,
    rgba(6, 182, 212, 0.03) 44%,
    rgba(255, 255, 255, 0) 100%
  );
  box-shadow: var(--ndx-shadow-dark);
}

.plan__badge {
  display: inline-block;
  align-self: flex-start;
  margin-bottom: 14px;
  padding: 4px 11px;
  border-radius: var(--ndx-radius-pill);
  background: var(--ndx-cyan);
  color: var(--ndx-slate); /* 7.31:1 — see the button note at the top */
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.plan__name {
  margin-bottom: 6px;
}

.plan__for {
  margin-bottom: 18px;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ndx-text-body);
}

.price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 4px;
  color: var(--ndx-text);
}

.price__amount {
  font-size: clamp(1.875rem, 3vw, 2.25rem);
  line-height: 1;
  font-weight: 800;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.price__period {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ndx-text-body);
}

.plan__limits {
  margin: 0 0 20px;
  font-size: 0.8125rem;
  line-height: 1.55;
  color: var(--ndx-text-body);
}

.plan__limits strong {
  color: var(--ndx-text);
  font-weight: 700;
}

.plan .ticks {
  flex: 1 1 auto;
  margin-bottom: 22px;
  padding-top: 20px;
  border-top: 1px solid var(--ndx-hairline);
}

/* Tailored is not a priced tier: full width beneath the four tiers, no price. */
.plan--tailored {
  grid-column: 1 / -1;
  border-style: dashed;
  border-color: var(--ndx-outline);
  background: var(--ndx-bg-alt);
}

.plan--tailored .plan__for {
  max-width: 74ch;
}

.plan--tailored .ticks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 28px;
  max-width: 760px;
}

.plan--tailored .ticks li + li {
  margin-top: 0;
}

.plan--tailored .btn {
  align-self: flex-start;
  width: auto;
}

@media (min-width: 700px) {
  .plans {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1080px) {
  .plans {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  .plan--featured {
    margin-top: -12px;
  }
}

/* --- overage / allowance note ---
   TRUTH: this block is the reason a visitor can trust the pricing table. It says
   exceeding the fine allowance never blocks work, that extras are billed at
   €1.00 each and counted in the dashboard, and why (the 30-day deadline). It is
   a selling point and a commitment, not small print. Keep it on both pages. */
.overage {
  margin-top: 22px;
  padding: 22px 24px;
  border: 1px solid rgba(6, 182, 212, 0.42);
  border-left: 3px solid var(--ndx-cyan);
  border-radius: var(--ndx-radius);
  background: var(--ndx-card-2);
  scroll-margin-top: calc(var(--ndx-header-h) + 16px);
}

.overage h3 {
  margin-bottom: 10px;
  font-size: 1.0625rem;
}

.overage p {
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--ndx-text-body);
  max-width: 88ch;
}

.overage strong {
  color: var(--ndx-text);
  font-weight: 700;
}

.pricing-foot {
  margin-top: 20px;
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--ndx-text-body);
  max-width: 88ch;
}

/* ==========================================================================
   12. PLAN COMPARISON TABLE
   --------------------------------------------------------------------------
   This table is why the old "https://app.ndx-llc.com/pricing" link is gone:
   that route does not exist in the application. Plan comparison now resolves to
   this in-page section. Do not point it back at the app.
   ========================================================================== */
.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--ndx-hairline);
  border-radius: var(--ndx-radius);
  background: var(--ndx-card);
  -webkit-overflow-scrolling: touch;
}

.table-scroll:focus-visible {
  outline: var(--ndx-focus-dark);
  outline-offset: var(--ndx-focus-offset);
}

.compare {
  width: 100%;
  min-width: 720px; /* below this the wrapper scrolls rather than the page */
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.compare caption {
  padding: 18px 20px 14px;
  text-align: left;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--ndx-text-body);
}

.compare th,
.compare td {
  padding: 13px 16px;
  text-align: left;
  vertical-align: top;
  border-top: 1px solid var(--ndx-hairline);
}

.compare thead th {
  border-top: 0;
  background: var(--ndx-card-2);
  font-size: 0.875rem;
  font-weight: 750;
  color: var(--ndx-text);
  white-space: nowrap;
}

.compare thead th[scope="row"] {
  background: transparent;
}

.compare tbody th {
  font-weight: 600;
  color: var(--ndx-text);
  min-width: 250px;
}

.compare td {
  color: var(--ndx-text-body);
  font-variant-numeric: tabular-nums;
}

.compare tbody tr:hover td,
.compare tbody tr:hover th {
  background: var(--ndx-card-2);
}

/* The featured column keeps a stronger tint than it had on white: at 6% over a
   near-black card the column was no longer distinguishable from its
   neighbours. Text on the 10% tint still measures 5.82:1. */
.compare .col-featured {
  background: rgba(6, 182, 212, 0.1);
}

.compare-group th {
  background: var(--ndx-card-2);
  padding-top: 22px;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ndx-accent);
  border-top: 1px solid var(--ndx-hairline);
}

.yes {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 650;
  color: var(--ndx-text);
}

.yes svg {
  width: 16px;
  height: 16px;
  color: var(--ndx-accent);
}

.no {
  color: var(--ndx-text-body);
}

.table-foot {
  margin-top: 16px;
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--ndx-text-body);
  max-width: 88ch;
}

/* ==========================================================================
   13. FAQ
   --------------------------------------------------------------------------
   Native <details>/<summary>: keyboard operable and screen-reader announced
   without a line of JavaScript.
   ========================================================================== */
.faq {
  max-width: 860px;
  margin-inline: auto;
}

.faq__item {
  border: 1px solid var(--ndx-hairline);
  border-radius: var(--ndx-radius-sm);
  background: var(--ndx-card);
}

.faq__item + .faq__item {
  margin-top: 12px;
}

.faq__item[open] {
  border-color: rgba(6, 182, 212, 0.5);
  box-shadow: var(--ndx-shadow-dark);
}

.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px;
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.4;
  color: var(--ndx-text);
  cursor: pointer;
  list-style: none;
}

/* remove the platform disclosure triangle, we draw our own chevron */
.faq__q::-webkit-details-marker {
  display: none;
}
.faq__q::marker {
  content: "";
}

.faq__q:hover {
  color: var(--ndx-accent);
}

/* The question line holds an optional short verdict chip ("No") before the
   question itself. The chip is aria-hidden, so a screen reader hears only the
   question and not a stray "No" in front of it. */
.faq__q-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  min-width: 0;
}

.faq__chevron {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  color: var(--ndx-accent);
}

.faq__item[open] .faq__chevron {
  transform: rotate(180deg);
}

.faq__a {
  padding: 0 20px 20px;
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--ndx-text-body);
}

.faq__a p + p {
  margin-top: 12px;
}

.faq__a ul {
  margin: 12px 0 0;
  padding-left: 20px;
  list-style: disc;
}

.faq__a li {
  margin-bottom: 6px;
}

/* A question whose answer is a firm "no" gets a visible marker, so the limit of
   the product is impossible to skim past. */
.faq__flag {
  display: inline-block;
  margin-right: 8px;
  padding: 2px 8px;
  border-radius: var(--ndx-radius-pill);
  background: rgba(6, 182, 212, 0.14);
  border: 1px solid rgba(6, 182, 212, 0.4);
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ndx-accent);
  vertical-align: 1px;
}

/* ==========================================================================
   14. CLOSING CTA BAND
   ========================================================================== */
.cta-band {
  position: relative;
  color: var(--ndx-white);
  background-color: var(--ndx-bg-alt);
  border-block: 1px solid var(--ndx-hairline);
  /* The 135deg slate-to-blue gradient is a brand fragment and is unchanged;
     the cyan wash above it is the one accent on the page that is meant to be
     loud, so it stays at 22%. */
  background-image: radial-gradient(
      60% 100% at 50% 0%,
      rgba(6, 182, 212, 0.22) 0%,
      rgba(6, 182, 212, 0) 70%
    ),
    linear-gradient(135deg, var(--ndx-slate) 0%, #0f2233 100%);
}

.cta-band .container {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 22px;
}

.cta-band h2 {
  margin: 0;
  max-width: 22ch;
}

.cta-band .lead {
  color: var(--ndx-muted);
  max-width: 56ch;
}

@media (min-width: 900px) {
  .cta-band .container {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 40px;
  }
}

/* ==========================================================================
   15. FOOTER
   ========================================================================== */
.site-footer {
  color: var(--ndx-white);
  background-color: var(--ndx-slate-deep);
  padding-block: clamp(40px, 6vw, 64px) 28px;
  font-size: 0.9375rem;
}

.footer__grid {
  display: grid;
  gap: 32px;
}

@media (min-width: 700px) {
  .footer__grid {
    grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr));
    gap: 40px;
  }
}

/* The footer signature is the same logo at the same size as the header: the
   only difference is that the header one is a link and sits in a 68px bar. */
.footer__brand .brand {
  padding: 0;
}

.footer__about {
  margin: 14px 0 0;
  max-width: 42ch;
  font-size: 0.875rem;
  line-height: 1.7;
  color: var(--ndx-muted);
}

.footer__heading {
  margin: 0 0 14px;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ndx-cyan-light);
}

.footer__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.footer__list li + li {
  margin-top: 4px;
}

.footer__list a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  font-size: 0.9375rem;
  color: var(--ndx-muted);
  text-decoration: none;
}

.footer__list a:hover {
  color: var(--ndx-white);
  text-decoration: underline;
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 24px;
  margin-top: clamp(32px, 5vw, 48px);
  padding-top: 22px;
  border-top: 1px solid var(--ndx-border-dark);
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--ndx-muted);
}

/* ==========================================================================
   16. COMPANY SECTIONS (services, values, contact)
   --------------------------------------------------------------------------
   These exist only for the homepage, which is now the company's showcase
   rather than a product page: services, products, about, contact.

   Nothing above this line is restyled and no brand token is touched. Where a
   new block could have re-used an existing class it does (services are
   .feature cards, the boundary statement is .reads-box); the classes below are
   the ones that had no existing equivalent.
   ========================================================================== */

/* The company hero is a single column: one statement, one action pair. The old
   two-column .hero__grid held the product's four-step illustration, which now
   lives on fleet.html where the rest of the product detail lives. */
.hero__intro {
  max-width: 70ch;
}

/* Sub-points inside a service card. .feature p is margin:0, and .ticks carries
   no top spacing of its own, so the list needs it here. */
.card-points {
  margin-top: 16px;
}

/* The homepage shows two product cards, so the three-column .products grid
   would leave an empty third slot. Declared after the base rule above, so it
   wins at the same specificity. */
@media (min-width: 900px) {
  .products--duo {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* The boundary statement sits in a full-width band under the products grid on
   the homepage, rather than in the narrow hero column it was written for, so
   its paragraph needs a measure instead of the container's full width. 72ch is
   deliberately tighter than the 88ch the site's footnotes use: this paragraph
   is read rather than skimmed, and it is the one that must not be misread. */
.reads-box--band p {
  max-width: 72ch;
}

/* --- core values ---
   Four cards on the dark About band. Not .feature cards: these are short
   statements rather than product capabilities, and they do not carry an icon. */
.values {
  display: grid;
  gap: 18px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.value {
  padding: 22px;
  border: 1px solid var(--ndx-hairline);
  border-left: 3px solid var(--ndx-cyan);
  border-radius: var(--ndx-radius-sm);
  background: var(--ndx-card-2);
}

.value h3 {
  margin-bottom: 8px;
}

.value p {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--ndx-text-body);
}

/* The About band is dark slate, so the value cards take the same dark card
   treatment as .problem-card rather than inventing a second one. */
.section--dark .value {
  background: var(--ndx-surface-dark);
  border-color: var(--ndx-border-dark);
  border-left-color: var(--ndx-cyan);
}

.section--dark .value h3 {
  color: var(--ndx-white);
}

.section--dark .value p {
  color: var(--ndx-muted);
}

@media (min-width: 640px) {
  .values {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1000px) {
  .values {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* --- contact (email, country, business hours) --- */
.contact {
  display: grid;
  gap: 18px;
}

.contact__item {
  padding: 22px 24px;
  border: 1px solid var(--ndx-hairline);
  border-radius: var(--ndx-radius);
  background: var(--ndx-card);
  box-shadow: var(--ndx-shadow-dark);
}

.contact__label {
  margin: 0 0 6px;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ndx-accent);
}

.contact__value {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 650;
  color: var(--ndx-text);
}

/* The email card is a link rather than a line of text, so it keeps the 44px
   target the rest of the site's interactive elements use. */
a.contact__value {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

a.contact__value:hover {
  color: var(--ndx-accent);
}

@media (min-width: 700px) {
  .contact {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ==========================================================================
   17. MOTION, FOCUS AND PRINT
   ========================================================================== */

/* Everything that moves is opt-in, so a reduced-motion visitor gets a static
   page rather than a page that merely moves less. */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }

  .btn,
  .product,
  .feature,
  .plan,
  .step,
  .faq__item,
  .nav-list a {
    transition: background-color 0.18s ease, border-color 0.18s ease,
      color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
  }

  .product--live:hover,
  .feature:hover,
  .step:hover {
    transform: translateY(-2px);
    box-shadow: var(--ndx-shadow-dark);
  }

  .faq__chevron {
    transition: transform 0.18s ease;
  }
}

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

/* One consistent, high-contrast focus ring on every interactive element,
   including on the dark bands where the light-mode ring would be invisible. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: var(--ndx-focus-dark);
  outline-offset: var(--ndx-focus-offset);
  border-radius: 4px;
}

.section--dark a:focus-visible,
.section--dark button:focus-visible,
.section--dark summary:focus-visible,
.cta-band a:focus-visible,
.cta-band button:focus-visible,
.site-footer a:focus-visible {
  outline-color: var(--ndx-cyan-light);
}

/* Printing a dark site unchanged is a black page. The whole thing flips back to
   the light scale here — which is the second reason those tokens are still in
   :root: they are the paper palette, and they are the only place a
   light-surface colour is still correct. */
@media print {
  .site-header,
  .cta-band,
  .nav-toggle {
    display: none !important;
  }
  body {
    color: var(--ndx-ink);
    background: var(--ndx-white);
  }
  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    color: var(--ndx-ink);
  }
  p,
  li,
  dd,
  dt,
  caption,
  td,
  th,
  .lead,
  .note,
  .ticks li,
  .footer__about,
  .footer__bottom,
  .footer__list a {
    color: var(--ndx-ink-muted) !important;
  }
  .hero,
  .section--surface,
  .section--white,
  .section--dark,
  .cta-band,
  .site-footer,
  .panel,
  .panel--stop,
  .flow,
  .flow__fields,
  .step,
  .product,
  .product--soon,
  .feature,
  .plan,
  .plan--featured,
  .plan--tailored,
  .overage,
  .products-note,
  .table-scroll,
  .compare thead th,
  .compare-group th,
  .faq__item,
  .value,
  .contact__item,
  .nav-panel[data-open="true"] {
    background: var(--ndx-white) !important;
    background-image: none !important;
    box-shadow: none !important;
    color: var(--ndx-ink) !important;
  }
  .panel,
  .flow,
  .step,
  .product,
  .feature,
  .plan,
  .faq__item,
  .table-scroll,
  .value,
  .contact__item,
  .compare thead th,
  .compare-group th {
    border-color: var(--ndx-border-strong) !important;
  }
  .compare th,
  .compare td,
  .plan .ticks,
  .product__foot,
  .panel__foot {
    border-color: var(--ndx-border) !important;
  }
  .section--surface,
  .product--soon,
  .plan--tailored,
  .panel--stop,
  .flow__fields,
  .value,
  .compare tbody tr:hover td,
  .compare tbody tr:hover th,
  .compare .col-featured {
    background: var(--ndx-surface) !important;
  }
  .compare tbody th,
  .compare .yes,
  .price,
  .flow__title,
  .flow__label,
  .flow__fields dd,
  .faq__q,
  .contact__value,
  .plan__limits strong,
  .overage strong {
    color: var(--ndx-ink-2) !important;
  }
  .eyebrow,
  .contact__label,
  .compare-group th,
  a {
    color: var(--ndx-cyan-ink) !important;
  }
  .reads-box,
  .overage {
    background: var(--ndx-surface-2) !important;
  }
  .faq__item {
    break-inside: avoid;
  }
  .faq__item[open] .faq__a,
  .faq .faq__a {
    display: block;
  }
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.8em;
  }
}
