/* ==========================================================================
   Eventag, shared stylesheet
   --------------------------------------------------------------------------
   Created during the homepage redesign. Currently used only by
   index.html. The other pages (about, how-it-works, careers, blog) still
   carry their own <style> blocks and are deliberately not touched yet.

   HOW TO READ THE VALUES BELOW
   Values marked DECIDED or MEASURED come from design/tokens.md and are
   authoritative.
   Values marked PROVISIONAL were measured by me off the 2x exports in
   design/sections/ and halved. They are close, but they are not Figma
   inspect values. Replace them when the real numbers are available.

   Built so far: nav, hero, footer.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Fonts, self-hosted
   Poppins, per design/tokens.md. This replaced DM Sans, which the other seven
   pages still use. That inconsistency is known and stands until they are
   ported.

   Poppins ships one file per weight, so only the three weights actually in use
   are here: 400 regular, 500 medium, 600 semibold. The devanagari subset
   Google also serves is not downloaded, the site is English and German.
   Poppins is OFL licensed, self-hosting is permitted.

   NOTE: there is no 700. tokens.md lists it as unconfirmed. Anything that
   needs a heavier weight uses 600 rather than asking the browser to fake a
   bold, which would distort the letterforms and the metrics.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/poppins-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: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/poppins-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: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/poppins-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: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/poppins-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: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/poppins-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: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/poppins-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;
}


/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Colour ---------------------------------------------------------------- */
  --brand: #3F42F8;         /* MEASURED, matches the mockup and the logo mark */
  --dark: #19191B;          /* MEASURED, nav and hero background */
  --black: #000000;         /* MEASURED, hardware band */
  --white: #FFFFFF;
  --light: #FAFAFF;         /* MEASURED, applications and FAQ */
  --light-alt: #F4F4FF;     /* MEASURED. Was the privacy strip fill; that
                               section is removed, and the pricing compare
                               band still uses this. */
  --footer-navy: #07083A;   /* MEASURED, footer only */

  /* Lightened brand blue, used for the nav Login link. The mockup samples
     #8D8FFF, which is the brand blue mixed roughly 40% toward white. Expressed
     as a mix of --brand rather than a fixed hex so it follows the brand colour
     if it ever changes. The plain hex on the first line is the fallback for
     browsers without color-mix. */
  --brand-tint: #8D8FFF;
  --brand-tint: color-mix(in srgb, var(--brand) 60%, #FFFFFF);

  /* Text ------------------------------------------------------------------ */
  --text-on-dark: #FFFFFF;
  --muted-on-navy: #A6A6A6; /* PROVISIONAL, sampled from the export.
                               7.8:1 on --footer-navy, passes WCAG AA. */
  --muted-on-light: #727272; /* DECIDED. The mockup's #939393 is 3.07:1 on
                               white and fails WCAG AA, and the 0.93 type pass
                               makes the text carrying it physically smaller.
                               #727272 is 4.81:1 on white and 4.63:1 on
                               #FAFAFF, so it clears 4.5:1 on both. */
  --text-on-light: #6B6B6B; /* body copy on the light sections. Chosen over
                               the mockup's #7E7E7E, which is 4.06:1 on white and
                               fails AA. This clears 4.5:1 on all three light
                               backgrounds: 5.33 white, 5.12 #FAFAFF, 4.88 #F4F4FF */
  --muted-on-dark: #A0A0A8; /* PROVISIONAL, hero lead copy. 6.8:1 on --dark,
                               passes WCAG AA. */
  --radius-card: 40px;      /* MEASURED, hero card corner */

  /* Layout ---------------------------------------------------------------- */
  --canvas: 1440px;         /* MEASURED, Figma canvas width */
  --gutter: 120px;          /* MEASURED, confirmed from the nav export */
  --gutter-footer: 80px;    /* MEASURED. Note this genuinely differs from the
                               nav's 120px in the mockup. Flagged, not a bug. */
  --gutter-mobile: 24px;    /* PROVISIONAL, mockup is desktop only */

  /* ------------------------------------------------------------------------
     TYPE. DECIDED: every size below is the Figma value multiplied by 0.93 and
     rounded to the nearest whole pixel. Line heights carry the same factor so
     the ratios hold. Nothing at 14px or under was scaled, and 13px is the
     floor. The Figma figure is kept beside each built figure so the
     provenance is not lost: the number in the comment is what Figma says, the
     number in the declaration is what ships. Full reasoning in
     design/tokens.md, "DECIDED: the whole type scale runs at 0.93".

     Unitless line heights elsewhere in this file are deliberately untouched.
     A ratio already follows its font size down; scaling the ratio as well
     would change it, which is the opposite of holding it.
     ------------------------------------------------------------------------ */

  /* PROVISIONAL, derived from glyph measurements off the export. */
  --fs-nav: 17px;           /* Figma 18 */
  --fw-nav: 500;
  --fs-btn: 17px;           /* Figma 18 */
  --fw-btn: 600;            /* no 700 file, see the font block above */
  --fs-footer: 15px;        /* Figma 16 */
  --fw-footer: 400;

  /* PROVISIONAL-MEASURED. Derived by matching rendered line widths against
     the export, not read from the Figma inspect panel. Size and line height
     are solid. The 500 weight is inferred from H2 and H3 both being 500, so
     it is the softest part of this and the first thing to check if Figma
     later disagrees. */
  --fs-h1: 49px;            /* Figma 53 */
  --lh-h1: 60px;            /* Figma 64 */
  --fw-h1: 500;
  /* CONFIRMED from the Figma inspect panel, then scaled */
  --fs-eyebrow: 20px;       /* Figma 22 */
  --lh-eyebrow: 32px;       /* Figma 34 */
  --fw-eyebrow: 400;
  --fw-eyebrow-em: 600;     /* the emphasis span, in brand blue */

  --fs-h2: 45px;            /* Figma 48, CONFIRMED, centre aligned */
  --lh-h2: 65px;            /* Figma 70 */
  --fw-h2: 500;

  --fs-h3: 22px;            /* Figma 24, CONFIRMED, card titles */
  --lh-h3: 32px;            /* Figma 34 */
  --fw-h3: 500;

  --fs-step-label: 19px;    /* Figma 20, PROVISIONAL, fitted to the export */
  --fw-step-label: 500;

  /* MEASURED, and each differs from the single CONFIRMED "Body" style.
     The section eyebrows are Figma 20 where the hero's is 22; the
     applications cards use a Figma 16 body where how-it-works uses 18; and
     the applications intro is a Figma 24 style that tokens.md does not list
     at all. */
  --fs-section-eyebrow: 19px;  /* Figma 20 */
  --fs-section-intro: 22px;    /* Figma 24 */
  --lh-section-intro: 37px;    /* Figma 40 */
  --fs-card-body: 15px;        /* Figma 16 */
  --lh-card-body: 25px;        /* Figma 27 */

  --fs-body: 17px;          /* Figma 18, CONFIRMED, section and card body */
  --lh-body: 24px;          /* Figma 26 */
  --fw-body: 400;

  /* Hero sub copy is "Body large" in tokens.md and still PROVISIONAL, so it
     keeps its fitted value rather than adopting the confirmed body size. */
  --fs-lead: 21px;          /* Figma 23 */
  --lh-lead: 32px;          /* Figma 34 */

  /* Hero layout. Grid is 559 + 90 + 551 = 1200. --hero-card is the square
     card, so it sets the row height too. */
  --hero-card: 551px;

  /* Shape of the hero media card. The mockup draws it 550x499 (1.10), but the
     video source is 1:1 and must not be cropped, so the card matches the
     source instead. That is what makes the hero 51px taller than the export.
     If a future asset is not square, change this one value to its ratio. */
  --hero-media-aspect: 1 / 1;
  --hero-col-gap: 90px;     /* leaves a 559px copy column, which is what
                               makes the H1 break after "turns" like the export */
  --hero-pad-top: 100px;    /* DECIDED override, mockup is 142px. See tokens.md */
  --hero-pad-bottom: 161px; /* card bottom to section end */
  --hero-btn-gap: 24px;

  /* How it works. Three columns, matching the mockup. */
  --hiw-slot-aspect: 373.5 / 230; /* DECIDED, the mockup's slot is 373.5x156.
                               Raised to 230 so each square source shows a 62%
                               band instead of 42%. See tokens.md. */
  --hiw-col-gap: 40px;      /* MEASURED, 3 x 373.3 + 2 x 40 = 1200 */
  --hiw-pad-top: 84px;
  --hiw-pad-bottom: 120px;
  --hiw-head-gap: 69px;     /* H2 block to the STEP labels */
  --hiw-slot-gap: 33px;     /* slot to the step title */
  --radius-step: 28px;      /* MEASURED, the mockup's image slot corner */

  /* Pricing page.
     ONE spacing scale for the whole page. Every gap on /pricing is one of
     these seven values, so the vertical rhythm is a decision made once rather
     than a number picked per element. Colours, radii and every type size but
     two are existing tokens. */
  --pr-1: 8px;
  --pr-2: 16px;
  --pr-3: 24px;
  --pr-4: 32px;
  --pr-5: 48px;
  --pr-6: 64px;
  --pr-7: 96px;

  /* The two type sizes this page adds. DECIDED, recorded in tokens.md.
     The quality bar for the page is that prices are the largest type after
     the H1. The 48px H2 token leaves no room between itself and the 53px H1,
     so the page H1 steps up to 64 and the price sits at 52, above every
     section heading and below the H1. */
  --fs-pr-h1: 60px;         /* was 64 before the 0.93 pass */
  --lh-pr-h1: 67px;         /* was 72 */
  --fs-pr-price: 48px;      /* was 52 */

  /* Plan block. The cards are one bordered container divided by 1px rules,
     not separate boxes, so there is a rule colour and no grid gap. */
  --pr-rule: var(--faq-rule);          /* the same 1px the FAQ rows use */
  --pr-card-bg: var(--white);
  --pr-card-hover: var(--apps-card-bg);
  --pr-featured-bg: #F7F7FF;
  --pr-featured-bg: color-mix(in srgb, var(--brand) 4%, #FFFFFF);
  --pr-row-hover: rgba(63, 66, 248, 0.04);   /* half the applications
                                                spotlight, same family */
  --pr-two-max: 800px;
  --pr-faq-col: 400px;
  --pr-hero-tint: rgba(63, 66, 248, 0.10);

  /* CTA, MEASURED off the export */
  --cta-form-w: 713px;
  --cta-gap: 13.5px;
  --cta-field-h: 54px;
  --cta-message-h: 127px;
  --cta-btn-h: 48px;
  --cta-field-pad: 20px;
  --radius-field: 8px;
  --cta-pad-top: 80px;
  --cta-pad-bottom: 78.5px;
  --cta-form-gap: 51px;
  --cta-send-gap: 11px;
  --cta-note-gap: 15.5px;
  /* 17% white over the band, per tokens.md, not a fixed hex. The export
     samples nearer 20%, noted there. */
  --cta-field-bg: rgba(255, 255, 255, 0.17);
  --cta-placeholder: rgba(255, 255, 255, 0.72);
  --cta-note-colour: rgba(255, 255, 255, 0.88);

  /* Privacy strip tokens removed with the section they served. All nine were
     MEASURED off the export and come back with it. See section 6g below. */

  /* FAQ, MEASURED off the export */
  --faq-rule: #E0E5EF;
  --faq-list-max: 1019px;
  --faq-row-inset: 24px;
  --faq-row-pad: 28.5px;    /* the 36px icon, not the 34px text line, sets the
                               row's content height. This gives the export's 94. */
  --faq-icon: 36px;
  --fs-faq-q: 22px;
  --lh-faq-q: 32px;
  --faq-pad-top: 80px;
  --faq-list-gap: 54px;
  --faq-pad-bottom: 100px;
  --faq-answer-max: 780px;
  --faq-answer-pad: 8px;
  --faq-ms: 220ms;

  /* Hardware band, all MEASURED off the export */
  --hw-eyebrow: #969696;
  --hw-copy-col: 630px;
  --hw-copy-max: 690px;
  --hw-body-max: 590px;
  --hw-media-size: 532px;
  --hw-media-offset: 4px;
  --hw-pad-top: 172px;
  --hw-pad-bottom: 81px;    /* the media, not the copy, is the tall column */
  --hw-title-gap: 30px;
  --hw-body-gap: 18px;
  --hw-btn-gap: 70px;
  --hw-btn-pad: 25px;       /* lands the pill on the export's 296 */
  --lh-hw-body: 34px;

  /* Applications. Same 373.3 + 40 grid as how-it-works. */
  --apps-card-bg: #F5F7FB;      /* MEASURED */
  --apps-card-border: #ECEEF2;  /* MEASURED */
  --apps-card-border-active: rgba(63, 66, 248, 0.35);
  --apps-spotlight: rgba(63, 66, 248, 0.10);
  --apps-hover-ms: 180ms;
  --apps-icon-bg: #DEE6FD;      /* MEASURED */
  --radius-app-card: 15px;      /* MEASURED, fitted from the corner curve */
  --radius-icon-tile: 10px;     /* MEASURED, least-squares fit of the corner
                                   curve lands on 10.05 */
  --apps-icon-size: 48px;       /* MEASURED, exactly 96x96 at 2x */
  --apps-icon-art: 38px;        /* MEASURED, artwork size inside the tile */
  --apps-card-pad: 32px 31px 32px; /* 31 horizontal is MEASURED and matches
                                   the Figma Left 151 note. Vertical is now
                                   balanced 32/32; the export runs 32 top
                                   against 43 bottom. */
  --apps-gap: 40px;
  --apps-h2-width: 700px;
  --apps-intro-width: 1000px;
  --apps-pad-top: 60px;
  --apps-pad-bottom: 100px;
  --apps-intro-gap: 24px;   /* DECIDED. The export's H2-to-intro gap is 88
                               ink against an 18.5 eyebrow-to-H2 gap, which is
                               the inconsistency, not a value to copy. */
  --apps-grid-gap: 60px;
  --apps-title-gap: 16px;   /* DECIDED. The export's is 31 box / 39.5 ink,
                               which reads as two blocks rather than one. */
  --apps-body-gap: 18px;

  /* Model band. The 494px is the empty space the mockup leaves between the
     H2 and the buttons; the 16:9 video fills it at 879px wide. */
  --mb-h2-width: 680px;
  --mb-intro-width: 640px;
  --mb-video-height: 300px;
  --mb-col-gap: 80px;
  --mb-grid-gap: 56px;
  --mb-layer-gap: 24px;
  --mb-actions-gap: 56px;
  --fs-layer-desc: 15px;
  --mb-pad-top: 80px;
  --mb-pad-bottom: 80px;

  /* Sampled from the four coloured curves in the model band video, one per
     quadrant of the source frame, not chosen by eye. */
  --dot-blue: #85D9FE;
  --dot-pink: #F586D5;
  --dot-amber: #FEE595;
  --dot-teal: #82FEE3;
  /* 0.88 rather than a lighter knock-back: at 0.78 this lands 4.41:1 on the
     band, just under the 4.5 floor for 16px regular text. 0.88 gives 5.2:1. */
  --mb-desc-colour: rgba(255, 255, 255, 0.88);

  /* Spacing, PROVISIONAL ---------------------------------------------------- */
  --nav-pad-top: 32px;      /* DECIDED override, mockup is 112px. See tokens.md */
  --nav-link-gap: 44px;
  --nav-action-gap: 30px;
  --footer-pad-y: 48px;
  --footer-link-gap: 19px;

  /* Shape ------------------------------------------------------------------ */
  --radius-pill: 999px;     /* MEASURED. The button corner curve matches a
                               true half-height radius, so it is a full pill. */

  /* Motion ----------------------------------------------------------------- */
  --ease: 0.2s ease;
}


/* --------------------------------------------------------------------------
   3. Reset and base
   -------------------------------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

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

body {
  margin: 0;
  font-family: 'Poppins', system-ui, -apple-system, 'Segoe UI', sans-serif;
  background: var(--dark);
  color: var(--text-on-dark);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }

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

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}


/* --------------------------------------------------------------------------
   4. Shared helpers
   -------------------------------------------------------------------------- */

/* Centres content and applies the page side gutter. At the 1440px canvas this
   yields exactly the 1200px content width the mockup uses. */
.container {
  width: 100%;
  max-width: var(--canvas);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* For screen readers only. Used for real form labels and nav landmarks. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Keyboard focus. Visible on every interactive element, never removed. */
:focus-visible {
  outline: 2px solid var(--brand-tint);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: 50%;
  top: 8px;
  translate: -50% -200%;
  z-index: 100;
  padding: 12px 20px;
  background: var(--white);
  color: var(--brand);
  font-weight: 600;         /* no 700 file, see the font block above */
  border-radius: var(--radius-pill);
}
.skip-link:focus { translate: -50% 0; }


/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 15px 36px;              /* PROVISIONAL, gives the measured 48px
                                      height and 36px side padding */
  font-size: var(--fs-btn);
  font-weight: var(--fw-btn);
  line-height: 1;
  border-radius: var(--radius-pill);
  transition: background-color var(--ease), color var(--ease),
              border-color var(--ease);
  white-space: nowrap;
}

.btn--primary {
  background: var(--brand);
  color: var(--white);
}
.btn--primary:hover { background: color-mix(in srgb, var(--brand) 88%, #FFFFFF); }


/* --------------------------------------------------------------------------
   6. Site header and nav
   The mockup's nav is a single row across the 1200px content width, with the
   logo, the link group and the actions distributed by space-between. Measured
   positions match that exactly, so no manual offsets are needed.
   -------------------------------------------------------------------------- */

/* The header declares its own text colour as well as its fill. It did not
   before, so on pricing.html it inherited black from .pricing-page and every
   element in it that did not set a colour explicitly got black on the dark
   band. Nothing visible was affected, because the nav links and the hamburger
   bars both set their own colour, but anything added to the header later would
   have been. A section that sets a dark background should set the text colour
   that goes with it. */
.site-header {
  padding-top: var(--nav-pad-top);
  background: var(--dark);
  color: var(--text-on-dark);
}

.nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.nav-logo img { width: 161px; height: auto; }

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--nav-link-gap);
}

.nav-links a {
  font-size: var(--fs-nav);
  font-weight: var(--fw-nav);
  color: var(--text-on-dark);
  transition: opacity var(--ease);
}
.nav-links a:hover { opacity: 0.7; }

.nav-actions {
  display: flex;
  align-items: center;
  gap: var(--nav-action-gap);
}

/* A nav with no action on the right.

   The homepage has no Login and no button, so above 900px .nav-actions holds
   nothing but the hamburger, which is display:none there. Two things follow,
   and both are keyed off the same :has() test so they can never disagree:

     1. The empty wrapper is taken out of the flex row. It was still a child,
        so .nav-row's 24px gap sat between it and the links and stopped
        "Pricing" reaching the right gutter: the group ended at 1296 where the
        content box ends at 1320.
     2. The links take margin-left:auto so they sit flush right. Without it,
        space-between strands them mid-row.

   Both are scoped to the no-action case rather than applied to .nav-links
   outright. pricing.html and research.html still carry a real action, so they
   never match and their navs are untouched. If a button is ever added back to
   the homepage nav, both rules stop matching on their own and the layout
   returns to three-group space-between with no edit here.

   Below 900px neither applies: that is where the hamburger lives and the links
   become a full-width stacked panel. */
@media (min-width: 901px) {
  .nav-actions:not(:has(.btn, .nav-login)) { display: none; }
  .nav-row:not(:has(.nav-actions .btn, .nav-actions .nav-login)) .nav-links {
    margin-left: auto;
  }
}

.nav-login {
  font-size: var(--fs-nav);
  font-weight: var(--fw-nav);
  color: var(--brand-tint);
  transition: opacity var(--ease);
}
.nav-login:hover { opacity: 0.75; }

/* A second Login link lives inside the collapsible panel for small screens.
   Only ever one of the two is rendered, so screen readers hear it once. */
.nav-login--mobile { display: none; }

/* Hamburger, hidden until the desktop row stops fitting. */
.nav-toggle {
  display: none;
  width: 44px;               /* 44px keeps it a comfortable tap target */
  height: 44px;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
}

.nav-toggle .bars {
  display: block;
  position: relative;
  width: 22px;
  height: 2px;
  background: var(--white);
  transition: background-color var(--ease);
}
.nav-toggle .bars::before,
.nav-toggle .bars::after {
  content: '';
  position: absolute;
  left: 0;
  width: 22px;
  height: 2px;
  background: var(--white);
  transition: translate var(--ease), rotate var(--ease);
}
.nav-toggle .bars::before { top: -7px; }
.nav-toggle .bars::after  { top: 7px; }

/* Turns the bars into a cross while the menu is open. */
.nav-toggle[aria-expanded='true'] .bars { background: transparent; }
.nav-toggle[aria-expanded='true'] .bars::before { translate: 0 7px; rotate: 45deg; }
.nav-toggle[aria-expanded='true'] .bars::after  { translate: 0 -7px; rotate: -45deg; }


/* Every full-width section that paints a background also declares the text
   colour that belongs on it. .btn--outline and anything else using
   `color: inherit` or `currentColor` depends on this being true: a section
   that sets a light fill but leaves the colour to inherit hands white text to
   its children, because <body> is dark on this site. Nothing visible was
   wrong, since each child here sets its own colour, but an outline button
   dropped into one of these would have come out white on near-white. */

/* --------------------------------------------------------------------------
   6b. Hero
   Two columns across the 1200px content box: copy on the left, visual card
   on the right. Measured off the export, so the grid is 554.5 + 94.5 + 551.

   The card is SQUARE here, not the mockup's 550x499. The video source is
   1200x1200 and must not be cropped, so the card matches the source instead.
   That makes the card 551px tall rather than 500, which is why this section
   is 51px taller than the export.
   -------------------------------------------------------------------------- */

.hero {
  background: var(--dark);
  color: var(--text-on-dark);
  padding-top: var(--hero-pad-top);
  padding-bottom: var(--hero-pad-bottom);
}

.hero-grid {
  display: grid;
  grid-template-columns: 1fr var(--hero-card);
  gap: var(--hero-col-gap);
  align-items: center;
}

.hero-eyebrow {
  margin: 0 0 24px;
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-eyebrow);
  line-height: var(--lh-eyebrow);
  color: var(--text-on-dark);
}
.hero-eyebrow span { color: var(--brand); font-weight: var(--fw-eyebrow-em); }

.hero-title {
  margin: 0 0 32px;
  font-size: var(--fs-h1);
  font-weight: var(--fw-h1);
  line-height: var(--lh-h1);
  letter-spacing: 0;
  color: var(--text-on-dark);
}

.hero-lead {
  margin: 0 0 40px;
  font-size: var(--fs-lead);
  font-weight: 400;
  line-height: var(--lh-lead);
  color: var(--muted-on-dark);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--hero-btn-gap);
}

/* Hero buttons are equal width in the mockup, both 198px, rather than sized
   to their label. min-width holds that without hard-coding a width. */
.btn--hero { min-width: 198px; }

/* Outline button. It takes its colour from whatever section it sits in rather
   than naming one, so there is no per-section variant to keep in sync and no
   way for it to inherit the wrong colour on a background it was not written
   for. Three things make that work:

     color: inherit      the label is the section's own text colour, so it is
                         white on the dark hero, white on the blue model band,
                         and near-black on the light pricing cards
     currentColor        the border is that same colour, knocked back so it
                         reads as an edge rather than a second label
     no background       the section shows through, so nothing has to match it

   Do not add a section-specific .btn--outline rule. That is what previously
   put a black label on the blue band. If a section needs a different outline
   button, give it a different modifier class.

   The border is currentColor at 65%. The binding case is white on the brand
   blue band, which is much tighter than white on a near-black section: swept
   in 5% steps, 55% gives only 2.94:1 there and fails, 57% is the arithmetic
   minimum at 3.05:1, and 65% gives 3.53:1, which is the first value with real
   headroom rather than one that just scrapes the line. Measured at 65%:

     white on brand blue   #3F42F8    3.53:1
     white on near-black   #0A0A0A    8.45:1
     white on hero dark    #19191B    7.96:1
     black on white card              6.98:1
     black on #FAFAFF card            6.88:1

   All clear the 3:1 WCAG floor for a control boundary. The plain currentColor
   line above is the fallback for browsers without color-mix; it lands heavier
   but never fails. */
.btn--outline {
  background: transparent;
  color: inherit;
  border: 1px solid currentColor;
  border-color: color-mix(in srgb, currentColor 65%, transparent);
}

/* Hover strengthens the edge to full currentColor and lays the same colour
   over the section at 12%. Both are relative to the inherited colour, so this
   works on any background without knowing what it is. The old hover filled
   with solid white, which on a white card painted the button invisible. */
.btn--outline:hover {
  border-color: currentColor;
  background: color-mix(in srgb, currentColor 12%, transparent);
}

/* The visual card. aspect-ratio keeps it square at every width, so the video
   fills it exactly and object-fit never has anything to crop. */
/* overflow:hidden is what makes the corner radius clip the video, since a
   <video> does not inherit its container's rounded corners on its own. */
.hero-visual {
  position: relative;
  aspect-ratio: var(--hero-media-aspect);
  border-radius: var(--radius-card);
  overflow: hidden;
  background: #26262E;           /* PROVISIONAL, card fill behind the video */
}

.hero-video,
.hero-still {
  width: 100%;
  height: 100%;
  object-fit: cover;             /* card and source are both 1:1, so no crop */
  display: block;
}

/* The still is only for reduced motion, hidden the rest of the time. */
.hero-still { display: none; }

@media (prefers-reduced-motion: reduce) {
  .hero-video { display: none; }
  .hero-still { display: block; }
}


/* --------------------------------------------------------------------------
   6c. How it works
   Three columns across, matching the mockup's grid. The slot is taller than
   the mockup draws it, 230px rather than 156px, so each square source shows a
   62% band instead of 42%. object-position selects which band, scored per
   image against the band actually visible.
   -------------------------------------------------------------------------- */

.hiw {
  background: var(--white);
  padding-top: var(--hiw-pad-top);
  padding-bottom: var(--hiw-pad-bottom);
  color: var(--black);
}

.hiw-head { text-align: center; }

.section-eyebrow {
  margin: 0 0 1px;
  font-size: var(--fs-section-eyebrow);
  font-weight: var(--fw-eyebrow);
  line-height: var(--lh-eyebrow);
  color: var(--muted-on-light);
}

.section-h2 {
  margin: 0;
  font-size: var(--fs-h2);
  font-weight: var(--fw-h2);
  line-height: var(--lh-h2);
  letter-spacing: 0;
  color: var(--black);
}

.hiw-steps {
  list-style: none;
  margin: var(--hiw-head-gap) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--hiw-col-gap);
}

/* The slot is landscape and the source is square, so cover crops the source
   vertically. object-position per step picks which band shows.

   DO NOT rescore these by ink density. They are set so the crop clears the
   "sentien" wordmark at the top of each screenshot. Ink scoring optimises for
   the densest band, which pulls the window back down and slices through the
   wordmark. Ceilings at the current 62% band are 28% for step 1, 56% for
   step 2 and 31% for step 3; at or below each clears with padding to spare.
   Recompute the ceilings, not the optima, if the slot height changes. */
.hiw-media {
  aspect-ratio: var(--hiw-slot-aspect);
  margin: 0 0 var(--hiw-slot-gap);
  border-radius: var(--radius-step);
  overflow: hidden;
  background: #F7F7FF;      /* MEASURED, the mockup's empty slot fill */
}
.hiw-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hiw-step:nth-child(1) .hiw-media img { object-position: 50% 25%; }
.hiw-step:nth-child(2) .hiw-media img { object-position: 50% 50%; }
.hiw-step:nth-child(3) .hiw-media img { object-position: 50%  8%; }

.hiw-label {
  margin: 0 0 25px;
  font-size: var(--fs-step-label);
  font-weight: var(--fw-step-label);
  line-height: 1.2;
  color: var(--muted-on-light);
}

.hiw-title {
  margin: 0 0 9px;
  font-size: var(--fs-h3);
  font-weight: var(--fw-h3);
  line-height: var(--lh-h3);
  color: var(--black);
}

.hiw-body {
  margin: 0;
  max-width: 46ch;
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  line-height: var(--lh-body);
  color: var(--text-on-light);
}


/* --------------------------------------------------------------------------
   6d. Model band, full-bleed blue
   DECIDED override of the mockup, which is a single centred column with 494px
   of empty blue under the H2. This is a centred header over two columns, the
   video on the left and the four context layers on the right. See tokens.md.
   -------------------------------------------------------------------------- */

.model-band {
  background: var(--brand);
  color: var(--text-on-dark);
  padding-top: var(--mb-pad-top);
  padding-bottom: var(--mb-pad-bottom);
}

.mb-head { text-align: center; }

/* The shared eyebrow and H2 are styled for light sections, so both need
   recolouring here. */
.model-band .section-eyebrow { color: var(--text-on-dark); }
.model-band .section-h2 {
  color: var(--text-on-dark);
  /* Holds the mockup's two-line break. The full string is 1077px at 48px, so
     it would otherwise sit on one line inside the 1200 box. */
  max-width: var(--mb-h2-width);
  margin-inline: auto;
}

.mb-intro {
  margin: 20px auto 0;
  max-width: var(--mb-intro-width);
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  line-height: var(--lh-body);
  color: var(--text-on-dark);
}

.mb-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--mb-col-gap);
  align-items: center;
  margin-top: var(--mb-grid-gap);
}

/* Video card. The source is 16:9 and the card is wider than tall, so cover
   crops it vertically and object-position centres the waveform, which sits at
   50.1% of the source height. */
.mb-visual {
  height: var(--mb-video-height);
  border-radius: var(--radius-card);
  overflow: hidden;
  background: #051022;      /* MEASURED from the poster's border, so the card
                               reads as deliberate rather than as a hole */
}

.mb-video,
.mb-still {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  display: block;
}

.mb-still { display: none; }

@media (prefers-reduced-motion: reduce) {
  .mb-video { display: none; }
  .mb-still { display: block; }
}

/* The four context layers. Dot colours are sampled from the four coloured
   curves in the video, one per quadrant, so the list and the visual agree. */
.mb-layers {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--mb-layer-gap);
}

.mb-layer {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 14px;
  row-gap: 2px;
}

.mb-dot {
  width: 12px;
  height: 12px;
  margin-top: 7px;          /* optical centring against the name's cap height */
  border-radius: 50%;
  background: var(--dot);
}

.mb-layer:nth-child(1) { --dot: var(--dot-blue); }
.mb-layer:nth-child(2) { --dot: var(--dot-pink); }
.mb-layer:nth-child(3) { --dot: var(--dot-amber); }
.mb-layer:nth-child(4) { --dot: var(--dot-teal); }

.mb-layer-name {
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: var(--lh-body);
  color: var(--text-on-dark);
}

.mb-layer-desc {
  grid-column: 2;
  font-size: var(--fs-layer-desc);
  font-weight: 400;
  line-height: 22px;
  color: var(--mb-desc-colour);
}

/* DELIBERATE OVERRIDE, not a redundant declaration. Do not "simplify" this
   back to inherit.

   The model band button was reported rendering a black label on the blue band
   in a real browser, repeatedly, and could not be reproduced here: every
   measurement in headless Chrome, computed style, full cascade dump and
   sampled pixels, returned white. The stylesheet served over HTTP was byte
   identical to disk and parsed to 232 rules, while the affected browser
   reported 241, so nine rules were coming from somewhere outside this file
   and were never identified.

   Rather than leave it resolving through `color: inherit`, which is what was
   in dispute, the colour is stated outright here. -webkit-text-fill-color is
   set alongside it because it wins over `color` for glyph painting where both
   apply, so setting only `color` would leave a gap.

   If the source of the extra rules is ever found, this can go back to
   inheriting. Until then it stays. */
.model-band .btn--outline {
  color: #FFFFFF;
  -webkit-text-fill-color: #FFFFFF;
}

.mb-actions {
  display: flex;
  justify-content: center;
  margin-top: var(--mb-actions-gap);
}

/* --------------------------------------------------------------------------
   6e. Applications
   Six cards in a 3x2 grid on the same 373.3 + 40 grid as how-it-works.
   -------------------------------------------------------------------------- */

.apps {
  background: var(--light);
  color: var(--black);
  padding-top: var(--apps-pad-top);
  padding-bottom: var(--apps-pad-bottom);
}

.apps-head { text-align: center; }

.apps-head .section-h2 {
  /* Holds the export's two-line break, after "of". */
  max-width: var(--apps-h2-width);
  margin-inline: auto;
}

.apps-intro {
  margin: var(--apps-intro-gap) auto 0;
  max-width: var(--apps-intro-width);
  font-size: var(--fs-section-intro);
  font-weight: 400;
  line-height: var(--lh-section-intro);
  color: var(--black);      /* MEASURED. The section intro is black, unlike the
                               card body, which is the muted grey. */
}

.app-grid {
  list-style: none;
  margin: var(--apps-grid-gap) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--apps-gap);
}

.app-card {
  position: relative;
  overflow: hidden;         /* clips the spotlight to the card radius */
  padding: var(--apps-card-pad);
  background: var(--apps-card-bg);
  /* Inset shadow rather than a border. A 1px border would eat 2px of content
     width, which is enough to push the longest line in "AI & Agents" onto a
     fourth row and make that grid row taller than the export. This is also
     what the hover state recolours, since there is no border to change. */
  box-shadow: inset 0 0 0 1px var(--apps-card-border);
  border-radius: var(--radius-app-card);
  transition: box-shadow var(--apps-hover-ms) ease;
}

/* Keeps the card content painting above the spotlight overlay. Positioned
   elements paint after in-flow ones, and ::before comes first in DOM order. */
.app-card > * { position: relative; }

/* Outline reacts to keyboard focus as well as hover. This currently never
   matches: the cards hold no link or button, so nothing inside them can take
   focus. It is here so the state is correct the moment a card becomes
   interactive. Adding tabindex to make it match today would put six inert
   stops in the tab order, which is worse than the state being dormant. */
.app-card:focus-within,
.app-card:has(:focus-visible) {
  box-shadow: inset 0 0 0 1px var(--apps-card-border-active);
}

/* Spotlight. Hover-capable pointers only, so a touch device cannot leave the
   glow stuck on after a tap. */
@media (hover: hover) {
  .app-card::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--apps-hover-ms) ease;
    background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 50%),
                                var(--apps-spotlight), transparent 70%);
  }
  .app-card:hover::before { opacity: 1; }
  .app-card:hover { box-shadow: inset 0 0 0 1px var(--apps-card-border-active); }
}

/* Reduced motion keeps the outline change and drops the spotlight entirely.
   The JS also skips tracking, so without this the glow would sit frozen in
   the middle of the card. */
@media (prefers-reduced-motion: reduce) {
  .app-card::before { display: none; }
}

/* Icon tile. The six SVGs are inlined rather than loaded via <img> so that
   currentColor resolves against this rule; an <img> cannot inherit it. */
.app-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--apps-icon-size);
  height: var(--apps-icon-size);
  border-radius: var(--radius-icon-tile);
  background: var(--apps-icon-bg);
  color: var(--brand);      /* every icon path is currentColor */
}

/* The artwork is drawn at 38px inside its own viewBox, which reproduces the
   export's 16x23 glyph ink centred in the 48px tile. height:auto keeps the
   one non-square icon (wearables, 38x39) from being squashed. */
.app-icon svg {
  width: var(--apps-icon-art);
  height: auto;
  display: block;
}

.app-title {
  margin: var(--apps-title-gap) 0 0;
  font-size: var(--fs-h3);
  font-weight: var(--fw-h3);
  line-height: var(--lh-h3);
  color: var(--black);
}

.app-body {
  margin: var(--apps-body-gap) 0 0;
  font-size: var(--fs-card-body);
  font-weight: 400;
  line-height: var(--lh-card-body);
  color: var(--text-on-light);
}


/* --------------------------------------------------------------------------
   6f. Hardware band, full-bleed black
   #000000 is a third dark tone alongside the hero's #19191B and the footer's
   #07083A. That is what the mockup has.
   -------------------------------------------------------------------------- */

.hw {
  background: var(--black);
  color: var(--text-on-dark);
  padding-top: var(--hw-pad-top);
  padding-bottom: var(--hw-pad-bottom);
}

/* Fixed columns rather than fractions, so the media slot lands on the
   export's x 750 regardless of what the copy does. */
.hw-grid {
  display: grid;
  grid-template-columns: var(--hw-copy-col) var(--hw-media-size);
  align-items: start;
}

/* Wider than its own column on purpose. The H2's long lines run about 20px
   into the media slot, whose left edge is transparent, which is what the
   export does. Nothing is clipped because the grid does not hide overflow. */
.hw-copy { width: var(--hw-copy-max); }   /* width, not max-width: it has to
                                            exceed its own column to overflow */

.hw .section-eyebrow { color: var(--hw-eyebrow); }

.hw-title {
  margin: var(--hw-title-gap) 0 0;
  font-size: var(--fs-h2);
  font-weight: var(--fw-h2);
  line-height: var(--lh-h2);
  letter-spacing: 0;
  color: var(--text-on-dark);
}

.hw-body {
  margin: var(--hw-body-gap) 0 0;
  max-width: var(--hw-body-max);   /* narrower than the H2, so it breaks after
                                      "interpretable" as the export does */
  font-size: var(--fs-section-intro);
  font-weight: 400;
  line-height: var(--lh-hw-body);
  color: var(--text-on-dark);
}

.hw-btn {
  margin-top: var(--hw-btn-gap);
  padding-inline: var(--hw-btn-pad);   /* widens the pill to the export's 296 */
}

/* The slot contains the render rather than filling it, so the whole device is
   visible and nothing is cropped. At 532 tall the render comes out 409 wide
   and centres; the spare width is transparent, so it reads as the black band
   rather than as letterboxing. */
.hw-media {
  width: var(--hw-media-size);
  height: var(--hw-media-size);
  margin-top: var(--hw-media-offset);
  overflow: hidden;
}
.hw-media img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}


/* --------------------------------------------------------------------------
   6g. Privacy strip, REMOVED
   The section was pulled from the homepage because its three claims were
   still placeholders and the page was rendering "Claim 1 pending" to
   visitors. The rules that were here, and the nine --pri-* tokens in section
   2, come back with the markup. See the RESTORE HERE comment in
   index.html for the blocker and the git command.
   -------------------------------------------------------------------------- */


/* --------------------------------------------------------------------------
   6h. FAQ
   -------------------------------------------------------------------------- */

.faq {
  background: var(--light);
  color: var(--black);
  padding-top: var(--faq-pad-top);
  padding-bottom: var(--faq-pad-bottom);
}

.faq-head { text-align: center; }

.faq-list {
  list-style: none;
  margin: var(--faq-list-gap) auto 0;
  padding: 0;
  max-width: var(--faq-list-max);
  border-top: 1px solid var(--faq-rule);
}

.faq-item { border-bottom: 1px solid var(--faq-rule); }

.faq-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: var(--faq-row-pad) var(--faq-row-inset);
  text-align: left;
  font-size: var(--fs-faq-q);
  font-weight: 400;
  line-height: var(--lh-faq-q);
  color: var(--black);
}

.faq-q { margin: 0; font-size: inherit; font-weight: inherit; }

.faq-icon {
  flex: none;
  width: var(--faq-icon);
  height: var(--faq-icon);
  color: var(--brand);
}
.faq-icon svg { width: 100%; height: 100%; }

/* Plus when closed, minus when open. These selectors are deliberately as
   specific as the rule above; a bare .faq-minus loses to .faq-icon svg and
   both icons render at once. */
.faq-icon .faq-minus { display: none; }
.faq-trigger[aria-expanded="true"] .faq-plus  { display: none; }
.faq-trigger[aria-expanded="true"] .faq-minus { display: block; }

/* Collapsed with a 0fr row rather than height:0, so the panel animates to its
   natural height without measuring it. visibility:hidden keeps the collapsed
   text out of the accessibility tree and out of tab order. */
.faq-a {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows var(--faq-ms) ease, visibility 0s linear var(--faq-ms);
}
.faq-a > * {
  overflow: hidden;
  margin: 0;
  padding-inline: var(--faq-row-inset);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-on-light);
  max-width: var(--faq-answer-max);
}
.faq-item.is-open .faq-a {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows var(--faq-ms) ease, visibility 0s;
}
.faq-item.is-open .faq-a > * { padding-bottom: var(--faq-answer-pad); }

@media (prefers-reduced-motion: reduce) {
  .faq-a { transition: none; }
  .faq-item.is-open .faq-a { transition: none; }
}


/* --------------------------------------------------------------------------
   6i. CTA, full-bleed blue
   -------------------------------------------------------------------------- */

.cta {
  background: var(--brand);
  color: var(--text-on-dark);
  padding-top: var(--cta-pad-top);
  padding-bottom: var(--cta-pad-bottom);
  text-align: center;
}

.cta .section-eyebrow { color: var(--text-on-dark); }
.cta .section-h2 {
  color: var(--text-on-dark);
  /* Holds the export's two-line break. At the full 1200 the line fits on one. */
  max-width: var(--cta-form-w);
  margin-inline: auto;
  /* Splits the two lines evenly instead of filling the first and leaving
     "product?" alone on the second. */
  text-wrap: balance;
}

.cta-form {
  width: var(--cta-form-w);
  max-width: 100%;
  margin: var(--cta-form-gap) auto 0;
  display: grid;
  gap: var(--cta-gap);
  text-align: left;
}

.cta-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--cta-gap);
}

/* Field fills are white at 17% over the band rather than a fixed hex, so they
   follow the brand colour if it changes. Recorded in tokens.md. */
.cta-input {
  display: block;           /* inline-level form controls sit on a text
                               baseline, which adds descender space under the
                               textarea and pushes the button down */
  width: 100%;
  height: var(--cta-field-h);
  padding: 0 var(--cta-field-pad);
  font: inherit;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-on-dark);
  background: var(--cta-field-bg);
  border: 0;
  border-radius: var(--radius-field);
  appearance: none;
}
.cta-input::placeholder { color: var(--cta-placeholder); }

/* The select needs its own arrow once appearance is stripped. */
.cta-select {
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 26px) 24px, calc(100% - 20px) 24px;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 48px;
}
.cta-select option { color: var(--black); background: var(--white); }

.cta-send {
  margin-top: var(--cta-send-gap);
  height: var(--cta-btn-h);
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--brand);
  font-size: var(--fs-btn);
  font-weight: var(--fw-btn);
  transition: background-color var(--ease), color var(--ease);
}
.cta-send:hover { background: color-mix(in srgb, var(--white) 90%, var(--brand)); }

.cta-note {
  margin: var(--cta-note-gap) 0 0;
  font-size: var(--fs-footer);
  line-height: var(--lh-body);
  color: var(--cta-note-colour);
}

.cta-success {
  margin: var(--cta-form-gap) auto 0;
  width: var(--cta-form-w);
  max-width: 100%;
}
.cta-check {
  width: 56px;
  height: 56px;
  margin: 0 auto 16px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  background: rgba(255, 255, 255, 0.15);
}
.cta-thanks {
  margin: 0;
  font-size: var(--fs-section-intro);
  line-height: var(--lh-section-intro);
  color: var(--text-on-dark);
}



/* --------------------------------------------------------------------------
   6j. Pricing page
   Rebuilt. The plan cards are no longer separate floating boxes: they are one
   bordered container divided by 1px rules, and every card is a subgrid so
   name, price, note, allowance and CTA sit on the same lines across the row
   regardless of how much copy each plan carries.

   Everything here draws on the existing tokens. The page adds two type sizes
   and one spacing scale, both declared in section 2 with their reasons.
   -------------------------------------------------------------------------- */

/* The page runs light end to end, so the dark body background never shows
   through between sections. */
.pricing-page { background: var(--light); color: var(--black); }


/* Header field ------------------------------------------------------------
   A flat white page under a flat black nav is what made the old version read
   as unfinished. This is a soft brand-tinted field behind the heading that
   fades out into the page, not a gradient panel with an edge: the linear
   layer lands on --light, which is what the section below it is painted in,
   so there is no seam to see. */
.pr-hero {
  position: relative;
  padding-top: var(--pr-6);
  padding-bottom: var(--pr-6);
  text-align: center;
  background:
    radial-gradient(900px 340px at 50% -40px, var(--pr-hero-tint), transparent 72%),
    linear-gradient(180deg, var(--light-alt) 0%, var(--light) 100%);
}

.pr-title {
  margin: 0;
  font-size: var(--fs-pr-h1);
  line-height: var(--lh-pr-h1);
  font-weight: var(--fw-h2);
  letter-spacing: 0;
  color: var(--black);
}

/* Re-derived after the 0.93 type pass took this from 24px to 22px, which
   invalidated the 690px cap the previous sweep landed on. Swept again at the
   new size: no cap between 540 and 750 reads cleanly on its own, but binding
   "around it." with a non-breaking space in the markup opens a clean band from
   580 to 630. 620 sits in the middle of it, which is where the brief asked for
   this in the first place. Three lines, breaking on the colon, then on
   "going", then a three word last line. text-wrap:pretty is the safety net for
   the narrower widths this drops to on smaller screens. */
.pr-intro {
  margin: var(--pr-3) auto 0;
  max-width: 620px;
  text-wrap: pretty;
  font-size: var(--fs-section-intro);
  font-weight: 400;
  line-height: var(--lh-section-intro);
  color: var(--text-on-light);
}


/* Controls ----------------------------------------------------------------
   One row: audience on the left, billing period beside it. They were stacked,
   which read as two unrelated decisions. */
.pr-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--pr-2);
  margin-top: var(--pr-5);
}

.pr-switch,
.pr-billing {
  display: flex;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--white);
  box-shadow: inset 0 0 0 1px var(--pr-rule);
}

.pr-switch-btn,
.pr-bill-btn {
  border-radius: var(--radius-pill);
  font-weight: 500;
  color: var(--text-on-light);
  transition: background-color var(--apps-hover-ms) ease,
              color var(--apps-hover-ms) ease;
  white-space: nowrap;
}
.pr-switch-btn { padding: 11px 26px; font-size: var(--fs-nav); }
.pr-bill-btn   { padding: 11px 22px; font-size: var(--fs-footer); }

.pr-switch-btn.is-on,
.pr-bill-btn.is-on { background: var(--brand); color: var(--white); }

.pr-switch-btn:not(.is-on):hover,
.pr-bill-btn:not(.is-on):hover { color: var(--black); }


/* Plan block --------------------------------------------------------------- */
.pr-plans { padding-bottom: var(--pr-7); }

/* One container, one radius, one border. The 1px grid gap is filled by the
   container's own background, which is how the dividing rules are drawn:
   no per-card borders to double up at the joins. overflow:hidden is what
   clips the outer cards to the shared radius. */
.pr-table {
  display: grid;
  gap: 1px;
  background: var(--pr-rule);
  border: 1px solid var(--pr-rule);
  border-radius: var(--radius-app-card);
  overflow: hidden;
}
.pr-table--3 { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(8, auto); }
.pr-table--2 {
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: repeat(8, auto);
  max-width: var(--pr-two-max);
  margin-inline: auto;
}

/* Each card spans the eight shared rows and adopts them as its own, so plan
   name, price, billing note, allowance and CTA all land on the same baseline
   across the row however much copy sits above them. This is the fix for the
   CTAs sitting at different heights. */
.pr-card {
  grid-row: span 8;
  display: grid;
  grid-template-rows: subgrid;
  align-content: start;
  padding: var(--pr-4);
  background: var(--pr-card-bg);
  transition: background-color var(--apps-hover-ms) ease;
}

/* Hover, same restraint as the applications spotlight: a fill change at the
   same 180ms, no transform, no shadow, no scale. */
@media (hover: hover) {
  .pr-card:hover { background: var(--pr-card-hover); }
  .pr-card--featured:hover { background: var(--pr-featured-bg); }
}

/* The highlighted plan steps out of the shared treatment: its own fill and a
   2px brand edge, drawn as an inset shadow so it stays inside the container's
   clip and does not shift the card by a pixel. It is also the only card whose
   CTA is filled. */
.pr-card--featured {
  background: var(--pr-featured-bg);
  box-shadow: inset 0 0 0 2px var(--brand);
}

/* Browsers without subgrid fall back to the old stacked card. Nothing breaks,
   the CTAs simply stop aligning. */
@supports not (grid-template-rows: subgrid) {
  .pr-table--3, .pr-table--2 { grid-template-rows: none; }
  .pr-card { grid-row: auto; display: flex; flex-direction: column; }
}

/* An empty cell still holds its row open at the height the other cards set,
   which is what keeps the rows aligned. Zeroing the margin stops it adding
   space of its own on top of that. */
.pr-blurb:empty,
.pr-note:empty,
.pr-allowance:empty { margin: 0; }

.pr-name {
  margin: 0;
  font-size: var(--fs-h3);
  font-weight: var(--fw-h3);
  line-height: var(--lh-h3);
  color: var(--black);
}
.pr-blurb {
  margin: var(--pr-1) 0 0;
  font-size: var(--fs-card-body);
  line-height: var(--lh-card-body);
  color: var(--text-on-light);
}
.pr-price {
  margin: var(--pr-3) 0 0;
  font-size: var(--fs-pr-price);
  font-weight: var(--fw-h2);
  line-height: 1.05;
  color: var(--black);
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  column-gap: 6px;
}
.pr-period {
  font-size: var(--fs-card-body);
  font-weight: 400;
  line-height: var(--lh-card-body);
  color: var(--text-on-light);
}
.pr-note {
  margin: var(--pr-2) 0 0;
  font-size: var(--fs-footer);
  line-height: 22px;
  color: var(--text-on-light);
}
.pr-allowance {
  margin: var(--pr-2) 0 0;
  font-size: var(--fs-card-body);
  line-height: var(--lh-card-body);
  color: var(--black);
}
.pr-seats { color: var(--text-on-light); }

.pr-card-cta {
  width: 100%;
  margin-top: var(--pr-3);
}

/* Every CTA but the featured one is .btn--outline, which takes its colour
   from this page's own text colour. No rule is needed here: a page-scoped
   .btn--outline used to live at this spot, and removing it is the point. See
   the note on .btn--outline in section 5. */

/* The divider the feature list sits under. It is the top edge of its own
   shared row, so it lines up across every card in the block. */
.pr-what {
  margin: var(--pr-4) 0 0;
  padding-top: var(--pr-3);
  border-top: 1px solid var(--pr-rule);
  font-size: var(--fs-footer);
  font-weight: 500;
  color: var(--black);
}

.pr-feats { margin-top: var(--pr-3); }
.pr-feat-head {
  margin: 0 0 var(--pr-2);
  font-size: var(--fs-card-body);
  font-weight: 500;
  line-height: var(--lh-card-body);
  color: var(--black);
}
.pr-feats ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
}
.pr-feats li {
  position: relative;
  padding-left: var(--pr-3);
  font-size: var(--fs-card-body);
  line-height: var(--lh-card-body);
  color: var(--text-on-light);
}

/* Tick drawn in CSS rather than shipping another icon file. The card lists
   draw it from ::before so the list items need no extra markup; the table
   cells need a real element to centre, so they get .pr-tick. Same geometry. */
.pr-tick {
  position: absolute;
  left: 0;
  top: 3px;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  rotate: -45deg;
}
.pr-feats li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 9px;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  rotate: -45deg;
}

.pr-smallprint {
  margin-top: var(--pr-5);
  text-align: center;
}
.pr-smallprint p {
  margin: 0;
  font-size: var(--fs-footer);
  line-height: 24px;
  color: var(--text-on-light);
}
.pr-smallprint a { color: var(--brand); text-decoration: underline; }


/* Comparison table --------------------------------------------------------- */
.pr-compare {
  padding-top: var(--pr-7);
  padding-bottom: var(--pr-7);
  background: var(--light-alt);
  color: var(--black);
}
.pr-section-head { text-align: center; }
.pr-sub {
  margin: var(--pr-2) auto 0;
  max-width: 620px;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-on-light);
}

.pr-matrix {
  width: 100%;
  margin-top: var(--pr-5);
  border-collapse: collapse;
  text-align: left;
  background: var(--white);
  border: 1px solid var(--pr-rule);
  border-radius: var(--radius-app-card);
  overflow: hidden;
}

.pr-matrix th,
.pr-matrix td {
  padding: 14px var(--pr-2);
  border-bottom: 1px solid var(--pr-rule);
  vertical-align: middle;
}
.pr-matrix tbody tr:last-child th,
.pr-matrix tbody tr:last-child td { border-bottom: 0; }

.pr-matrix thead th {
  padding-top: var(--pr-3);
  padding-bottom: var(--pr-3);
  vertical-align: bottom;
  background: var(--light);
}
.pr-plan-name {
  display: block;
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: var(--lh-body);
  color: var(--black);
}
.pr-plan-price {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-footer);
  font-weight: 400;
  color: var(--text-on-light);
}
.pr-matrix thead th:first-child { width: 28%; }

/* The highlighted plan keeps its identity in the table too. */
.pr-matrix .is-featured { background: var(--pr-featured-bg); }
.pr-matrix thead th.is-featured { background: var(--pr-featured-bg); }

.pr-matrix tbody th {
  font-size: var(--fs-card-body);
  font-weight: 400;
  line-height: var(--lh-card-body);
  color: var(--black);
}
.pr-matrix tbody td {
  font-size: var(--fs-card-body);
  line-height: var(--lh-card-body);
  color: var(--text-on-light);
}

/* Row hover, same family as the card hover and the applications spotlight. */
@media (hover: hover) {
  .pr-matrix tbody tr { transition: background-color var(--apps-hover-ms) ease; }
  .pr-matrix tbody tr:hover { background: var(--pr-row-hover); }
}

/* Cells carrying a tick or a bar centre it; cells carrying words do not. */
/* 12px box, tick centred inside it, so the glyph sits on the row's optical
   centre rather than 6px below it. The rotation is about the element centre,
   which is why the offset is half the tick height and not the whole of it. */
.pr-cell { position: relative; display: block; width: 11px; height: 12px; }
.pr-bar {
  position: absolute;
  left: 0;
  top: 5px;
  width: 11px;
  height: 2px;
  background: var(--muted-on-light);
}


/* FAQ ---------------------------------------------------------------------
   Two columns: the heading and its line on the left, the accordion on the
   right. The accordion itself is the one already built for the homepage,
   reused class for class. */
.pr-faq {
  padding-top: var(--pr-7);
  padding-bottom: var(--pr-7);
  background: var(--light);
  color: var(--black);
}
.pr-faq-grid {
  display: grid;
  grid-template-columns: var(--pr-faq-col) 1fr;
  gap: var(--pr-6);
  align-items: start;
}
.pr-faq-head .section-h2 { text-align: left; }
.pr-faq-head .pr-sub { margin-inline: 0; max-width: none; }

/* The homepage centres this list at a fixed width. Here it fills its column. */
.pr-faq .faq-list {
  margin: 0;
  max-width: none;
  border-top: 1px solid var(--pr-rule);
}
.pr-faq .faq-item { border-bottom-color: var(--pr-rule); }
.pr-faq .faq-trigger {
  padding-inline: 0;
  font-size: var(--fs-h3);
  transition: color var(--apps-hover-ms) ease;
}
.pr-faq .faq-a > * { padding-inline: 0; max-width: none; }
@media (hover: hover) {
  .pr-faq .faq-trigger:hover { color: var(--brand); }
}


/* Dark CTA band -----------------------------------------------------------
   --footer-navy rather than a fourth dark tone. It shares an edge with the
   footer, so a hairline keeps the two from reading as one long block. */
.pr-band {
  padding-top: var(--pr-7);
  padding-bottom: var(--pr-7);
  background: var(--footer-navy);
  color: var(--text-on-dark);
  text-align: center;
}
.pr-band .section-h2 { color: var(--text-on-dark); }
.pr-band .pr-sub { color: var(--muted-on-navy); }
.pr-band .btn { margin-top: var(--pr-5); }
/* The band and the footer are the same navy by design, so a hairline keeps
   them from reading as one very tall block. Scoped to the page rather than
   written as .pr-band + .site-footer: the band sits inside <main>, so it is
   never the footer's sibling and that selector never matches. */
.pricing-page .site-footer { border-top: 1px solid rgba(255, 255, 255, 0.08); }


/* Pricing page responsive -------------------------------------------------
   Cards go three across, then two, then one. The comparison table becomes a
   list of features rather than a horizontal scrollbar. */
@media (max-width: 1200px) {
  :root { --fs-pr-h1: 48px; --lh-pr-h1: 58px; --fs-pr-price: 41px; }
  .pr-card { padding: var(--pr-3); }
  .pr-matrix th, .pr-matrix td { padding: 12px 12px; }
  .pr-faq-grid { grid-template-columns: 320px 1fr; gap: var(--pr-5); }
}

@media (max-width: 900px) {
  :root { --fs-pr-h1: 41px; --lh-pr-h1: 50px; --fs-pr-price: 37px; }
  .pr-table--3 { grid-template-columns: repeat(2, 1fr); }
  .pr-faq-grid { grid-template-columns: 1fr; gap: var(--pr-4); }
  .pr-faq-head .pr-sub { max-width: 620px; }
}

/* Comparison table stops being a table. Each feature becomes a block with the
   plan names beside its own result, which is a layout a phone can actually
   read rather than a grid pushed off the side of the screen. */
@media (max-width: 768px) {
  .pr-matrix,
  .pr-matrix tbody,
  .pr-matrix tr,
  .pr-matrix th,
  .pr-matrix td { display: block; }
  .pr-matrix thead { display: none; }
  .pr-matrix { border-radius: var(--radius-app-card); }
  .pr-matrix tbody tr {
    padding: var(--pr-2) var(--pr-3);
    border-bottom: 1px solid var(--pr-rule);
  }
  .pr-matrix tbody tr:last-child { border-bottom: 0; }
  .pr-matrix tbody th,
  .pr-matrix tbody td { padding: 0; border-bottom: 0; }
  .pr-matrix tbody th { margin-bottom: var(--pr-1); font-weight: 500; }
  .pr-matrix tbody td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--pr-3);
    padding: 3px 0;
  }
  .pr-matrix tbody td::before {
    content: attr(data-plan);
    color: var(--muted-on-light);
  }
  .pr-matrix .is-featured { background: transparent; }
  .pr-cell { flex: none; }
}

@media (max-width: 760px) {
  .pr-table--3,
  .pr-table--2 { grid-template-columns: 1fr; max-width: 420px; margin-inline: auto; }
  .pr-switch-btn { padding: 10px 18px; font-size: var(--fs-footer); }
  .pr-bill-btn   { padding: 10px 16px; }
  .pr-intro { font-size: var(--fs-body); line-height: var(--lh-body); }
  .pr-faq .faq-trigger { font-size: var(--fs-body); }
  .pr-hero, .pr-compare, .pr-faq, .pr-band { padding-block: var(--pr-6); }
  .pr-plans { padding-bottom: var(--pr-6); }
}

/* The toggle and the accordion both animate. Section 9 zeroes every
   transition globally, and the accordion carries its own rule alongside it;
   this is the toggle's, kept next to what it applies to. */
@media (prefers-reduced-motion: reduce) {
  .pr-switch-btn,
  .pr-bill-btn,
  .pr-card,
  .pr-matrix tbody tr,
  .pr-faq .faq-trigger { transition: none; }
}


/* --------------------------------------------------------------------------
   7. Footer
   Same space-between structure as the nav, but on an 80px gutter.
   -------------------------------------------------------------------------- */

.site-footer {
  background: var(--footer-navy);
  color: var(--text-on-dark);
  padding-block: var(--footer-pad-y);
  --gutter: var(--gutter-footer);
}

.footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  flex-wrap: wrap;
}

.footer-logo img { width: 107px; height: auto; }

.footer-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--footer-link-gap);
}

.footer-links a,
.footer-meta a,
.footer-copyright {
  font-size: var(--fs-footer);
  font-weight: var(--fw-footer);
  color: var(--muted-on-navy);
}

.footer-links a,
.footer-meta a { transition: color var(--ease); }
.footer-links a:hover,
.footer-meta a:hover { color: var(--white); }

/* Copyright and LinkedIn travel together as one group, per brief v2. */
.footer-meta {
  display: flex;
  align-items: center;
  gap: 20px;
}

.footer-copyright { margin: 0; white-space: nowrap; }


/* --------------------------------------------------------------------------
   8. Responsive
   The mockup is desktop only, so these breakpoints are my call, per the brief.
   -------------------------------------------------------------------------- */

/* Below the full canvas, shrink the gutters rather than the content. */
@media (max-width: 1200px) {
  :root { --gutter: 64px; --gutter-footer: 48px; }
  .nav-links { gap: 28px; }

  /* Card stops being a fixed 551 and shares the row proportionally. */
  :root { --hero-col-gap: 56px; --hero-pad-top: 96px; --hero-pad-bottom: 96px; }
  :root { --hiw-col-gap: 28px; --hiw-head-gap: 64px;
          --fs-h2: 37px; --lh-h2: 52px;
          --mb-col-gap: 48px; --mb-video-height: 260px; }
  .hero-grid { grid-template-columns: 1fr minmax(0, 480px); }
  :root { --fs-h1: 43px; --lh-h1: 52px; }

}

/* The hardware band is fixed at 630px + 532px, which is 1162 plus the gap.
   That only fits inside the 1200px content box of the full 1440 canvas, so
   below 1440 it pushed the whole page sideways: 2px at 1280, 202px at 1024,
   418px at 768 and 796px at 390. It had no responsive rule of any kind.

   The fixed layout is kept for the canvas it was measured against and
   everything narrower goes fluid. .hw-copy loses its fixed 690px width here:
   that width is deliberately wider than its own 630px column so the H2 runs
   about 20px into the transparent media slot, matching the export, and it is
   exactly the wrong behaviour once the columns are narrower than the copy. */
@media (max-width: 1439px) {
  .hw-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, var(--hw-media-size));
    gap: 40px;
  }
  .hw-copy { width: auto; max-width: 100%; }
  .hw-body { max-width: none; }
  .hw-media { width: 100%; height: auto; aspect-ratio: 1 / 1; }
}

/* Applications drop to two columns here. The grid is repeat(3, 1fr), which
   shrinks the cards rather than reflowing them, so without this it stays three
   across all the way down and the titles clip mid-word. Two columns from 1024
   holds the cards near 320px, which is the width they were designed at. */
@media (max-width: 1024px) {
  .app-grid { grid-template-columns: repeat(2, 1fr); }
}

/* One column. The card goes under the copy and stays square. */
@media (max-width: 900px) {
  :root { --fs-h1: 37px; --lh-h1: 45px; --fs-lead: 17px; --lh-lead: 28px; }

  /* The hardware band had no responsive rule at all. Its grid was a fixed
     630px + 532px and its copy a fixed 690px width, so it stayed two columns
     at every width and pushed the whole page to a 1186px scroll width down to
     390. That was the horizontal overflow on this page, not the nav or the
     cards. Stack it, and let both halves size to the column. */
  .hw-grid { grid-template-columns: 1fr; gap: 48px; }
  .hw-copy { width: auto; max-width: 100%; }
  .hw-body { max-width: none; }
  .hw-media {
    width: min(var(--hw-media-size), 100%);
    height: auto;
    aspect-ratio: 1 / 1;
    margin-inline: auto;
  }

  /* Steps stack. The image keeps a real column of its own rather than being
     shrunk beside the copy, which is the whole point of this layout. */
  .hiw-steps { grid-template-columns: 1fr; gap: 56px; }
  .hiw-body { max-width: none; }

  .mb-grid { grid-template-columns: 1fr; gap: 40px; }
  .mb-visual { height: 240px; }
  .hero-grid {
    grid-template-columns: 1fr;
    gap: 48px;
  }
  .hero-visual { max-width: 480px; }
  .hero-lead { max-width: none; }
}

/* The desktop nav row stops fitting here, so it collapses to a hamburger.
   Try Sentien stays visible in the collapsed bar, as the brief requires. */
@media (max-width: 900px) {
  :root { --gutter: var(--gutter-mobile); --gutter-footer: var(--gutter-mobile); }

  .nav-toggle { display: inline-flex; }

  .nav-links {
    display: none;
    order: 3;
    flex-basis: 100%;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    padding-block: 8px 4px;
  }
  .nav-links.is-open { display: flex; }
  .nav-links a { padding-block: 12px; }

  /* Login moves out of the top bar and into the open panel. */
  .nav-actions .nav-login { display: none; }
  .nav-login--mobile { display: block; }

  .nav-row { flex-wrap: wrap; row-gap: 4px; }

  .footer-row {
    justify-content: flex-start;
    gap: 24px;
  }
  .footer-links { gap: 16px 20px; }
}

/* Applications go single column. Two 1fr columns inside a 342px content box
   would be about 150px each, which is narrower than the card was ever drawn
   for and clips the longer titles. */
@media (max-width: 640px) {
  .app-grid { grid-template-columns: 1fr; gap: 24px; }
}

/* Phone widths. The bar has to hold the logo, the Try Sentien button and the
   hamburger on one line without overflowing, so all three shrink together. */
@media (max-width: 560px) {
  :root {
    --nav-pad-top: 24px;
    --fs-nav: 16px;
    --fs-btn: 14px;
    --nav-action-gap: 12px;
    --footer-link-gap: 14px;
  }

  .nav-row { gap: 12px; }
  .nav-logo img { width: 120px; }
  .btn { padding: 12px 18px; }
  .nav-toggle { width: 40px; }

  /* The copyright line plus LinkedIn is about 342px wide and the line is set
     nowrap, so below roughly 400px the pair pushed past the right gutter and
     gave the whole page a horizontal scrollbar. Letting the group wrap fixes
     it. This is a shared-footer fix: it applies to every page using
     styles.css, not just /pricing. */
  .footer-meta { flex-wrap: wrap; gap: 8px 20px; }
  .footer-copyright { white-space: normal; }
}

/* Smallest phones still in use (320px). The bar holds logo + button + toggle
   on one line, which needs about 352px at the sizes above, so everything
   steps down once more here. */
@media (max-width: 380px) {
  :root { --fs-btn: 14px; --nav-action-gap: 8px; }
  .nav-row { gap: 8px; }
  .nav-logo img { width: 104px; }
  .btn { padding: 10px 14px; }
  .nav-toggle { width: 36px; }
}

/* Flex items default to min-width:auto, which lets a long row push past the
   gutter instead of wrapping. This lets the link rows actually wrap. */
.nav-row > *,
.footer-row > * { min-width: 0; }


/* --------------------------------------------------------------------------
   9. Reduced motion
   Honours the operating system setting. Nothing animates for people who have
   asked for that.
   -------------------------------------------------------------------------- */

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