/* =============================================================
   Visionaire Products, Inc. — Production Stylesheet
   Single consolidated build. No framework, no preprocessor.

   Generated from the Figma file `Visionaire`
   (lD80oAAtQGPXimv26YnGDg), page "↳ Design".

   CONTENTS
     1. Font faces          self-hosted Poppins + Nunito Sans
     2. Design tokens       130 Figma variables, verbatim
     3. Layout gap scale    the one thing Figma does not tokenise
     4. Reset
     5. Page shell
     6. Section
     7. Colour schemes
     8. Container
     9. Auto Layout primitives
    10. Typography utilities
    11. Icons & image placeholders
    12. Button
    13. Navbar
    14. Hero
    15. Stats
    16. Comparison table
    17. Testimonials
    18. Cards
    19. FAQ
    20. CTA form
    21. Footer
    22. Responsive

   RESPONSIVE MODEL
     desktop  >= 992px   Figma Desktop mode
     tablet   768-991px  interpolated — Figma has no tablet artboard
     mobile   <= 767px   Figma Mobile mode (type + spacing verbatim)
   ============================================================= */

/* =============================================================
   1. FONT FACES
   ============================================================= */
/* ---------------- Nunito Sans — variable ---------------- */
@font-face {
  font-family: "Nunito Sans";
  src: url("fonts/NunitoSans-Variable.woff2") format("woff2-variations"),
       url("fonts/NunitoSans-Variable.ttf") format("truetype-variations");
  font-weight: 200 1000;
  font-stretch: 75% 125%;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Nunito Sans";
  src: url("fonts/NunitoSans-Italic-Variable.woff2") format("woff2-variations"),
       url("fonts/NunitoSans-Italic-Variable.ttf") format("truetype-variations");
  font-weight: 200 1000;
  font-stretch: 75% 125%;
  font-style: italic;
  font-display: swap;
}

/* ---------------- Poppins — static instances ---------------- */
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-Thin.woff2") format("woff2");            font-weight: 100; font-style: normal; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-ThinItalic.woff2") format("woff2");      font-weight: 100; font-style: italic; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-ExtraLight.woff2") format("woff2");      font-weight: 200; font-style: normal; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-ExtraLightItalic.woff2") format("woff2");font-weight: 200; font-style: italic; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-Light.woff2") format("woff2");           font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-LightItalic.woff2") format("woff2");     font-weight: 300; font-style: italic; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-Regular.woff2") format("woff2");         font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-Italic.woff2") format("woff2");          font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-Medium.woff2") format("woff2");          font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-MediumItalic.woff2") format("woff2");    font-weight: 500; font-style: italic; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-SemiBold.woff2") format("woff2");        font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-SemiBoldItalic.woff2") format("woff2");  font-weight: 600; font-style: italic; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-Bold.woff2") format("woff2");            font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-BoldItalic.woff2") format("woff2");      font-weight: 700; font-style: italic; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-ExtraBold.woff2") format("woff2");       font-weight: 800; font-style: normal; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-ExtraBoldItalic.woff2") format("woff2"); font-weight: 800; font-style: italic; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-Black.woff2") format("woff2");           font-weight: 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Poppins"; src: url("fonts/Poppins-BlackItalic.woff2") format("woff2");     font-weight: 900; font-style: italic; font-display: swap; }

/* -------------------------------------------------------------
   Variation axis pin.

   Figma applies fontVariationSettings: "YTLC" 500, "wdth" 100 to
   every Nunito Sans text style. Reproduce that globally so weights
   resolve the same way they do on the canvas.
   ------------------------------------------------------------- */
body {
  font-variation-settings: "YTLC" 500, "wdth" 100, "opsz" 12;
}

/* =============================================================
   2. DESIGN TOKENS
   ============================================================= */
:root {
  /* ----------------------------------------------------------
     PRIMITIVES — raw colour ramps (Figma: Primitives)
     Not for direct use in components; reference the semantic
     scheme tokens further down instead.
     ---------------------------------------------------------- */
  --color-white: #ffffff;

  --color-neutral-lightest: #f2f2f2;
  --color-neutral-lighter: #d9d9d9;
  --color-neutral-light: #b3b4b4;
  --color-neutral: #818383;
  --color-neutral-dark: #4e5152;
  --color-neutral-darker: #1c1f20;
  --color-neutral-darkest: #030708;

  --color-dark-lightest: #e6ebee;
  --color-dark-lighter: #cdd7dd;
  --color-dark-light: #50748a;
  --color-dark: #063959;
  --color-dark-dark: #042d47;
  --color-dark-darker: #021623;
  --color-dark-darkest: #01111a;

  --color-regent-st-blue-lightest: #f5fafc;
  --color-regent-st-blue-lighter: #ebf6f9;
  --color-regent-st-blue-light: #b9dfea;
  --color-regent-st-blue: #9cd2e2;
  --color-regent-st-blue-dark: #7ca8b4;
  --color-regent-st-blue-darker: #3e545a;
  --color-regent-st-blue-darkest: #2e3f43;

  --color-background-lightest: #fbfeff;
  --color-background-lighter: #f8fdff;
  --color-background-light: #e8faff;
  --color-background: #dff9ff;
  --color-background-dark: #b2c7cc;
  --color-background-darker: #596366;
  --color-background-darkest: #424a4c;

  --color-downy-lightest: #f0f9f9;
  --color-downy-lighter: #e1f4f3;
  --color-downy-light: #98dbd7;
  --color-downy: #6cccc6;
  --color-downy-dark: #56a39e;
  --color-downy-darker: #2b514f;
  --color-downy-darkest: #203d3b;

  --color-default-lightest: #ebf2f5;
  --color-default-lighter: #d7e6ec;
  --color-default-light: #75a9bc;
  --color-default: #317993;   /* was #3a85a0 — raised to clear AA for white text on Scheme 3 */
  --color-default-dark: #215f74;   /* was #2e6a80 — darkened to restore card/section separation after Color/Default moved */
  --color-default-darker: #173540;
  --color-default-darkest: #112730;

  /* Alpha overlays */
  --opacity-transparent: #ffffff00;
  --opacity-white-5: #ffffff0d;
  --opacity-white-10: #ffffff1a;
  --opacity-white-15: #ffffff26;
  --opacity-white-20: #ffffff33;
  --opacity-white-30: #ffffff4d;
  --opacity-white-40: #ffffff66;
  --opacity-white-50: #ffffff80;
  --opacity-white-60: #ffffff99;
  --opacity-neutral-darkest-5: #0307080d;
  --opacity-neutral-darkest-10: #0307081a;
  --opacity-neutral-darkest-15: #03070826;
  --opacity-neutral-darkest-20: #03070833;
  --opacity-neutral-darkest-30: #0307084d;
  --opacity-neutral-darkest-40: #03070866;
  --opacity-neutral-darkest-50: #03070880;
  --opacity-neutral-darkest-60: #03070899;

  /* ----------------------------------------------------------
     SEMANTIC COLOUR SCHEMES (Figma: Color Schemes)
     8 schemes x 5 roles. These are aliases onto the primitives
     above — this indirection is the whole point, so prefer
     these in application code.
     ---------------------------------------------------------- */

  /* Scheme 1 */
  --scheme-1-text: var(--color-white);
  --scheme-1-foreground: var(--color-dark-dark);
  --scheme-1-background: var(--color-dark);
  --scheme-1-border: var(--opacity-white-20);
  --scheme-1-accent: var(--color-white);

  /* Scheme 2 */
  --scheme-2-text: var(--color-neutral-darkest);
  --scheme-2-background: var(--color-background);
  --scheme-2-border: var(--opacity-neutral-darkest-15);
  --scheme-2-accent: var(--color-dark);
  --scheme-2-foreground: var(--color-background-dark);

  /* Scheme 3 */
  --scheme-3-text: var(--color-white);
  --scheme-3-background: var(--color-default);
  --scheme-3-border: var(--opacity-white-20);
  --scheme-3-accent: var(--color-white);
  --scheme-3-foreground: var(--color-default-dark);

  /* Scheme 4 */
  --scheme-4-text: var(--color-neutral-darkest);
  --scheme-4-background: var(--color-downy);
  --scheme-4-border: var(--opacity-neutral-darkest-15);
  --scheme-4-accent: var(--color-neutral-darkest);
  --scheme-4-foreground: var(--color-downy-dark);

  /* Scheme 5 */
  --scheme-5-text: var(--color-neutral-darkest);
  --scheme-5-background: var(--color-white);
  --scheme-5-border: var(--opacity-neutral-darkest-15);
  --scheme-5-accent: var(--color-dark);
  --scheme-5-foreground: var(--color-neutral-lightest);

  /* Scheme 6 */
  --scheme-6-text: var(--color-white);
  --scheme-6-background: var(--color-dark-darker);
  --scheme-6-border: var(--opacity-white-20);
  --scheme-6-accent: var(--color-white);
  --scheme-6-foreground: var(--color-dark-darkest);

  /* Scheme 7 */
  --scheme-7-text: var(--color-neutral-darkest);
  --scheme-7-background: var(--color-neutral-lightest);
  --scheme-7-border: var(--opacity-neutral-darkest-15);
  --scheme-7-accent: var(--color-dark);
  --scheme-7-foreground: var(--color-white);

  /* Scheme 8 */
  --scheme-8-text: var(--color-neutral-darkest);
  --scheme-8-background: var(--color-default-lighter);
  --scheme-8-border: var(--opacity-neutral-darkest-15);
  --scheme-8-accent: var(--color-dark);
  --scheme-8-foreground: var(--color-default-lightest);

  /* ----------------------------------------------------------
     RADIUS & STROKE (Figma: UI Styles)
     ---------------------------------------------------------- */
  --radius-small: 24px;
  --radius-medium: 32px;
  --radius-procedure: 0px;   /* procedure illustrations carry their own frame */
  --radius-large: 40px;
  --stroke-border-width: 0px;
  --stroke-divider-width: 1px;

  /* ----------------------------------------------------------
     TYPOGRAPHY — families, weights, line heights
     ---------------------------------------------------------- */
  --font-family-heading: "Poppins", sans-serif;
  --font-family-body: "Nunito Sans", sans-serif;

  --font-weight-light: 300;
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-extrabold: 800;

  --line-height-tight: 1.2;   /* H1-H3 */
  --line-height-snug: 1.3;    /* H4 */
  --line-height-heading: 1.4; /* H5-H6 */
  --line-height-body: 1.5;    /* all body text */

  --letter-spacing-heading: -0.01em;
  --letter-spacing-body: 0;

  /* Type scale — Desktop (Figma: Typography / Desktop) */
  --text-sizes-heading-1: 56px;
  --text-sizes-heading-2: 48px;
  --text-sizes-heading-3: 40px;
  --text-sizes-heading-4: 32px;
  --text-sizes-heading-5: 24px;
  --text-sizes-heading-6: 20px;
  --text-sizes-text-large: 20px;
  --text-sizes-text-medium: 18px;
  --text-sizes-text-regular: 16px;
  --text-sizes-text-small: 14px;
  --text-sizes-text-tiny: 12px;

  /* ----------------------------------------------------------
     SPACING & SIZING — Desktop
     (Figma: Spacing & Sizing / Desktop)
     ---------------------------------------------------------- */

  /* Container */
  --container-large: 1440px;
  --container-medium: 1024px;
  --container-small: 768px;

  /* Max Width */
  --max-width-xxlarge: 1280px;
  --max-width-xlarge: 1024px;
  --max-width-large: 768px;
  --max-width-medium: 560px;
  --max-width-small: 480px;
  --max-width-xsmall: 400px;
  --max-width-xxsmall: 320px;

  /* Page Padding */
  --padding-global: 64px;

  /* Section Padding */
  --padding-section-large: 112px;
  --padding-section-medium: 80px;
  --padding-section-small: 48px;

  /* ----------------------------------------------------------
     ELEVATION (Figma effect styles)
     ---------------------------------------------------------- */
  --shadow-xxsmall: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  --shadow-xsmall: 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 1px 3px 0 rgba(0, 0, 0, 0.1);
  --shadow-small: 0 2px 4px -2px rgba(0, 0, 0, 0.06), 0 4px 8px -2px rgba(0, 0, 0, 0.1);
  --shadow-medium: 0 4px 6px -2px rgba(0, 0, 0, 0.03), 0 12px 16px -4px rgba(0, 0, 0, 0.08);
  --shadow-large: 0 8px 8px -4px rgba(0, 0, 0, 0.03), 0 20px 24px -4px rgba(0, 0, 0, 0.08);
  --shadow-xlarge: 0 24px 48px -12px rgba(0, 0, 0, 0.18);
  --shadow-xxlarge: 0 32px 64px -12px rgba(0, 0, 0, 0.14);
  --shadow-menu: 0 8px 8px -4px rgba(0, 0, 0, 0.03), 0 20px 24px -4px rgba(0, 0, 0, 0.08), -2px -2px 24px -4px rgba(0, 0, 0, 0.08);
}

/* ===============================================================
   MOBILE MODE OVERRIDES
   Only tokens whose Mobile value differs from Desktop are
   redeclared. Container and max-width tokens are identical
   across both modes in Figma, so they are omitted here.
   =============================================================== */
@media (max-width: 767px) {
  :root {
    /* Type scale — Mobile */
    --text-sizes-heading-1: 40px;
    --text-sizes-heading-2: 36px;
    --text-sizes-heading-3: 32px;
    --text-sizes-heading-4: 24px;
    --text-sizes-heading-5: 20px;
    --text-sizes-heading-6: 18px;
    --text-sizes-text-large: 18px;
    --text-sizes-text-medium: 16px;
    --text-sizes-text-regular: 14px;
    --text-sizes-text-small: 12px;
    --text-sizes-text-tiny: 10px;

    /* Spacing — Mobile */
    --padding-global: 20px;
    --padding-section-large: 64px;
    --padding-section-medium: 48px;
    --padding-section-small: 32px;
  }
}

/* ===============================================================
   TEXT STYLE UTILITIES
   One class per Figma text style (42 total). Sizes reference the
   type-scale variables above, so these stay responsive.
   =============================================================== */

.heading-h1 {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-heading-1);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.heading-h2 {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-heading-2);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.heading-h3 {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-heading-3);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.heading-h4 {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-heading-4);
  line-height: 1.3;
  letter-spacing: -0.01em;
}

.heading-h5 {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-heading-5);
  line-height: 1.4;
  letter-spacing: -0.01em;
}

.heading-h6 {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-heading-6);
  line-height: 1.4;
  letter-spacing: -0.01em;
}

.heading-tagline {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-semibold);
  font-size: 1rem;
  line-height: 1.5;
}

.text-large-light {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-light);
  font-size: var(--text-sizes-text-large);
  line-height: 1.5;
}

.text-large-normal {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-large);
  line-height: 1.5;
}

.text-large-medium {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-text-large);
  line-height: 1.5;
}

.text-large-semi-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sizes-text-large);
  line-height: 1.5;
}

.text-large-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-text-large);
  line-height: 1.5;
}

.text-large-extra-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-extrabold);
  font-size: var(--text-sizes-text-large);
  line-height: 1.5;
}

.text-large-link {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-large);
  line-height: 1.5;
  text-decoration: underline;
}

.text-medium-light {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-light);
  font-size: var(--text-sizes-text-medium);
  line-height: 1.5;
}

.text-medium-normal {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-medium);
  line-height: 1.5;
}

.text-medium-medium {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-text-medium);
  line-height: 1.5;
}

.text-medium-semi-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sizes-text-medium);
  line-height: 1.5;
}

.text-medium-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-text-medium);
  line-height: 1.5;
}

.text-medium-extra-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-extrabold);
  font-size: var(--text-sizes-text-medium);
  line-height: 1.5;
}

.text-medium-link {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-medium);
  line-height: 1.5;
  text-decoration: underline;
}

.text-regular-light {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-light);
  font-size: var(--text-sizes-text-regular);
  line-height: 1.5;
}

.text-regular-normal {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-regular);
  line-height: 1.5;
}

.text-regular-medium {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-text-regular);
  line-height: 1.5;
}

.text-regular-semi-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sizes-text-regular);
  line-height: 1.5;
}

.text-regular-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-text-regular);
  line-height: 1.5;
}

.text-regular-extra-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-extrabold);
  font-size: var(--text-sizes-text-regular);
  line-height: 1.5;
}

.text-regular-link {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-regular);
  line-height: 1.5;
  text-decoration: underline;
}

.text-small-light {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-light);
  font-size: var(--text-sizes-text-small);
  line-height: 1.5;
}

.text-small-normal {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-small);
  line-height: 1.5;
}

.text-small-medium {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-text-small);
  line-height: 1.5;
}

.text-small-semi-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sizes-text-small);
  line-height: 1.5;
}

.text-small-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-text-small);
  line-height: 1.5;
}

.text-small-extra-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-extrabold);
  font-size: var(--text-sizes-text-small);
  line-height: 1.5;
}

.text-small-link {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-small);
  line-height: 1.5;
  text-decoration: underline;
}

.text-tiny-light {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-light);
  font-size: var(--text-sizes-text-tiny);
  line-height: 1.5;
}

.text-tiny-normal {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-tiny);
  line-height: 1.5;
}

.text-tiny-medium {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-text-tiny);
  line-height: 1.5;
}

.text-tiny-semi-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sizes-text-tiny);
  line-height: 1.5;
}

.text-tiny-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-text-tiny);
  line-height: 1.5;
}

.text-tiny-extra-bold {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-extrabold);
  font-size: var(--text-sizes-text-tiny);
  line-height: 1.5;
}

.text-tiny-link {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-sizes-text-tiny);
  line-height: 1.5;
  text-decoration: underline;
}

/* =============================================================
   3. LAYOUT GAP SCALE

   Figma binds padding, fills, max-width and stroke weight to
   variables — but never itemSpacing (0 of 16 section frames had a
   bound gap). These fill that hole.
   ============================================================= */
:root {
  --gap-4: 4px;
  --gap-6: 6px;
  --gap-8: 8px;
  --gap-12: 12px;
  --gap-16: 16px;
  --gap-24: 24px;
  --gap-32: 32px;
  --gap-40: 40px;
  --gap-48: 48px;
  --gap-64: 64px;
  --gap-80: 80px;
  --gap-section: var(--gap-80);

  /* Text/Stat — Poppins Bold 80. New style: the statistics were a
     raw override in Figma with no size variable bound, so they sat
     outside the type scale entirely. Worth adding to the Typography
     collection as "Text Sizes/Stat" with a Mobile mode so it swaps
     like every other size; until then the steps below are ours. */
  --text-sizes-stat: 75px;

  /* Breakpoints, for reference — CSS can't use vars in media queries.
     desktop >= 992px · tablet 768-991px · mobile <= 767px */
}

/* =============================================================
   4. RESET

   Figma has no inherited margins and every frame is border-box
   (padding sits inside). Match that or every padding value is off.
   ============================================================= */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  font-family: var(--font-family-body);
  font-size: var(--text-sizes-text-regular);
  line-height: var(--line-height-body);
  color: var(--scheme-7-text);
  background: var(--scheme-7-background);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Navbar is fixed (out of flow) — reserve its height so content
     doesn't start underneath it. Updated at the mobile breakpoint
     below to match the shorter mobile bar. */
  padding-top: 72px;
}

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

h1, h2, h3, h4, h5, h6 { margin: 0; font-family: var(--font-family-heading); font-weight: var(--font-weight-medium); letter-spacing: var(--letter-spacing-heading); }
h1 { font-size: var(--text-sizes-heading-1); line-height: var(--line-height-tight); }
h2 { font-size: var(--text-sizes-heading-2); line-height: var(--line-height-tight); }
h3 { font-size: var(--text-sizes-heading-3); line-height: var(--line-height-tight); }
h4 { font-size: var(--text-sizes-heading-4); line-height: var(--line-height-snug); }
h5 { font-size: var(--text-sizes-heading-5); line-height: var(--line-height-heading); }
h6 { font-size: var(--text-sizes-heading-6); line-height: var(--line-height-heading); }

p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
a { color: inherit; }
button { font: inherit; color: inherit; }

:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; border-radius: 2px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: var(--gap-16); top: -100%; z-index: 1100;
  padding: var(--gap-8) var(--gap-16); border-radius: 8px;
  background: var(--scheme-1-background); color: var(--scheme-1-text);
  text-decoration: none;
}
.skip-link:focus { top: var(--gap-16); }

/* =============================================================
   5. PAGE SHELL

   Figma: "Home • Desktop" FRAME · VERTICAL · gap 0 · padding 0
          · 1440 FIXED wide · height HUG

   The 1440 is the artboard, not a constraint — every section is
   width-FILL, so the page is fluid and .container does the work.
   ============================================================= */
.page { display: flex; flex-direction: column; width: 100%; min-height: 100vh; }

/* =============================================================
   6. SECTION

   Figma: FRAME · VERTICAL · primary start / counter CENTER
          · py = Section Padding/padding-section-large
          · px = Page Padding/padding-global
          · width FILL · height HUG · has fill

   63 of these across the five pages, all with the same binding.
   ============================================================= */
.section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-section);
  width: 100%;
  padding: var(--padding-section-large) var(--padding-global);
  background: var(--scheme-7-background);
  color: var(--scheme-7-text);
}

.section--pad-medium { padding-block: var(--padding-section-medium); }
.section--pad-small  { padding-block: var(--padding-section-small); }
.section--flush-top    { padding-top: 0; }
.section--flush-bottom { padding-bottom: 0; }
.section--gap-40 { gap: var(--gap-40); }
/* "Header / 70 /" is py 112 / 64 — top large, bottom page-padding. */
.section--pad-bottom-global { padding-bottom: var(--padding-global); }

/* "Banner / 10 /" and "FAQ / 2 /" — thin strips.
   Figma padding is 0/64/12/64: no top padding, 12 at the bottom.
   The inner container carries its own 8px block padding. */
.section--strip {
  padding-top: 0;
  padding-bottom: var(--gap-12);
  gap: 0;
  border-bottom: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-1-border));
}
.section--strip > .container { padding-block: var(--gap-8); }
/* "FAQ / 2 /" is p12/64/12/64 — padded top AND bottom, unlike the banner. */
.section--strip-even { padding-top: var(--gap-12); border-bottom: 0; }
.section--strip-even > .container { padding-block: 0; }

/* =============================================================
   7. COLOUR SCHEMES

   Every section frame binds its fill to a Color Scheme background.
   Applying a scheme class rebinds background, text, border and
   accent together, mirroring how the tokens are grouped in Figma.
   ============================================================= */
.scheme-1 { background: var(--scheme-1-background); color: var(--scheme-1-text); --scheme-background: var(--scheme-1-background); --scheme-border: var(--scheme-1-border); --scheme-accent: var(--scheme-1-accent); --scheme-foreground: var(--scheme-1-foreground); }
.scheme-2 { background: var(--scheme-2-background); color: var(--scheme-2-text); --scheme-background: var(--scheme-2-background); --scheme-border: var(--scheme-2-border); --scheme-accent: var(--scheme-2-accent); --scheme-foreground: var(--scheme-2-foreground); }
.scheme-3 { background: var(--scheme-3-background); color: var(--scheme-3-text); --scheme-background: var(--scheme-3-background); --scheme-border: var(--scheme-3-border); --scheme-accent: var(--scheme-3-accent); --scheme-foreground: var(--scheme-3-foreground); }
.scheme-4 { background: var(--scheme-4-background); color: var(--scheme-4-text); --scheme-background: var(--scheme-4-background); --scheme-border: var(--scheme-4-border); --scheme-accent: var(--scheme-4-accent); --scheme-foreground: var(--scheme-4-foreground); }
.scheme-5 { background: var(--scheme-5-background); color: var(--scheme-5-text); --scheme-background: var(--scheme-5-background); --scheme-border: var(--scheme-5-border); --scheme-accent: var(--scheme-5-accent); --scheme-foreground: var(--scheme-5-foreground); }
.scheme-6 { background: var(--scheme-6-background); color: var(--scheme-6-text); --scheme-background: var(--scheme-6-background); --scheme-border: var(--scheme-6-border); --scheme-accent: var(--scheme-6-accent); --scheme-foreground: var(--scheme-6-foreground); }
.scheme-7 { background: var(--scheme-7-background); color: var(--scheme-7-text); --scheme-background: var(--scheme-7-background); --scheme-border: var(--scheme-7-border); --scheme-accent: var(--scheme-7-accent); --scheme-foreground: var(--scheme-7-foreground); }
.scheme-8 { background: var(--scheme-8-background); color: var(--scheme-8-text); --scheme-background: var(--scheme-8-background); --scheme-border: var(--scheme-8-border); --scheme-accent: var(--scheme-8-accent); --scheme-foreground: var(--scheme-8-foreground); }

/* =============================================================
   8. CONTAINER

   Figma: FRAME "Container" · VERTICAL · width FILL · height HUG
          · maxWidth bound to Container/container-large (1280)

   Figma says "fill the parent but stop at 1280 and centre" via
   FILL + maxWidth, with the parent's align-items doing the
   centring. CSS needs width/max-width/auto-margin; the auto margin
   is more robust because it survives the parent changing axis.
   ============================================================= */
.container {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-section);
  width: 100%;
  max-width: var(--container-large);
  margin-inline: auto;
}
.container--medium { max-width: var(--container-medium); }
.container--small  { max-width: var(--container-small); }
.container--center { align-items: center; }
/* Header / 70 / Content is 1312 — full width inside the section padding,
   deliberately wider than the 1280 container beside it. */
.container--wide { max-width: none; }
.container--gap-24 { gap: var(--gap-24); }
.container--gap-40 { gap: var(--gap-40); }

/* =============================================================
   9. AUTO LAYOUT PRIMITIVES

   Figma reuses four frame names everywhere — Content, Column,
   Row, Actions. Direct flexbox equivalents.
   ============================================================= */
.stack { display: flex; flex-direction: column; align-items: flex-start; gap: var(--gap-16); }
.stack--24 { gap: var(--gap-24); }
.stack--32 { gap: var(--gap-32); }
.stack--40 { gap: var(--gap-40); }
.stack--64 { gap: var(--gap-64); }
.stack--80 { gap: var(--gap-80); }
.stack--center { align-items: center; text-align: center; width: 100%; }
/* Figma "Header / 26 /" Column: FILL but capped at 1024 inside a
   1280 Container — a hero column narrower than its container. */
.measure-xlarge { width: 100%; max-width: var(--max-width-xlarge); }

.row { display: flex; flex-direction: row; align-items: center; gap: var(--gap-16); }
.row--top     { align-items: flex-start; }
.row--between { justify-content: space-between; }
.row--end     { justify-content: flex-end; }
.row--center  { justify-content: center; }
.row--wrap    { flex-wrap: wrap; }
.row--24 { gap: var(--gap-24); }
.row--32 { gap: var(--gap-32); }
.row--80 { gap: var(--gap-80); }

/* FILL on the primary axis => flex:1 1 0 AND min-width:0.
   Without min-width a flex child refuses to shrink below its
   content's intrinsic width, so long headings blow out the row.
   Figma's own export emits min-w-px for exactly this reason. */
.fill { flex: 1 1 0; min-width: 0; }
.hug  { flex: 0 0 auto; width: auto; }
.stretch { align-self: stretch; }

/* Repeating equal children. Figma has no grid track concept, so it
   models these as horizontal frames with N equal-FILL children.
   Grid states the intent better and wraps, which a fixed 1440
   artboard cannot express. */
.grid { display: grid; gap: var(--gap-32); width: 100%; }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* The UA default [hidden] { display: none } already applies to grid
   items, but .footer__socials needed an explicit rule once a component
   style set display on its li, so state it here too rather than rely on
   nobody adding one later. */
.grid > li[hidden] { display: none; }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* =============================================================
   10. TYPOGRAPHY UTILITIES
   Mapped from the Figma text styles.
   ============================================================= */
.t-large        { font-size: var(--text-sizes-text-large); }
.t-medium       { font-size: var(--text-sizes-text-medium); }
.t-small        { font-size: var(--text-sizes-text-small); }
.t-tiny         { font-size: var(--text-sizes-text-tiny); }
.t-semibold     { font-weight: var(--font-weight-semibold); }
.t-bold         { font-weight: var(--font-weight-bold); }
.t-extrabold    { font-weight: var(--font-weight-extrabold); }
.t-muted        { opacity: 0.75; }

/* Eyebrow above the H1 — Figma "Text/Large/Extra Bold", 20px/800.
   letterSpacing is 0 and textCase is ORIGINAL, so the capitals come
   from the copy itself; do NOT add tracking or text-transform.
   Colour is Color Scheme 3/Background (the teal), not inherited. */
.eyebrow {
  font-size: var(--text-sizes-text-large);
  font-weight: var(--font-weight-extrabold);
  letter-spacing: 0;
  /* Figma binds Scheme 3/Background here, which fails on every scheme
     it lands on — 1.00:1 on a teal section, where it IS the background.
     The Accent role is what this wants: white on dark schemes, navy on
     light ones, and it passes everywhere. */
  color: var(--scheme-accent, var(--color-dark));
}

/* Figma "Heading/Tagline" — Nunito Sans SemiBold 16 */
.tagline { font-weight: var(--font-weight-semibold); }

/* Small label above a figure — Figma "Text/Regular/Extra Bold",
   16px/800, each with its own accent colour rather than inherit. */
.label { font-size: var(--text-sizes-text-regular); font-weight: var(--font-weight-extrabold); }
/* Economics card eyebrows. Renamed from --bill/--pay when the copy
   changed: the left figure is what CMS reimburses, not what a provider
   bills, and "you pay" read as an accusation. */
.label--reimbursement { color: var(--scheme-3-foreground); }   /* Color/Default Dark */
.label--cost          { color: var(--color-white); }           /* was Scheme 2/Foreground #b2c7cc — 2.37:1 on the teal card */
.label--origin { color: var(--color-default-darker); } /* "Manufactured in the USA" */

.section-heading { display: flex; flex-direction: column; align-items: flex-start; gap: var(--gap-24); max-width: var(--max-width-large); }

/* Jump-link pills — Resources hero. Not in Figma: added so a page
   with two distinct sections (Downloads, FAQ) tells you both exist
   from the top, instead of relying on scroll discovery. */
.jump-nav { display: flex; flex-wrap: wrap; gap: var(--gap-12); }
.jump-nav__link {
  display: inline-flex; align-items: center; gap: var(--gap-4);
  padding: 8px 16px 8px 12px;
  border-radius: 100px;
  border: 1px solid var(--scheme-border, var(--scheme-7-border));
  font-size: var(--text-sizes-text-small); font-weight: var(--font-weight-semibold);
  color: var(--color-neutral-darkest);
  text-decoration: none;
}
.jump-nav__link:hover { background: var(--opacity-neutral-darkest-5); }
/* -------------------------------------------------------------
   Full-width heading blocks

   Three things had to change together, and any one alone looks
   like it does nothing:

   1. max-width: none  — lifts the 768 cap from .section-heading.
   2. align-self: stretch — .section-heading is a flex item of
      .container, which sets align-items:flex-start (or center via
      .container--center). Both make a flex item shrink-to-fit on
      the cross axis, so the block sized to its longest line and
      left space either side no matter what max-width said.
   3. width: 100% — covers the case where the parent is a plain
      block rather than a flex container.

   margin-inline:auto is deliberately NOT set. With the element
   already stretched there is nothing left to centre, and keeping
   it only invites the impression that it is doing the centring.
   ------------------------------------------------------------- */
.section-heading--center,
.section-heading--wide,
.section-heading--full,
.section-heading--centered-full {
  align-self: stretch;
  width: 100%;
  max-width: none;
}

/* Figma "Header / 62 /" Section Title is V gap 16 holding the tagline
   and a gap-24 Content group — so the tagline sits closer to the
   heading than the heading does to its body copy. */
.section-heading--gap-16 { gap: var(--gap-16); }
.section-heading--center,
.section-heading--centered-full {
  align-items: center;
  text-align: center;
}
.section-heading--center > *,
.section-heading--wide > *,
.section-heading--full > *,
.section-heading--centered-full > * {
  align-self: stretch;
  width: 100%;
  max-width: none;
}

/* Stretching the children to 100% is right for text, but a flex ROW
   child then fills the width and falls back to justify-content:
   flex-start — which is what left-aligned the Instructions for use
   buttons. Inside a centred block, rows centre their contents. */
.section-heading--center .actions,
.section-heading--centered-full .actions,
.section-heading--center .row,
.section-heading--centered-full .row {
  justify-content: center;
}

/* -------------------------------------------------------------
   Text/Center

   Several Section Titles override the base token: centred, and
   with the 768px max-width removed. One class does both so the
   override stops being invisible in the markup.
   ------------------------------------------------------------- */
.t-center { text-align: center; }
/* Some Section Titles carry Heading/H3 on what is semantically an
   H2. Keep the document outline correct, borrow the smaller size. */
.h-as-h3 { font-size: var(--text-sizes-heading-3); }

/* Heading typography on a NON-heading element. Figma sometimes styles
   a lead paragraph as a heading; borrowing the type is right, adding
   it to the document outline is not. Mirrors the h4/h5 base rules. */
.t-h4 {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-heading-4);
  line-height: var(--line-height-snug);
  letter-spacing: var(--letter-spacing-heading);
}
.t-h5 {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-heading-5);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
}
/* Alias of .section-heading--center, kept because the markup uses it
   to signal "this is a deliberate override of the base token". */

/* =============================================================
   11. ICONS

   <span class="icon" data-icon="name"> — the span owns the box,
   the injected svg fills it. Colour comes from currentColor so an
   icon inherits its section's scheme. Never hardcode a fill.
   ============================================================= */
.icon {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; width: 24px; height: 24px; color: inherit; line-height: 0;
}
.icon svg { display: block; width: 100%; height: 100%; }
.icon--16 { width: 16px; height: 16px; }
.icon--32 { width: 32px; height: 32px; }
.icon--48 { width: 48px; height: 48px; }
.icon--64 { width: 64px; height: 64px; }
.icon--80 { width: 80px; height: 80px; }
.icon--todo { opacity: 0.65; }
.icon--missing { outline: 1px dashed currentColor; opacity: 0.5; }

/* Image placeholders — labelled boxes holding the right aspect
   ratio, so layout is final before the art lands. */
.img-placeholder {
  display: flex; align-items: center; justify-content: center; text-align: center;
  width: 100%;
  aspect-ratio: var(--placeholder-ratio, 3 / 2);
  border: var(--stroke-divider-width) dashed var(--scheme-border, var(--scheme-7-border));
  border-radius: var(--radius-medium);
  background: var(--scheme-2-background); color: var(--scheme-2-text);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--text-sizes-text-tiny);
  opacity: 0.75; padding: var(--gap-16);
}
.img-placeholder--logo   { aspect-ratio: auto; width: 150px; height: 32px; border-radius: 4px; padding: 0; flex: 0 0 auto; }
.img-placeholder--avatar { aspect-ratio: 1; width: 48px; height: 48px; border-radius: 50%; padding: 0; flex: 0 0 auto; }
.img-placeholder--badge  { aspect-ratio: 1; width: 96px; height: 96px; border-radius: 50%; padding: 0; flex: 0 0 auto; }


/* -------------------------------------------------------------
   Real-image helpers.

   Swapping a placeholder for a photo should be a one-line change:
   keep the same box, change the tag. Each .media-* mirrors the
   radius and fit of the corresponding Figma rectangle.
   ------------------------------------------------------------- */
.media { display: block; width: 100%; height: auto; object-fit: cover; border-radius: var(--radius-large); }
.media--square { aspect-ratio: 1; }
/* Figma draws the logo in a 150x32 box, but the supplied SVGs are
   4.92:1 and 4.63:1 — neither is 4.6875:1. Lock the height to 32
   and let width follow, so the mark is never squashed. */
.media--logo   { height: 32px; width: auto; max-width: none; object-fit: contain; border-radius: 0; flex: 0 0 auto; }
.media--avatar { width: 48px; height: 48px; border-radius: 50%; flex: 0 0 auto; }
/* .media--badge is defined in section 14 (HERO) — the artwork carries
   its own corners and shadow, so no CSS radius and no cover-crop. */
.media--flat   { border-radius: 0; }

/* Aspect-ratio boxes for images whose new resolution arrived at a
   DIFFERENT ratio from the Figma frame. Rather than re-cropping the
   files (destructive, and wrong if the art is revised again), the
   box keeps Figma's proportion and object-fit:cover crops to fill.
   The full image is preserved on disk; only the view is cropped.

     .media--r-1x1      Badge 1        216x216 box, art now 1.37:1
     .media--r-4x3      device in context 1 & 2, current soc 2
     .media--r-3x2      device in context 3, device transparent bg
     .media--r-5x4      device packaging
     .media--r-compare  comparison heads, 3:2
     .media--r-graphic  fluid loss graphic, 1801x1081             */
.media--r-1x1     { aspect-ratio: 1 / 1; }
.media--r-4x3     { aspect-ratio: 4 / 3; }
.media--r-3x2     { aspect-ratio: 3 / 2; }
.media--r-5x4     { aspect-ratio: 5 / 4; }
/* Both comparison heads are supplied at exactly 3:2, so the frame
   matches the source and the two images render at identical width and
   height with nothing cropped. `contain` is kept rather than `cover`
   so a future asset that is slightly off-ratio letterboxes instead of
   losing its edges — these are line drawings on white, so the margin
   would be invisible. */
.media--r-compare { aspect-ratio: 3 / 2; object-fit: contain; }
/* The chart carries its own title, axis labels and source line, so
   nothing may be cropped. The supplied art is 1801x1081 (1.666:1),
   not the 1.733:1 of the Figma frame, so the box takes the ratio of
   the artwork itself and `contain` guards a future re-export. */
.media--r-graphic { aspect-ratio: 1801 / 1081; object-fit: contain; }

/* =============================================================
   12. BUTTON

   Figma: INSTANCE "Button" · HORIZONTAL · centre/centre
          · padding 8 20 · radius 12 · 1px transparent border
          · fill = linear-gradient(121.15deg, Color/Dark -> Color/Regent St Blue)
   ============================================================= */
/* The Figma Button component has four variant axes:
     Style     = Primary | Secondary | Link
     Small     = True (p 8/20) | False (p 10/24)
     Alternate = True (for dark sections) | False
     Icon position = No icon | Trailing

   Resolved from the instances actually placed on the Design page,
   not from the base component — the frames override it:

     Primary            gradient 121.15deg Dark -> Regent St Blue,
                        text White, 1px transparent border
     Secondary          fill Opacity/Neutral Darkest 5 (5% #030708),
                        text Neutral Darkest, 1px transparent border
     Secondary + Alt    fill Opacity/White 10, text White, NO border
     Primary   + Alt    solid Color/White, text Neutral Darkest
     Link               no fill, no border, no padding, trailing icon
   All variants: radius 12. */
.button {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--gap-8);
  padding: 10px 24px;                       /* Small = False */
  border: 1px solid var(--opacity-transparent);
  border-radius: 12px;
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sizes-text-regular);
  line-height: var(--line-height-body);
  text-decoration: none; white-space: nowrap; cursor: pointer;
  background-origin: border-box;
  background-repeat: no-repeat;
  transition: background-color 0.15s ease, opacity 0.15s ease, transform 0.15s ease;
}
.button:active { transform: translateY(1px); }

.button--sm { padding: 8px 20px; }
/* Figma mobile navbar Button: pad 4/20, Text/Regular/Medium 14px, r12. */
.button--xs { padding: 4px 20px; font-size: var(--text-sizes-text-small); }          /* Small = True */

.button--primary {
  color: var(--color-white);
  /* Figma ends this ramp on Color/Regent St Blue, where white text is
     1.65:1 — so the bottom-right of every primary CTA failed badly.
     Ending on Color/Default keeps a visible navy-to-teal gradient and
     holds 4.90:1 at the palest point, using tokens already in the set. */
  background-image: linear-gradient(121.15deg, var(--color-dark) 0%, var(--color-default) 100%);
}
.button--secondary {
  background-color: var(--opacity-neutral-darkest-5);
  color: var(--color-neutral-darkest);
}
.button--primary:hover { opacity: 0.9; }
.button--secondary:hover { background-color: var(--opacity-neutral-darkest-10); }

/* Alternate = True — the variants used on dark sections. */
.button--primary-alt {
  background-color: var(--color-white);
  color: var(--color-neutral-darkest);
}
.button--secondary-alt {
  /* Opacity/White 10 over a teal section lands at 4.07:1 for white
     text. The Foreground role is darker and scheme-aware: 14.27:1 on
     scheme 1, 7.11:1 on scheme 3. */
  background-color: var(--scheme-foreground, var(--opacity-white-10));
  color: var(--color-white);
  border-color: transparent;
}
.button--primary-alt:hover   { background-color: var(--color-neutral-lightest); }
.button--secondary-alt:hover { background-color: var(--opacity-white-20); }

/* Link: Text/Regular/Normal, no underline in Figma — the affordance
   is the trailing chevron, not a rule. */
.button--link {
  background: none; border-color: transparent; padding: 0;
  font-weight: var(--font-weight-regular);
  color: var(--color-neutral-darkest);
  text-decoration: none;
}
.button--link-alt { color: var(--color-white); }

/* Tertiary — no fill, no stroke, but PADDED like a real button
   (10/24, or 8/20 when Small). That padding is what separates it
   from Link, which is padding-zero. Trailing-icon gap is 12. */
.button--tertiary {
  background: none; border-color: transparent;
  color: var(--color-neutral-darkest);
  font-weight: var(--font-weight-regular);
}
.button--tertiary:hover { background-color: var(--opacity-neutral-darkest-5); }
.button--tertiary.has-icon { gap: var(--gap-12); }
/* Card CTAs. The icon here is a hint about what the link does, not a
   second focal point, so it drops to 16px — the same size as the small
   type it sits beside. The 12px gap above and the 20px side padding
   were tuned for a 24px icon and left the mark floating away from its
   label; 4px and 14px bind the two into one unit. Placed after the
   rule above so it wins on source order at equal specificity. */
.button--sm.has-icon { padding: 8px 14px; gap: var(--gap-4); }
.button--sm.has-icon .icon { width: 16px; height: 16px; }
.button--link:hover { text-decoration: underline; text-underline-offset: 3px; }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-16); }
/* Paired CTAs inside a card, where the 16px row gap is too loose. */
.actions--sm { gap: var(--gap-8); }

/* =============================================================
   13. NAVBAR

   Figma: COMPONENT "Navbar / 2 /" · h72 FIXED · px padding-global
          > Container · HORIZONTAL · gap 32
            > Content (FILL)  logo
            > Column  (HUG)   links
            > Actions (FILL, end) CTA

   Two FILL siblings flanking a HUG centre column is the optically
   centred nav trick; it survives translation unchanged.
   ============================================================= */
.navbar {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 72px; padding-inline: var(--padding-global);
  background: var(--scheme-7-background); color: var(--scheme-7-text);
  position: fixed; top: 0; left: 0; width: 100%; z-index: 1000;
  transition: transform 0.3s ease-in-out;
}
/* Hide/show on scroll (app.js toggles this). transform only — never
   top/margin — so sliding the bar is compositor-only and never forces
   a layout reflow on every scroll tick. */
.navbar--hidden { transform: translateY(-100%); }
/* Container is 1312 in Figma — the full 1440 artboard minus 2x
   padding-global — and carries NO maxWidth binding. It is the one
   container on the site that is not capped at 1280, so the logo
   sits hard against the page padding. */
.navbar__container {
  display: flex; align-items: center; gap: var(--gap-32);
  width: 100%; max-width: none; margin-inline: 0;
}

/* Figma widths: Content 842 (FILL) · Column 289 (HUG) · Actions 117 (HUG).
   Only the logo column grows. Actions is HUG, so the CTA sits at its
   natural width and the links are pushed right — this is NOT the
   optically-centred nav it used to be. */
.navbar__brand   { display: flex; flex: 1 1 0; min-width: 0; align-items: center; }
.navbar__links   { display: flex; flex: 0 0 auto; align-items: center; gap: var(--gap-32); }
.navbar__actions { display: flex; flex: 0 0 auto; align-items: center; justify-content: flex-end; gap: var(--gap-16); }
.navbar__logo    { width: 150px; height: 32px; object-fit: contain; }

.nav-item { position: relative; display: flex; flex-direction: column; gap: var(--gap-8); }
.nav-link {
  display: flex; align-items: center; justify-content: center; gap: var(--gap-4);
  padding: 0; border: 0; background: none; white-space: nowrap;
  cursor: pointer; text-decoration: none;
}
.nav-link__chevron { transition: transform 0.2s ease; }
.nav-item[data-open="true"] .nav-link__chevron { transform: rotate(180deg); }

/* Figma "Menu" · VERTICAL · gap 16 · padding 24 · radius 24 */
.nav-menu {
  position: absolute; top: calc(100% + var(--gap-8)); left: 0;
  display: none; flex-direction: column; align-items: flex-start;
  gap: var(--gap-16); min-width: 198px; padding: var(--gap-24);
  border-radius: var(--radius-small);
  background: var(--scheme-5-background); color: var(--scheme-5-text);
  box-shadow: var(--shadow-menu);
}
.nav-item[data-open="true"] .nav-menu { display: flex; }
.nav-menu a { text-decoration: none; white-space: nowrap; }
.nav-menu a:hover { text-decoration: underline; }

/* Mobile disclosure — hidden on desktop, shown under 992px. */
.nav-toggle {
  display: none; align-items: center; justify-content: center;
  width: 48px; height: 48px; padding: 0;   /* Figma "Icon" frame */
  border: 0; border-radius: 12px;
  background: none; cursor: pointer;
}
.nav-toggle .icon { width: 24px; height: 24px; }
.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; }

/* =============================================================
   14. HERO  ("Header / 129 /")

   Figma: Component · HORIZONTAL · gap 64 · counter CENTER
          > Column (FILL, V, gap 32)
          > Image container (FILL, height 480 FIXED, padding-left 164)
            · Device-white-square  480x480  radius 40
            · Badge 1             216x216  radius 32   } absolutely
            · Badge 2             244x155  radius 32   } positioned

   The image container has no layoutMode — the three rectangles are
   absolutely placed, which is why the badges overlap the device
   shot rather than sitting in a row beneath it.

   IMPORTANT: the device shot is kept IN FLOW. It is the only thing
   giving .hero__media a real content height. Making all three
   children absolute (as this block used to) left the box with zero
   content height and relied entirely on aspect-ratio — and the
   moment .hero__grid switched to a column at <=991px, `flex: 1 1 0`
   started resolving flex-basis against the HEIGHT instead of the
   width, so the box collapsed to 0 and both images spilled over the
   section below. Only the badges are taken out of flow now.
   ============================================================= */
.hero__grid { display: flex; align-items: center; gap: var(--gap-64); width: 100%; }

.hero__media {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  overflow: visible;        /* badge shadows bleed past the box by design */
}

.hero__device {
  display: block;
  width: 78.947%;           /* 480 / 608 */
  margin-left: 10.526%;     /*  64 / 608 */
  aspect-ratio: 1;
  border-radius: var(--radius-large);
}
/* The badge PNGs bake their drop shadow into ~60px of transparent
   padding. object-fit:cover (from .media) plus a forced ratio sliced
   that padding off, which read as a clipped shadow. So: contain, no
   ratio class, no CSS radius (the artwork carries its own corners).
   Widths are grossed up and offsets pulled back by the padding
   fraction so the *visible* badge still lands on its Figma box. */
.media--badge { object-fit: contain; border-radius: 0; }
.hero__badge { position: absolute; margin: 0; height: auto; }
/* 432x315, opaque 63,63 -> 369,252.  Figma box 216x216 @ (0, 240) */
.hero__badge--1 { left: -7.32%;  top: 40.7%;  width: 50.2%; }
/* 488x310, opaque 48,48 -> 440,262.  Figma box 244x155 @ (364, 24) */
.hero__badge--2 { right: -4.92%; top: -1.22%; width: 50%; }

/* =============================================================
   15. STATS  ("Stats / 8 /")

   Figma: Content (V, gap 64) > Row (H, gap 48) > 3x Stat
          Stat · V · gap 8 · padding-left 32 · has stroke
   The stroke is a LEFT rule on each stat, not a full border.
   ============================================================= */
.stats-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap-48); width: 100%; }

.stat {
  display: flex; flex-direction: column; gap: var(--gap-8);
  padding-left: var(--gap-32);
  border-left: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-7-border));
}
.stat__value {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-stat);
  line-height: 1.3;
  letter-spacing: var(--letter-spacing-heading);
}
.stat__label { font-size: var(--text-sizes-heading-6); font-family: var(--font-family-heading); line-height: var(--line-height-heading); }

/* =============================================================
   16. COMPARISON TABLE  ("Comparison / 5 /")

   Figma models this as nested Row / Table cell frames. It is a
   real data table — feature rows compared across two columns — so
   it becomes <table> with proper <th scope>. Screen readers then
   announce "Draw rate, OcuTap, 40 µL/second" instead of reading
   three unrelated divs.
   ============================================================= */
/* Figma: Row · H · gap 0 · three Table cells
     col 1  440 FIXED  · label   · p 16/24/16/0 · start
     col 2  420 FILL   · OcuTap  · p 16/24      · centre · fill Foreground
     col 3  420 FILL   · current · p 16/24      · centre
   Header row cells are p24 and the label cell aligns end/start.
   The OcuTap column carries the scheme's Foreground fill for its
   whole height — that highlight is the point of the layout. */
.comparison { width: 100%; border-collapse: collapse; table-layout: fixed; }
.comparison col.comparison__col-label { width: 440px; }

.comparison th, .comparison td {
  padding: var(--gap-16) var(--gap-24);
  border-bottom: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-7-border));
  vertical-align: middle;
  text-align: center;
}
/* Label column: left aligned, no left padding, regular weight. */
.comparison tbody th, .comparison thead th:first-child {
  text-align: left;
  padding-left: 0;
  font-weight: var(--font-weight-regular);
}
.comparison thead th { padding: var(--gap-24); vertical-align: bottom; }
.comparison thead th:first-child { vertical-align: bottom; padding-left: 0; }
.comparison td { font-weight: var(--font-weight-semibold); }

/* The highlighted OcuTap column. */
.comparison thead th.is-highlight,
.comparison td.is-highlight { background: var(--scheme-foreground, transparent); }

.comparison__head { display: flex; flex-direction: column; align-items: center; gap: var(--gap-8); }
.comparison__head .img-placeholder { --placeholder-ratio: 16/7; }
.comparison__name { font-size: var(--text-sizes-text-large); font-weight: var(--font-weight-bold); }
.comparison .icon { margin-inline: auto; }

/* =============================================================
   17. TESTIMONIALS  ("Header / 70 /")
   ============================================================= */
/* Figma: Column · V · gap 24 · padding 32 · radius 32
          · fill Color Scheme 3/Foreground · stroke
   Each testimonial is a CARD, not bare text on the section fill. */
.testimonial {
  display: flex; flex-direction: column; gap: var(--gap-24);
  height: 100%;
  padding: var(--gap-32);
  /* Figma defines a stroke here but at strokeWeight 0 — it paints
     nothing. No border. */
  border-radius: var(--radius-medium);
  background: var(--scheme-foreground, transparent);
}
.testimonial__person { display: flex; align-items: center; gap: var(--gap-16); }
.testimonial__person > div { display: flex; flex-direction: column; gap: 0; }
.testimonial__name { font-family: var(--font-family-heading); font-size: var(--text-sizes-heading-6); line-height: var(--line-height-heading); }
.testimonial__role { font-weight: var(--font-weight-bold); font-size: var(--text-sizes-text-regular); }
/* Accent-coloured in Figma, and the accent tracks the surface:
   Regent St Blue Light on the teal header, Default on the white one. */
.scheme-3 .testimonial__role { color: var(--color-regent-st-blue-lightest); }   /* Light was 3.45:1 */
.scheme-5 .testimonial__role { color: var(--color-default-dark); }   /* Default was 4.38:1 on the #f2f2f2 card */
.testimonial__quote { font-size: var(--text-sizes-text-large); font-weight: var(--font-weight-bold); }
.stars { display: flex; gap: var(--gap-4); }

/* =============================================================
   18. CARDS

   Figma: Card · radius 32 · fill Color Scheme N/Foreground · stroke
          inner Content · padding 24 · gap 24

   The surface token is the scheme's FOREGROUND, not a fixed
   colour. Foreground is the elevated-surface role in this system:
   on scheme 7 it resolves to white over the light-grey background;
   on scheme 3 to a darker teal over teal. Hardcoding a scheme here
   breaks every section that isn't that scheme.
   ============================================================= */
.card {
  display: flex; flex-direction: column; gap: var(--gap-24);
  padding: var(--gap-24);
  /* Figma defines a stroke here but at strokeWeight 0 — it paints
     nothing. No border. */
  border-radius: var(--radius-medium);
  background: var(--scheme-foreground, transparent);
  height: 100%;
}
.card--flush { padding: 0; overflow: hidden; }
.card--flush > .card__body { padding: var(--gap-24); }
.card__body { display: flex; flex-direction: column; gap: var(--gap-24); height: 100%; }
.card__meta { display: flex; align-items: center; gap: var(--gap-16); }
/* Figma applies Heading/H5 to every card title on this page. */
.card__title {
  font-family: var(--font-family-heading);
  font-size: var(--text-sizes-heading-5);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
}
/* Bulleted body copy inside a card, e.g. the "How it works" steps. */
.card__list { display: flex; flex-direction: column; gap: var(--gap-12); }
.card__list li { position: relative; padding-left: 20px; }
.card__list li::before {
  content: "";
  position: absolute; left: 2px; top: 0.65em;
  width: 5px; height: 5px; border-radius: 50%;
  background: currentColor;
}

/* "Layout / 519 /" economics cards — padding 48, radius 40, and each
   card takes a different SCHEME background rather than Foreground. */
.card--feature { padding: var(--gap-48); border-radius: var(--radius-large); gap: var(--gap-32); border: 0; }
/* "Card" nodes in Layout/519 bind their own scheme rather than
   inheriting the section's, so the markup carries .scheme-5 /
   .scheme-3 directly and body copy inherits the right colour.
   Card A: bg Scheme 5/Background · Card B: bg Scheme 3/Background */

/* Pill tag. Radius 100px and a Color/Neutral Lightest fill, per
   direction — Figma draws these at r6 with an Opacity/Neutral
   Darkest 5 fill, so this is a deliberate departure from the file.
   Padding stays at Figma's 4/10. */
.tag {
  display: inline-flex; align-items: center;
  padding: 4px 10px;
  border-radius: 100px;
  /* Background role of the surrounding section, not a fixed colour.
     On a scheme-7 section that resolves to #f2f2f2 (Neutral Lightest)
     against a white card; on scheme 5 it resolves to #ffffff against
     the grey card, where a fixed Neutral Lightest was invisible
     because Scheme 5/Foreground IS Neutral Lightest. */
  background: var(--scheme-background, var(--color-neutral-lightest));
  color: var(--color-neutral-darkest);
  border: 1px solid var(--opacity-transparent);   /* Figma: transparent stroke */
  font-size: var(--text-sizes-text-small); font-weight: var(--font-weight-semibold);
}

.price {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-stat);
  line-height: 1.2;
  letter-spacing: var(--letter-spacing-heading);
}

/* Checklist — "List Item" H · gap 16 · icon + text */
/* Figma "Tagline Wrapper" — H · gap 6 · padding 8/16 · HUG ·
   fill Color/White, which on a scheme-7 section is the Foreground
   role. Pill radius. */
.tagline-pill {
  display: inline-flex; align-items: center; gap: var(--gap-6);
  align-self: flex-start;
  padding: 8px 16px;
  border-radius: 999px;
  background: var(--scheme-foreground, var(--scheme-7-foreground));
  color: var(--color-default-darker);
  font-size: var(--text-sizes-text-regular);
  font-weight: var(--font-weight-extrabold);
}
.tagline-pill .icon { width: 24px; height: 24px; flex: 0 0 auto; }

.checklist { display: flex; flex-direction: column; gap: var(--gap-16); }
.checklist li { display: flex; align-items: flex-start; gap: var(--gap-16); }

/* =============================================================
   19. FAQ  ("FAQ / 5 /", "FAQ / 2 /")

   Figma models accordions as stacked frames with a +/- icon.
   Open and closed are prototype states, not layout, so <details>
   gives the same structure plus the behaviour, keyboard support
   and screen-reader semantics with no JavaScript.
   ============================================================= */
/* Figma: Accordion List · V · gap 16
          Accordion · radius 24 · fill Foreground · stroke
            Question · H · gap 24 · padding 20/24
            Answer   · H · gap 16 · padding 0/72/24/24
   Each item is a rounded card, not a hairline-separated row. */
.faq { display: flex; flex-direction: column; gap: var(--gap-16); width: 100%; }

.faq__item {
  /* Figma defines a stroke here but at strokeWeight 0 — it paints
     nothing. No border. */
  border-radius: var(--radius-small);
  background: var(--scheme-foreground, transparent);
}
.faq__item > summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--gap-24);
  padding: 20px var(--gap-24);
  font-size: var(--text-sizes-text-medium); font-weight: var(--font-weight-bold);
  cursor: pointer; list-style: none;
}
.faq__item > summary::-webkit-details-marker { display: none; }
.faq__item > summary .icon { transition: transform 0.2s ease; }
.faq__item[open] > summary .icon { transform: rotate(45deg); }

/* Resources FAQ: a plain (non-heading) span inside <summary> — styled
   only by the .faq__item > summary rule above (Text/Medium/Bold), the
   same look this had before the ToC existed. It carries an id purely
   so the ToC (and its scrollspy) can target/label it, and a `title`
   attribute for the native hover/focus tooltip once truncated to a
   single line below. */
.faq__question {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.faq__answer { padding: 0 72px var(--gap-24) var(--gap-24); }
.faq__answer p + p { margin-top: var(--gap-16); }

/* References strip — Figma "FAQ / 2 /" › Accordion Item.
   No card treatment. The 32px chevron LEADS the label rather than
   sitting at the far right, and the answer is two columns, not a
   single stacked list. */
.faq__item--refs,
.faq__item--transcript { border: 0; background: none; border-radius: 0; width: 100%; }
.faq__item--refs > summary,
.faq__item--transcript > summary {
  justify-content: flex-start;
  gap: var(--gap-24);
  padding: 20px 0;
}
.faq__item--refs > summary .icon,
.faq__item--transcript > summary .icon { width: 32px; height: 32px; transform: rotate(180deg); }
.faq__item--refs[open] > summary .icon,
.faq__item--transcript[open] > summary .icon { transform: rotate(0deg); }
.faq__item--refs .faq__answer,
.faq__item--transcript .faq__answer {
  display: block;
  width: 100%;
  padding: 0 0 var(--gap-24) 0;
}
.faq__item--refs .faq__answer p + p { margin-top: 0; }

/* Transcript-specific: 12px above and below the whole block, and the
   answer is prose rather than a two-column list, so paragraphs need
   their normal rhythm back. */
.faq__item--transcript { padding-block: var(--gap-12); }
.faq__item--transcript .faq__answer { max-width: none; }
.faq__item--transcript .faq__answer p { margin-bottom: var(--gap-16); }
.faq__item--transcript .faq__answer p:last-child { margin-bottom: 0; }

/* Figma "FAQ / 2 /" Answer is H gap16 with two text blocks. A single
   <ol> in two CSS columns keeps one continuous 1..n sequence and
   still reads in document order for a screen reader. */
.refs-list {
  /* The reset sets `ul, ol { list-style: none }`, which was silently
     removing the numbers. Restore the marker explicitly, and keep it
     inside the column box so it cannot be clipped at a column break. */
  list-style: decimal;
  list-style-position: outside;

  /* The list itself is the multi-column context, so it spans the full
     container and the numbering runs 1..n down column one before
     continuing at the top of column two. column-fill: balance is the
     default but is stated here because the even distribution is the
     point, not a side effect. */
  column-count: 2;
  column-gap: var(--gap-16);
  column-fill: balance;

  width: 100%;
  margin: 0; padding-left: 1.5em;
  font-size: var(--text-sizes-text-regular);
}
.refs-list::marker, .refs-list li::marker { font-variant-numeric: tabular-nums; }
.refs-list li { break-inside: avoid; margin-bottom: var(--gap-16); }
.refs-list li:last-child { margin-bottom: 0; }

/* Each entry names the claim first, then the source. The claim is the
   part a reader scans for; the citation is the part they verify. */
.ref__claim {
  display: block;
  font-weight: var(--font-weight-bold);
  margin-bottom: var(--gap-4);
}
.ref__cite { display: block; opacity: 0.85; }
.ref__cite + .ref__cite { margin-top: var(--gap-4); }
.refs-list em { font-style: italic; }
.refs-list a { text-decoration: underline; }

/* Figma "Layout / 519 /" Frame 1 · V · gap 24 · cnt CENTER, holding
   the card Row and the dagger note. The note is maxWidth 560,
   Text/Small/Medium, centred. */
.econ-group { display: flex; flex-direction: column; align-items: center; gap: var(--gap-24); width: 100%; }
.econ-note  { max-width: var(--max-width-medium); text-align: center; font-size: var(--text-sizes-text-small); font-weight: var(--font-weight-medium); }

/* Card A takes the Foreground ROLE, resolved against whatever scheme
   the surrounding section declares — not a fixed colour. Home runs
   this section on scheme 7, so it lands on #ffffff; OcuTap runs it on
   scheme 5, so the same class lands on #f2f2f2. Every .scheme-N class
   already publishes --scheme-foreground, so no page-specific variant
   is needed and the pairing cannot drift if a section changes scheme.
   Text colour is inherited from the section for the same reason. */
.card--foreground { background: var(--scheme-foreground, var(--scheme-7-foreground)); }

/* Figma: Content · H · gap 24 · maxWidth max-width-medium (560) */
.faq__followup { display: flex; align-items: center; gap: var(--gap-24); width: 100%; max-width: var(--max-width-medium); }

/* =============================================================
   20. CTA FORM  ("CTA / 41 /")
   ============================================================= */
/* Figma: Card · H · padding 64 · radius 40 · fill IMAGE · stroke
          > Column · maxWidth max-width-medium (560) · gap 32
   The card background is a photograph, not a flat colour. Until it
   is supplied, a scheme fill stands in — see the ASSET comment in
   index.html. Keep a dark overlay under the text when the real
   image lands, or the copy will not hold contrast. */
.cta-card {
  display: flex; align-items: center; width: 100%;
  padding: var(--gap-64);
  border: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-1-border));
  border-radius: var(--radius-large);
  background: var(--scheme-foreground, var(--scheme-1-foreground));
  background-size: cover; background-position: center;
  color: var(--scheme-1-text);
}
.cta-card > * { max-width: var(--max-width-medium); }
.signup { display: flex; gap: var(--gap-16); width: 100%; }
.signup input[type="email"] {
  flex: 1 1 0; min-width: 0;
  padding: 10px var(--gap-16);
  /* Same Text input component as the contact form. */
  border: 1px solid var(--opacity-transparent);
  border-radius: 12px;
  background: var(--opacity-white-10); color: var(--color-white);
  font: inherit;
}
.signup input[type="email"]::placeholder { color: var(--opacity-white-60); }
.form-note { font-size: var(--text-sizes-text-small); opacity: 0.8; }
/* The investigational notice that sits beside a primary CTA. Required
   text, not supporting text, so it never takes the 0.8 opacity the terms
   note carries — on the CTA card it sits over a photograph, where full
   white holds 6.37:1 against the brightest part of card-1.png and 0.8
   would drop it toward the 4.5:1 floor. Colour comes from the scheme, so
   it reads correctly on navy, teal and white alike. */
.reg-note {
  display: flex; align-items: flex-start; gap: var(--gap-8);
  margin: 0; opacity: 1;
  font-size: var(--text-sizes-text-small);
  max-width: var(--max-width-medium);
}
.reg-note .icon { flex: 0 0 auto; margin-top: 1px; }
.form-note--reg { opacity: 1; display: flex; align-items: flex-start; gap: var(--gap-8); }
.form-note--reg .icon { flex: 0 0 auto; margin-top: 1px; }

/* =============================================================
   21. FOOTER  ("Footer / 3 /")
   ============================================================= */
.footer {
  display: flex; flex-direction: column; align-items: center; gap: var(--gap-section);
  padding: var(--padding-section-medium) var(--padding-global);
  background: var(--scheme-1-background); color: var(--scheme-1-text);
  --scheme-border: var(--scheme-1-border);
}
.footer__container { display: flex; flex-direction: column; gap: var(--gap-section); width: 100%; max-width: var(--container-large); margin-inline: auto; }
.footer__content { display: flex; align-items: flex-start; gap: var(--gap-64); }
.footer__brand   { display: flex; flex-direction: column; align-items: flex-start; flex: 1 1 0; min-width: 0; gap: var(--gap-32); }
.footer__nav     { display: flex; flex: 0 0 400px; gap: var(--gap-24); }
.footer__contact { display: flex; flex-direction: column; gap: var(--gap-16); padding-block: var(--gap-8); }
.footer__contact-row { display: flex; align-items: flex-start; gap: var(--gap-16); }
.footer__socials { display: flex; gap: var(--gap-12); }
.footer__socials a { display: block; }
/* Facebook / Instagram / X / YouTube are parked, not removed — the
   markup stays and each row carries `hidden`. This rule is needed
   because [hidden]'s UA display:none loses to any explicit display
   set on the same element. Delete the attribute to bring one back. */
.footer__socials li[hidden] { display: none; }

/* Link List frames use gap 0 and push spacing into each link's own
   8px block padding — keep that, it makes the whole 37px row
   clickable rather than just the 21px of text. */
.footer__list { display: flex; flex-direction: column; flex: 1 1 0; min-width: 0; gap: 0; }
.footer__list a { display: block; padding-block: var(--gap-8); text-decoration: none; font-size: var(--text-sizes-text-small); }
.footer__list a:hover { text-decoration: underline; }
/* Press kit leaves the site — Figma labels it "(direct link to GD)". */
.footer__list a[target="_blank"] { display: flex; align-items: center; gap: var(--gap-6); }
.footer__list a[target="_blank"] .icon { flex: 0 0 auto; width: 16px; height: 16px; }

.footer__credits { display: flex; flex-direction: column; gap: var(--gap-32); }
.footer__divider { width: 100%; height: 0; margin: 0; border: 0; border-top: var(--stroke-divider-width) solid var(--scheme-1-border); }
.footer__credits-row { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--gap-64); }
/* One persistent statement of regulatory status, above the copyright
   row on every page. 21 CFR 812.5 governs the device label, not the
   website; 812.7 governs promotion. A single durable line states the
   status without interrupting the page, and covers Contact and the
   legal pages, which carried nothing before. */
.footer__reg {
  display: flex; align-items: flex-start; gap: var(--gap-8);
  margin: 0 0 var(--gap-16);
  font-size: var(--text-sizes-text-small);
  max-width: var(--max-width-large);
}
/* Desktop: let the credits copy run the full width of the footer
   container instead of wrapping to a narrow measure. */
@media (min-width: 1200px) {
  .footer__reg { max-width: none; }
}
.footer__reg .icon { flex: 0 0 auto; margin-top: 1px; }
.footer__legal { display: flex; gap: var(--gap-24); }
.footer__legal a { text-decoration: none; font-size: var(--text-sizes-text-small); }
.footer__legal a:hover { text-decoration: underline; }


/* =============================================================
   23. FORM CONTROLS

   Figma "Contact / 6 /" — every control is the Alternate=True
   variant, because the section sits on scheme 3 (dark teal):

     Text input  48h · p 8/12  · r12 · fill Opacity/White 10
     Select      40h · p 8/12  · r12 · fill Opacity/White 10
     Text Area  180h · p 12    · r12 · fill Opacity/White 10
                placeholder Opacity/White 60
     Radio      18x18 circle   · fill Opacity/White 10 · gap 12
     Checkbox   18x18 r4       · fill Opacity/White 10 · gap 8
   All carry a 1px Opacity/Transparent stroke.
   ============================================================= */
.form { display: flex; flex-direction: column; gap: var(--gap-24); width: 100%; }
.form__row { display: flex; gap: var(--gap-24); }
.form__field { display: flex; flex-direction: column; flex: 1 1 0; min-width: 0; gap: var(--gap-8); }
.form__label { font-size: var(--text-sizes-text-regular); }
/* "(optional)" sits inside the <label>, so it becomes part of the
   accessible name and is announced without extra ARIA. Only the one
   optional field is marked — labelling the seven required ones instead
   would mean seven markers to flag the single exception. Contrast is
   held at Opacity/White 60 (5.38:1 on navy), not dropped further, since
   this is real text and not decoration. */
.form__optional {
  font-size: var(--text-sizes-text-small);
  color: var(--opacity-white-60);
  font-weight: var(--font-weight-regular);
}

.field {
  width: 100%;
  padding: 8px 12px;
  /* Figma component "Text input / Type=Default, Alternate=True"
     (5014:9508): fill Opacity/White 10, 1px Opacity/Transparent
     stroke, r12, placeholder Opacity/White 60. */
  border: 1px solid var(--opacity-transparent);
  border-radius: 12px;
  background: var(--opacity-white-10);
  color: var(--color-white);
  font: inherit;
  font-size: var(--text-sizes-text-regular);
}
.field::placeholder { color: var(--opacity-white-60); }
.field:focus-visible { outline: 2px solid var(--color-white); outline-offset: 2px; }

input.field  { height: 48px; }
select.field { height: 40px; padding-block: 8px; }
textarea.field { height: 180px; padding: 12px; resize: vertical; }

/* Radio + checkbox: 18px controls, accent-coloured, with the Figma gaps. */
.choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px var(--gap-24); }
.choice { display: flex; align-items: center; gap: var(--gap-12); font-size: var(--text-sizes-text-regular); }
.choice input { width: 18px; height: 18px; margin: 0; flex: 0 0 auto; accent-color: var(--color-white); }
.consent { display: flex; align-items: center; gap: var(--gap-8); padding-bottom: var(--gap-16); font-size: var(--text-sizes-text-small); }
.consent input { width: 18px; height: 18px; margin: 0; flex: 0 0 auto; accent-color: var(--color-white); }
.fieldset { border: 0; margin: 0; padding: var(--gap-16) 0; display: flex; flex-direction: column; gap: var(--gap-16); }
.fieldset legend { padding: 0; font-size: var(--text-sizes-text-regular); }


/* =============================================================
   24. ABOUT PAGE COMPONENTS

   Figma "About • Desktop" (10215:92573).
   ============================================================= */

/* "Content / 17 /" — Content H gap 80: a fixed 468 column beside a
   732 FILL rich-text column. The eyebrow here is Regent St Blue,
   not the teal used on Home. */
.split-intro { display: flex; align-items: flex-start; gap: var(--gap-80); width: 100%; }
.split-intro__aside { flex: 0 0 468px; display: flex; flex-direction: column; gap: var(--gap-16); }
.split-intro__body  { flex: 1 1 0; min-width: 0; padding-bottom: var(--gap-16); }
.split-intro__body p + p { margin-top: 1em; }

/* "Layout / 673 /" — founder card. H · gap 0 · r40 · fill Foreground
   · stroke. Image column FILL, content column p48 · gap 32. */
.founder {
  display: flex; align-items: stretch; width: 100%;
  /* Figma defines a stroke here but at strokeWeight 0 — it paints
     nothing. No border. */
  border-radius: var(--radius-large);
  background: var(--scheme-foreground, transparent);
  overflow: hidden;
}
/* The portrait is 1080x1607 — a 0.672 source. `height: 100%` let the
   body column dictate the card height (about 640 against a 640-wide
   media column), so cover was squeezing a 2:3 photo into a 1:1 box
   and trimming a third of it, half of that off the top of the head.
   Driving the height from an aspect-ratio instead makes the photo
   set the card height rather than inherit it. 3/4 is exactly the
   640x853 rectangle Figma draws.

   object-position is biased upward because whatever crop remains
   should come off the bottom of a headshot, never the face. */
.founder__media { flex: 1 1 0; min-width: 0; }
.founder__media img {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: 50% 18%;
  border-radius: 0;
}
.founder__body {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; justify-content: center;
  gap: var(--gap-32); padding: var(--gap-48);
}

/* "Team / 4 /" — Row H gap 32, four cards. Card V gap 24; image
   296x444 r32; Content V gap 16; Title V gap 0. */
.team-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap-32); width: 100%; }
/* 5 members: 3-up first row, remaining 2 cards in row two at the same
   card size (row two simply doesn't fill the full row width). */
.team-card { display: flex; flex-direction: column; gap: var(--gap-24); height: 100%; }
.team-card__photo { width: 100%; aspect-ratio: 296 / 444; object-fit: cover; border-radius: var(--radius-medium); }
.team-card__body { display: flex; flex-direction: column; gap: var(--gap-16); }
.team-card__title { display: flex; flex-direction: column; gap: 0; }
.team-card__name { font-size: var(--text-sizes-text-large); font-weight: var(--font-weight-semibold); }
.team-card__role { font-size: var(--text-sizes-text-medium); }

/* Social Icons rows use gap 14 — not a token, Figma's own number. */
.social-row { display: flex; gap: 14px; }
.social-row a { display: block; }


/* =============================================================
   25. RESOURCES PAGE COMPONENTS

   Figma "Resources & Downloads • Desktop" (10215:91863).
   ============================================================= */

/* "Header / 62 /" — Component H · space-between · gap 32:
   a Section Title on the left, Actions on the right. Several of
   these sections are flush top and/or bottom because they sit
   directly above a card row. */
.section-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--gap-32); width: 100%;
}

/* Press kit heading: same full-width, space-between row as every
   other .section-head (inherited — not overridden here), just
   vertically centred instead of top-aligned so the button sits on
   the h3's middle rather than its cap-height. Staying on one line at
   every width, including mobile, is handled by the flex-wrap and
   .actions--sm rules below/near the mobile breakpoint. */
.section-head--inline { align-items: center; }

/* Vertical padding modifiers used by the stacked download blocks.
   64 maps to Page Padding/padding-global, which is the token
   Figma binds for that value. */
.section--pt-0   { padding-top: 0; }
.section--pt-48  { padding-top: var(--padding-section-small); }
.section--pt-64  { padding-top: var(--padding-global); }
/* Matches the gap the section itself puts between its children, so a
   preceding section with padding-bottom: 0 lands at the same rhythm.
   Tracks --gap-section down the breakpoints rather than pinning 80px. */
.section--pt-section { padding-top: var(--gap-section); }
.section--pb-0   { padding-bottom: 0; }
.section--pb-48  { padding-bottom: var(--padding-section-small); }
.section--pb-64  { padding-bottom: var(--padding-global); }

/* "Blog / 36 /" download cards — Card V gap 0 · r32 · fill
   Foreground · stroke; inner Content V gap 24 p24; the title
   block is V gap 16. No image on these cards. */
.download-card {
  display: flex; flex-direction: column; height: 100%;
  /* Figma defines a stroke here but at strokeWeight 0 — it paints
     nothing. No border. */
  border-radius: var(--radius-medium);
  background: var(--scheme-foreground, transparent);
}
.download-card__body {
  display: flex; flex-direction: column; justify-content: space-between;
  gap: var(--gap-24); padding: var(--gap-24); height: 100%;
}
.download-card__text { display: flex; flex-direction: column; gap: var(--gap-16); }
.download-card__kind { font-size: var(--text-sizes-text-small); font-weight: var(--font-weight-semibold); }

/* "FAQ / 5 /" on Resources is five named groups, V gap 48 each,
   with the section itself at gap 80 between groups. */
.faq-group { display: flex; flex-direction: column; gap: var(--gap-48); width: 100%; }
.faq-group__intro { display: flex; flex-direction: column; gap: var(--gap-24); max-width: var(--max-width-large); }


/* =============================================================
   26. OCUTAP PAGE COMPONENTS

   Figma "OcuTap • Desktop" (10215:94010).
   ============================================================= */

/* "Stats / 27 /" and "Stats / 31 /" — stat CARDS, unlike Home's
   Stats / 8 / which is a left-ruled row. p32 · r32/r40 · fill
   Foreground · stroke. Inner gap is 48 on the clinical-need row
   and 12 on the molecular row. */
.stat-card {
  display: flex; flex-direction: column; gap: var(--gap-48); height: 100%;
  padding: var(--gap-32);
  /* Figma defines a stroke here but at strokeWeight 0 — it paints
     nothing. No border. */
  border-radius: var(--radius-medium);
  background: var(--scheme-foreground, transparent);
}
.stat-card--tight { gap: var(--gap-12); border-radius: var(--radius-large); }
.stat-card__figure {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-stat);
  line-height: 1.3;
  letter-spacing: var(--letter-spacing-heading);
}
.stat-card__body { display: flex; flex-direction: column; gap: var(--gap-8); }

/* "Layout / 353 /" — sticky intro beside a scrolling list.

   Figma renders the static state: Component H · gap 80, with the
   intro column capped at max-width-medium and six pain-point rows
   in a 640 column beside it, all expanded. The behaviour is that
   the intro PINS while the rows scroll past — Relume Layout 353.

   position: sticky needs an offset that clears the 72px navbar,
   which is itself sticky. Hence 72 + the section's own top padding.
   ------------------------------------------------------------- */
.painpoints { display: flex; align-items: flex-start; gap: var(--gap-80); width: 100%; }

.painpoints__intro {
  flex: 1 1 0; min-width: 0;
  max-width: var(--max-width-medium);
  position: sticky;
  top: calc(72px + var(--gap-48));
  align-self: flex-start;
  display: flex; flex-direction: column; gap: var(--gap-32);
}

.painpoint-list { display: flex; flex-direction: column; gap: var(--gap-32); flex: 1 1 0; min-width: 0; }

/* Row: H · gap 24 · p32 · r40 · fill Foreground · stroke.
   The figure sits left; the body carries its OWN left rule and 24px
   indent — a second stroke inside the card, not the card border. */
.painpoint {
  display: flex; align-items: center; gap: var(--gap-24);
  padding: var(--gap-32);
  /* Figma defines a stroke here but at strokeWeight 0 — it paints
     nothing. No border. */
  border-radius: var(--radius-large);
  background: var(--scheme-foreground, transparent);
}
/* All six figures are three glyphs wide in Figma (56%, 54%, 51%,
   38%, 26%, 25%) but rendered widths still differ by a few px, which
   left the body rules visibly unaligned down the column. A shared
   min-width in em tracks the stat size at every breakpoint. */
.painpoint__figure {
  flex: 0 0 auto;
  min-width: 2.5em;
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-stat);
  line-height: 1.3;
  letter-spacing: var(--letter-spacing-heading);
}
.painpoint__body {
  display: flex; flex-direction: column; gap: var(--gap-16);
  padding-left: var(--gap-24);
  border-left: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-7-border));
}

/* "Layout / 361 /" device-at-a-glance cards — same card shell as
   elsewhere but padded 32 and titled at Heading/H4. */
.feature-card { padding: var(--gap-32); gap: var(--gap-24); }
.feature-card__title { font-size: var(--text-sizes-heading-4); font-family: var(--font-family-heading); line-height: var(--line-height-snug); }

/* "Layout / 154 /" — the procedure video.

   Figma shows a still with a play button because a static frame is
   all it can show. In the build this is a real <video> with native
   controls, which gives play/pause, scrub, volume, captions and
   fullscreen for free — and, more importantly, gives them with the
   keyboard handling, screen-reader labels and platform conventions
   that a hand-rolled player almost never gets right.
   ------------------------------------------------------------- */
/* Figma "Layout / 154 /" Container: V gap 12 between the player and
   the transcript accordion. */
.video { display: flex; flex-direction: column; gap: var(--gap-12); width: 100%; }

.video__player {
  display: block; width: 100%; height: auto;
  border-radius: var(--radius-large);
  background: var(--color-neutral-darkest);
}

/* Default state is the poster plus a single play affordance. Native
   controls are attached on first play, not before. */
.video__frame { position: relative; display: block; width: 100%; }
.video__play {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  padding: 0; border: 0; cursor: pointer;
  background: transparent;
  border-radius: var(--radius-large);
}
.video__play::before {
  content: ""; position: absolute; inset: 0;
  background: rgba(4, 45, 71, 0.28);
  border-radius: inherit;
  transition: background 0.2s ease;
}
.video__play:hover::before { background: rgba(4, 45, 71, 0.14); }
.video__play[hidden] { display: none; }
/* Uses the existing play-button glyph, which already draws its own
   disc, so no extra circle here. */
.video__play .icon {
  position: relative;
  width: 88px; height: 88px;
  color: var(--color-white);
  filter: drop-shadow(0 8px 32px rgba(4, 45, 71, 0.45));
  transition: transform 0.2s ease;
}
.video__play:hover .icon { transform: scale(1.06); }


/* The bespoke transcript panel was replaced by a <details>
   accordion sharing the references-strip component. */

/* "Layout / 351 /" — HORIZONTAL ACCORDION, not a tab strip.

   Figma geometry is unambiguous:
     Row        H · gap 0 · 1280x720
     Tab Pane 1 706 wide · layoutGrow 1   (open, grows)
     Tab Panes 2-8  82 wide · HUG         (collapsed to the strip)
     Feature Tab    82x720 · V · gap 10 · p 32/24
       number  Heading/H5, centred
       title   Heading/H5, ROTATED 90 degrees
     Content        640 wide · V · gap 48 · p 64/48  (open pane only)
   Each pane carries a 1px right border bound to Color Scheme
   7/Border; the last pane has none.

   Relume lists "Accordion" among Layout 351's related UI elements,
   which corroborates the reading. */
/* The whole accordion sits on a Color Scheme 7/Foreground card
   (white on this section) at Radius/Large. overflow:hidden is
   required, not cosmetic: each pane paints its own right border to
   the full height, and without clipping those borders square off
   the rounded corners. */
.steps {
  display: flex;
  width: 100%;
  /* Figma's Row is 720 tall only because the artboard is fixed.
     Both the panes and the card now hug their content; the image
     max-height below is what actually bounds the section. */
  min-height: 0;
  background: var(--scheme-foreground, var(--color-white));
  border-radius: var(--radius-large);
  overflow: hidden;
}

.step-pane {
  position: relative;                   /* anchors the collapsed .step-panel below */
  display: flex;
  flex: 0 0 82px;                       /* collapsed */
  overflow: hidden;
  border-right: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-7-border));
  transition: flex-grow 0.45s ease, flex-basis 0.45s ease;
}
.step-pane:last-child { border-right: 0; }
.step-pane[data-open="true"] { flex: 1 1 82px; }

/* Desktop only — below 1200px the accordion is already vertical and
   .step-panel gets an explicit height:0/auto per state (see the
   min-width:1200px block far below), so it never hits the bug this
   fixes.

   A closed pane still renders its .step-panel (kept in the DOM for the
   crossfade and for screen readers), but as an in-flow flex child at
   an 82px pane width its flex-basis:0 leaves it ~0px wide, so its
   paragraph word-wraps to one glyph per line and reports a towering
   "natural" height. .steps is a default-stretch flex row, so it adopts
   the TALLEST of those eight bogus heights for every pane — hence the
   ~1350px strip. Pulling the closed panel out of flow removes it from
   that calculation entirely; only the open panel's real content height
   (plus the plain tab strips) determines the row's height now.

   Being position:absolute lifts it into its own paint layer, so even
   invisible (opacity:0) it still sits in front of the sibling
   .step-tab button underneath and swallows clicks meant for steps 2-8.
   pointer-events:none removes it from hit-testing while leaving the
   height fix and the crossfade/screen-reader behavior untouched. */
@media (min-width: 1200px) {
  .step-pane:not([data-open="true"]) .step-panel {
    position: absolute;
    inset: 0;
    pointer-events: none;
  }
}

.step-tab {
  flex: 0 0 82px; width: 82px;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: var(--gap-32) var(--gap-24);
  border: 0; background: none; color: inherit; cursor: pointer;
  font-family: var(--font-family-heading);
  font-size: var(--text-sizes-heading-5);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-heading);
  transition: opacity 0.2s ease;
  opacity: 0.55;
}
.step-pane[data-open="true"] .step-tab { opacity: 1; }
.step-tab:hover { opacity: 1; }

/* Figma rotates the label +90 degrees, i.e. counter-clockwise, so it
   reads bottom-to-top. vertical-rl reads top-to-bottom, hence the
   extra 180. */
/* Figma: number is Heading/H5, centred, unrotated. */
.step-tab__num { display: block; text-align: center; }

.step-tab__title {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
}

/* When a pane opens, its rotated label is redundant — the same words
   appear as the panel heading right beside it. Hide it visually so
   the strip shows only the number.

   Clipped rather than display:none deliberately: the button's
   accessible name would otherwise collapse to just "1", leaving a
   screen reader with eight buttons called 1 through 8 and no idea
   what any of them do. This keeps the text in the accessibility
   tree while removing it from view.

   Desktop only, and the threshold must match the one that flips the
   accordion vertical (1200). Below that the label IS the row —
   hiding it would leave a bare number as the control. */
@media (min-width: 1200px) {
  .step-pane[data-open="true"] .step-tab__title {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap; border: 0;
  }
  /* Number alone should sit at the top of the strip, not drift. */
  .step-pane[data-open="true"] .step-tab { justify-content: flex-start; }
}

.step-panel {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; gap: var(--gap-32);
  padding: var(--gap-32);
  opacity: 0;
  transition: opacity 0.3s ease 0.1s;
}
/* Head keeps its natural height; the figure absorbs whatever space
   is left, so there is no blank strip at the foot of the panel. */
.step-panel__head { flex: 0 0 auto; }
.step-pane[data-open="true"] .step-panel { opacity: 1; }
/* Hugging its own content means the row now resizes as you switch
   between a two-line step (7) and a four-line one (4). --step-panel-
   height is set by equalizeStepHeights() in app.js to the tallest of
   the eight, measured at the open panel's actual width, so the strip
   holds one height regardless of which step is open. No-ops (plain
   content height) with JS disabled. Desktop only — the mobile block
   below already hard-sets height:auto per open pane. */
@media (min-width: 1200px) {
  .step-pane[data-open="true"] .step-panel { min-height: var(--step-panel-height, auto); }
}
.step-panel__head { display: flex; flex-direction: column; gap: var(--gap-24); max-width: 544px; }

/* The eight illustrations range 1.187:1 to 1.360:1, so a raw <img>
   would resize the pane on every click. Pin 5:4 and contain. */
/* Every illustration is now 1000x800, so the pane can simply adopt
   5:4 rather than pinning a max-height and letting `contain` letterbox
   whatever did not fit. `flex: 1 1 auto` used to make this absorb all
   spare height and centre a shorter image inside it, which is where
   the dead space above and below came from. */
.step-figure {
  width: 100%; max-width: 544px;
  aspect-ratio: 5 / 4;
  flex: 0 0 auto; min-height: 0;
  display: block;
  /* The illustrations are line drawings inside their own rounded
     frame, so a radius here clipped the corners of that frame.
     Procedure imagery is square-cornered by design. */
  border-radius: var(--radius-procedure);
  overflow: hidden;
}
/* Source and frame share a ratio, so cover crops nothing — it just
   guarantees the box is filled if a future asset differs slightly. */
.step-figure img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-procedure); }

/* Step 8 carries two illustrations (cap/discard, then sharps
   disposal) instead of one. Reuse .step-figure for each frame —
   same 5:4 ratio, same cover/radius — and let the group split the
   544px column between them so neither stretches or crops. */
.step-figure-group {
  display: flex;
  gap: var(--gap-16);
  width: 100%;
  max-width: 544px;
}
.step-figure-group .step-figure { max-width: none; flex: 1 1 0; min-width: 0; }

/* "Stats / 27 /" clinical evidence — one tall card beside two
   stacked cards, all sharing the card shell. */
.evidence { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap-32); width: 100%; }
.evidence__stack { display: flex; flex-direction: column; gap: var(--gap-32); }
.evidence__figure { font-family: var(--font-family-heading); font-size: var(--text-sizes-heading-3); line-height: var(--line-height-tight); letter-spacing: var(--letter-spacing-heading); }

/* Disclaimer paragraph under the safety accordions. */
.disclaimer { font-size: var(--text-sizes-text-tiny); }   /* opacity 0.8 put 12px text at 3.76:1 */

/* Regulatory notice that has to be READ, not merely present. Tiny grey
   type at the foot of a page is the opposite of prominent, so this
   variant sits on the section's Foreground surface with a rule down
   the leading edge and steps up to Small. */
/* Same device as the regulatory banner: an info icon carries the
   attention, so the type can stay quiet and the block needs no rule
   or tint. Sits on the section's Foreground surface. */
.disclaimer--notice {
  display: flex;
  align-items: flex-start;
  gap: var(--gap-12);
  font-size: var(--text-sizes-text-small);
  padding: var(--gap-24);
  border-radius: var(--radius-small);
  background: var(--scheme-foreground, var(--scheme-7-foreground));
  max-width: none;
}
.disclaimer--notice .icon {
  flex: 0 0 auto;
  margin-top: 2px;                 /* optical alignment to the first line */
  color: var(--scheme-accent, var(--color-dark));
}
.disclaimer--notice strong { font-weight: var(--font-weight-bold); }


/* =============================================================
   27. TEXT/STAT — display figures

   The big statistics are a raw override in Figma, not a token:
   Poppins BOLD 80px, line-height 1.3 (1.2 in the economics cards),
   with NO font-size variable bound. So they do not participate in
   the Desktop/Mobile type swap and would stay 80px on a phone,
   where "40 µL/s" overflows. The breakpoints below are ours.

   Colours vary per placement and are NOT all the scheme accent:
     Home  Stats / 8 /    Color Scheme 3/Text     (inherits)
     OcuTap Stats / 27 /  Color/Regent St Blue
     OcuTap Layout / 353 / Color Scheme 5/Accent  -> Color/Dark
     OcuTap Stats / 31 /  Scheme 5 & 7 Accent     -> Color/Dark
     Layout / 519 / $137  Color Scheme 8/Accent   -> Color/Dark
     Layout / 519 / $75   Color Scheme 1/Text     (inherits, white)
   ============================================================= */
.t-stat {
  font-family: var(--font-family-heading);
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sizes-stat);
  line-height: 1.3;
  letter-spacing: var(--letter-spacing-heading);
}
.t-stat--tight  { line-height: 1.2; }   /* economics cards */

/* -------------------------------------------------------------
   Text/Accent

   Figma reaches for brand-accent text in five places and picks a
   different token each time, purely because of what surface the
   text sits on. One role, one class, four surface variants —
   compose it onto whatever type style the element already has.
   ------------------------------------------------------------- */
.t-accent        { color: var(--color-regent-st-blue); }        /* on navy  (scheme 1) #9cd2e2 */
.t-accent--light { color: var(--color-regent-st-blue-light); }  /* on teal  (scheme 3) #b9dfea */
.t-accent--mid   { color: var(--color-default); }               /* on white (scheme 5) #317993 */
.t-accent--dark  { color: var(--color-dark); }                  /* on grey  (scheme 7) #063959 */

/* Canonical tagline: .label sizing, colour keyed to the surrounding
   scheme so one class works everywhere.

   Light schemes take the scheme's Accent role (navy). Dark schemes take
   the Regent St Blue family instead, which reads as brand rather than
   plain white. Scheme 3 has to step to the lightest tint: teal is a
   mid-tone, so Regent St Blue itself only reaches 2.97:1 against it and
   even Lighter falls short at 4.45:1. */
.label.t-accent { color: var(--scheme-accent, var(--color-dark)); }
.scheme-1 .label.t-accent,
.scheme-6 .label.t-accent { color: var(--color-regent-st-blue); }           /* 7.33:1 on navy */
.scheme-3 .label.t-accent { color: var(--color-regent-st-blue-lightest); }  /* 4.66:1 on teal */

/* =============================================================
   28. TYPE SCALE — small-screen refinement

   design-tokens.css mirrors Figma exactly and is generated, so the
   tuning lives here instead of being hand-edited into that file.

   Figma has a single Mobile mode, which it draws at 390px but which
   applies from 767px down. Those values (H1 40, H2 36, H3 32) read
   well at the top of that range and crowd badly at the bottom: at
   360px the usable width is only 320px, so a 40px H1 gives roughly
   eight characters a line.

   clamp() keeps Figma's Mobile values intact at 767px and tapers
   toward a floor on small handsets, so no new breakpoint is needed
   and nothing changes at tablet or desktop. Worth adding these as a
   Mobile-mode range in Figma if you want the file to match.
   ============================================================= */
@media (max-width: 767px) {
  :root {
    --text-sizes-heading-1: clamp(30px, 8.2vw, 40px);   /* 390px -> 32 */
    --text-sizes-heading-2: clamp(27px, 7.4vw, 36px);   /* 390px -> 29 */
    --text-sizes-heading-3: clamp(24px, 6.6vw, 32px);   /* 390px -> 26 */
    --text-sizes-heading-4: clamp(20px, 4.9vw, 24px);   /* 390px -> 20 */
    --text-sizes-heading-5: clamp(18px, 4.1vw, 20px);   /* 390px -> 18 */
    --text-sizes-stat:      clamp(34px, 9.2vw, 45px);   /* 390px -> 36 */
  }
}


/* =============================================================
   22. RESPONSIVE

   Structure, because getting this wrong caused a run of bugs:

   Layout rules that must hold for BOTH tablet and phone live in
   plain max-width blocks. The 768-991 block is range-bounded ONLY
   because it also carries :root token overrides, which must not
   leak down into the phone block. Anything layout-related put in
   there silently stops applying below 768 — that is what left the
   hero overlapping, the painpoints sticky, the step panels
   collapsed and the evidence cards side by side on phones.

   Order matters: widest max-width first, narrowest last.
   ============================================================= */

/* ---- Steps accordion: horizontal only where it fits ----------
   Seven collapsed panes occupy 7 x 82 = 574px, and the open pane
   takes whatever is left of the container:

       container 1280 -> open pane 706 -> 610px of content
       container 1072 -> open pane 498 -> 402px
       container  896 -> open pane 322 -> 226px
       container  864 -> open pane 290 -> 194px

   Figma drew this at 1440. Below roughly 1200 the open pane is
   narrower than the illustration inside it, which is what made the
   tabs feel so tight. Go vertical there instead of persisting with
   a layout the width cannot support. */
@media (max-width: 1199px) {
  /* Four-up grids give each card 192-244px between 992 and 1199,
     which is not enough for a 48px icon plus a heading and body.
     Two-up keeps the 4-item sets balanced (2x2) rather than 3+1. */
  .grid--4, .team-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* The painpoint split leaves the list 392-496px here, and the
     equalised figure column alone is 187px of that. Stack instead —
     sticky is pointless once the intro is above the list. */
  .painpoints { flex-direction: column; gap: var(--gap-48); }
  .painpoints__intro { position: static; max-width: none; flex: 0 0 auto; }

  .steps { flex-direction: column; min-height: 0; }
  .step-pane {
    flex: 0 0 auto; flex-direction: column; border-right: 0;
    border-bottom: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-7-border));
  }
  .step-pane:last-child { border-bottom: 0; }
  .step-pane[data-open="true"] { flex: 0 0 auto; }
  .step-tab {
    flex: 0 0 auto; width: 100%; flex-direction: row; align-items: center;
    gap: var(--gap-16); padding: var(--gap-24) var(--gap-32); justify-content: flex-start;
  }
  .step-tab__title { writing-mode: horizontal-tb; transform: none; white-space: normal; text-align: left; }
  /* flex:1 1 0 from the base rule resolves against the HEIGHT once
     the pane is a column, so height:auto never won on its own. */
  /* height:0 collapses the CONTENT box only — padding still counts
     toward the border box, so a closed pane was carrying 40px of
     dead space under its tab. Padding belongs on the open state. */
  .step-panel {
    flex: 0 0 auto; height: 0; overflow: hidden;
    padding: 0;
    gap: var(--gap-32);
  }
  .step-pane[data-open="true"] .step-panel {
    flex: 0 0 auto; height: auto;
    padding: 0 var(--gap-32) var(--gap-40);
  }
  .step-panel__head { max-width: none; }
  /* Once the accordion is vertical the tab label sits directly above
     the panel, so repeating it as a visible heading is redundant.
     Clipped rather than display:none — the heading still needs to
     exist for anyone navigating by headings. */
  .step-panel__head > h4 {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0);
    white-space: nowrap; border: 0;
  }
  .step-figure { flex: 0 0 auto; max-width: none; }
  .step-figure-group { max-width: none; }
}

/* ---- Below desktop: shared stacking --------------------------
   Applies to tablet AND phone. */
@media (max-width: 991px) {
  /* ---- Mobile navbar — Figma "Navbar / mobile" (10461:44948) ----
     Bar is 64 tall, padding 0/12/0/20, gap 16, and carries BOTH the
     Contact us button and the toggle. The button was previously
     display:none here, which is why it went missing.

     Panel: Row V gap32 pad 16/20/160/20, centred. Its single Column
     has gap 0, so the spacing between links comes from each Link's
     own 12px block padding, not from a gap. */
  .navbar { height: 64px; padding-inline: 0; }
  body { padding-top: 64px; }
  /* The toggle is a 48px frame around a 24px glyph, so it carries 12px
     of its own breathing room on each side. A container gap on top of
     that pushed the CTA visibly away from it. */
  .navbar__container { gap: 0; padding: 0 12px 0 20px; }
  .navbar__brand { margin-right: var(--gap-16); }
  .navbar__brand { flex: 1 1 0; }
  .navbar__actions { display: flex; flex: 0 0 auto; gap: var(--gap-8); }
  .navbar__actions .button { padding: 4px 20px; font-size: var(--text-sizes-text-small); }
  .nav-toggle { display: inline-flex; }

  .navbar__links { display: none; }
  /* Fill the rest of the viewport below the 64px bar instead of the
     literal Figma frame height. That frame was sized to its content
     plus a fixed 160px bottom pad for one specific viewport in the
     design file; on real (often taller or shorter) devices that pad
     either fell short of the screen edge — leaving bare page behind
     the panel — or clipped a long menu. 100dvh (not vh) so mobile
     browser chrome doesn't leave a gap or force scroll. */
  .navbar__links[data-open="true"] {
    display: flex; position: fixed; top: 64px; left: 0; right: 0;
    height: calc(100dvh - 64px);
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 16px 20px calc(20px + env(safe-area-inset-bottom, 0px));
    overflow-y: auto;
    background: var(--scheme-7-background); color: var(--scheme-7-text);
    box-shadow: var(--shadow-menu);
  }
  /* Every Link is 335x48: a 24px line with 12px above and below. */
  .navbar__links[data-open="true"] .nav-item { gap: var(--gap-12); padding-block: 12px; }
  .navbar__links[data-open="true"] .nav-link {
    justify-content: center; width: 100%;
    font-size: var(--text-sizes-text-medium);   /* 16px at this breakpoint */
  }
  /* Submenu is in flow, centred, 14px, gap 24 — not the desktop popover. */
  .navbar__links[data-open="true"] .nav-menu {
    position: static; display: flex; align-items: center;
    gap: var(--gap-24); padding: 12px 0; min-width: 0;
    background: none; box-shadow: none; border-radius: 0;
  }
  .navbar__links[data-open="true"] .nav-menu li { width: 100%; }
  .navbar__links[data-open="true"] .nav-menu a {
    display: block; width: 100%; text-align: center;
    font-size: var(--text-sizes-text-regular);  /* 14px at this breakpoint */
  }
  /* Collapsed submenu still needs to be reachable by the chevron. */
  .navbar__links[data-open="true"] .nav-item[data-dropdown]:not([data-open="true"]) .nav-menu { display: none; }

  /* Two-column rows stack. */
  .row--stack-mobile { flex-direction: column; align-items: stretch; }
  .section-head { flex-direction: column; align-items: flex-start; gap: var(--gap-24); }
  /* Undoes the column-stack above just for the Press kit heading, so
     the h3 and button stay paired on one row instead of dropping to
     separate lines. Same specificity as .section-head, so source
     order (this rule coming after) is what wins for elements carrying
     both classes. flex-wrap:nowrap forces one line — with wrap, the
     browser was moving the whole button to its own line rather than
     letting the h3 shrink first, which is what caused it to drop
     below the heading. If it's ever truly too tight, the h3's own
     text can still wrap internally; the button (nowrap text) can't
     shrink, so it needs actions--sm below to stay hugged instead of
     stretching to fill the row. */
  .section-head--inline { flex-direction: row; flex-wrap: nowrap; }
  .evidence { grid-template-columns: minmax(0, 1fr); }
  .founder { flex-direction: column; }
  /* Was 3/2 — a landscape box on a portrait source, cropping away
     more than half the height. Square was no better: full-bleed
     across an 836px card still meant a 33% crop. Cap the media and
     centre it instead, so the frame can be tall in ratio without
     becoming enormous in absolute height. 4/5 holds the crop to the
     same 16% at every stacked width. */
  .founder__media { max-width: 560px; margin-inline: auto; }
  .founder__media img { aspect-ratio: 4 / 5; height: auto; }
  .split-intro { flex-direction: column; gap: var(--gap-32); }
  .split-intro__aside { flex: 0 0 auto; }

  /* Label column needs more of the table once space is tight. */
  .comparison col.comparison__col-label { width: 34%; }
  .refs-list { column-count: 1; }

  /* Three stats across a 704-836px container leaves each 213-257px,
     under a 60px display figure. Two-up. */
  .stats-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Hero: in a column flex container `flex: 1 1 0` resolves against
     the HEIGHT, so the media box must size to its content instead.
     Badges return to flow rather than overlaying a full-width
     device shot. No fixed px heights — the PNGs are 432x315 and
     488x310, so forcing a square re-crops the shadow padding. */
  /* Figma keeps the overlapping composition at every width, so the
     badges stay absolutely placed rather than dropping into flow. The
     only thing a column grid breaks is `flex: 1 1 0`, which resolves
     against the HEIGHT once the axis turns — hence 0 0 auto. */
  .hero__grid { flex-direction: column; align-items: stretch; }
  .hero__media { flex: 0 0 auto; padding-left: 0; min-height: 0; }
}

/* ---- Tablet only: 768-991 ------------------------------------
   Token overrides plus the few values that are genuinely specific
   to this range. Nothing layout-critical belongs here. */
@media (min-width: 768px) and (max-width: 991px) {
  :root {
    --padding-global: 32px;
    --padding-section-large: 80px;
    --padding-section-medium: 64px;
    --gap-section: var(--gap-48);
    --text-sizes-stat: 60px;
  }

  .grid--3, .grid--4, .team-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .card--feature { padding: var(--gap-32); }
  .row--80 { gap: var(--gap-48); }
  .cta-card { padding: var(--gap-48); }
  .stats-row { gap: var(--gap-32); }
  .footer__content { flex-direction: column; }
  .footer__nav { flex: 0 0 auto; width: 100%; }
}

/* ---- Phone: <= 767 ------------------------------------------- */
@media (max-width: 767px) {
  :root { --gap-section: var(--gap-40); }

  /* Contact us stays visible on phones — Figma keeps it in the bar
     alongside the toggle. */

  /* Step 8's two frames side-by-side would run under 160px wide on
     a phone — too small to read the illustration. Stack instead.
     Children must drop back to flex: 0 0 auto here: the base rule's
     flex: 1 1 0 sets a 0 flex-basis, which resolves against HEIGHT
     once the group turns column — same trap as .step-pane elsewhere
     in this file — and collapses each frame to nothing instead of
     sizing from its aspect-ratio. */
  .step-figure-group { flex-direction: column; gap: var(--gap-16); }
  .step-figure-group .step-figure { flex: 0 0 auto; width: 100%; }

  .hero__grid { gap: var(--gap-32); }
  /* Mobile hero — Figma 10468:2726. Image container 335x286:
       device 266x266 @ (34, 0)  ·  badge 1 116x116 @ (0, 135)
       badge 2 131x83 @ (204, 34), flush to the right edge.
     Widths are grossed up and offsets pulled back by each PNG's
     transparent shadow padding, so the VISIBLE artwork lands on those
     boxes. Tops are percentages of the device height, which is what
     sets the container height. */
  .hero__device { width: 79.403%; margin-left: 10.149%; }   /* 266 / 34 of 335 */
  .hero__badge--1 { left: -7.13%;  top: 41.8%; width: 48.9%; }
  .hero__badge--2 { right: -4.79%; top: 6.8%;  width: 48.7%; }
  .footer__content { flex-direction: column; gap: var(--gap-40); }
  .footer__nav { flex: 0 0 auto; width: 100%; flex-direction: column; gap: 0; }
  .footer__credits-row { flex-direction: column; gap: var(--gap-24); }
  .row--80 { gap: var(--gap-32); }

  .grid--2, .grid--3, .grid--4, .team-grid { grid-template-columns: minmax(0, 1fr); }
  .stats-row { grid-template-columns: minmax(0, 1fr); gap: var(--gap-24); }

  .founder__body { padding: var(--gap-24); }
  /* Already under the 560 cap at this width — nothing further to do
     beyond letting it run full width. */
  .founder__media { max-width: none; }
  .painpoints { gap: var(--gap-32); }
  .painpoint { flex-direction: column; align-items: flex-start; gap: var(--gap-16); padding: var(--gap-24); }
  .painpoint__figure { min-width: 0; }
  .painpoint__body { padding-left: 0; border-left: 0; }

  .step-tab { padding: var(--gap-24) var(--gap-24); }
  .step-panel { padding: 0; gap: var(--gap-24); }
  .step-pane[data-open="true"] .step-panel { padding: 0 var(--gap-24) var(--gap-32); }

  .card--feature { padding: var(--gap-24); }
  .cta-card { padding: var(--gap-32); }
  .cta-card > * { max-width: none; }
  .faq__answer { padding-right: var(--gap-24); }
  .faq__followup { flex-direction: column; align-items: flex-start; }

  /* Section-level CTAs go full-width on a phone so they are easy to
     hit. Card CTAs must not: a card is already narrow, and stretching
     two small buttons across it centres their labels and breaks the
     left edge that every other line in the card shares. */
  .actions:not(.actions--sm) { width: 100%; }
  .actions:not(.actions--sm) .button { flex: 1 1 auto; justify-content: center; }
  .actions--sm { width: auto; justify-content: flex-start; }
  .actions--sm .button { flex: 0 0 auto; justify-content: center; }
  .signup { flex-direction: column; max-width: none; }
  .form__row { flex-direction: column; }
  .choices { grid-template-columns: minmax(0, 1fr); }

  /* The comparison table cannot stay a grid at this width. Rows
     become stacked blocks; the column headings are carried down
     via data-label so each value stays labelled. */
  .comparison thead { display: none; }
  .comparison, .comparison tbody, .comparison tr, .comparison th, .comparison td { display: block; width: 100%; }
  .comparison tr {
    padding-block: var(--gap-16);
    border-bottom: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-7-border));
  }
  .comparison th, .comparison td { border: 0; padding: var(--gap-4) 0; }
  .comparison tbody th { font-weight: var(--font-weight-bold); }
  .comparison td::before {
    content: attr(data-label) " — ";
    font-weight: var(--font-weight-regular); opacity: 0.7;
  }
}

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

/* ---- Print --------------------------------------------------- */
@media print {
  .navbar, .nav-toggle, .actions, .signup { display: none !important; }
  .section { padding-block: var(--gap-24); }
  .page { display: block; }
}


/* =============================================================
   29. LEGAL PAGES  ("Legal Pages / TOS")

   Desktop: Header/64 (p48/64) with the title and effective date,
   then Content/27 — a 320px table of contents beside a 936px
   rich-text column, gap 24.

   Mobile: the ToC collapses into a disclosure above the body, and
   the whole section drops to p20/20/64/20 with a 32 gap.
   ============================================================= */
.legal { display: flex; align-items: flex-start; gap: var(--gap-24); width: 100%; }

/* Column is FIXED 320 in Figma — it does not grow with the body. */
.legal__toc {
  flex: 0 0 320px; min-width: 0;
  display: flex; flex-direction: column; gap: var(--gap-16);
  position: sticky; top: calc(72px + var(--gap-24));
  max-height: calc(100vh - 72px - var(--gap-48));
  overflow-y: auto;
}
.legal__toc-title { font-size: var(--text-sizes-heading-5); font-family: var(--font-family-heading); font-weight: var(--font-weight-medium); }
.legal__toc-list { display: flex; flex-direction: column; gap: 0; }
.legal__toc-list a {
  display: block; padding: 12px var(--gap-16);
  text-decoration: none;
  font-size: var(--text-sizes-text-medium);
  border-radius: var(--radius-small);
}
/* Indentation encodes heading depth, per the Figma padding ramp:
   H2 16 · H3 32 · H4 48 · H5 64 · H6 80. */
.legal__toc-list a[data-level="3"] { padding-left: 32px; }
.legal__toc-list a[data-level="4"] { padding-left: 48px; }
.legal__toc-list a[data-level="5"] { padding-left: 64px; }
.legal__toc-list a[data-level="6"] { padding-left: 80px; }
.legal__toc-list a[data-level="2"] { font-weight: var(--font-weight-bold); }
.legal__toc-list a:hover { background: var(--scheme-foreground, var(--scheme-7-foreground)); }
.legal__toc-list a[aria-current="true"] { background: var(--scheme-foreground, var(--scheme-7-foreground)); }

/* Resources FAQ only: .legal__toc-group/.legal__toc-sublist markup lets
   each group's questions collapse behind its heading. The Legal pages'
   ToC has no such markup, so none of this matches there. */
.legal__toc-list a.legal__toc-list__group-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: var(--gap-8);
}
.legal__toc-list__group-icon { flex: 0 0 auto; transition: transform 0.2s ease; }
.legal__toc-list__group-toggle[aria-expanded="true"] .legal__toc-list__group-icon { transform: rotate(180deg); }

/* Collapsed behind the group heading on desktop only — below 992px the
   sublist stays fully flat inside the existing mobile ToC disclosure. */
@media (min-width: 992px) {
  .legal__toc-sublist { display: none; flex-direction: column; }
  .legal__toc-group[data-open="true"] .legal__toc-sublist { display: flex; }
}

/* Rich Text — FILL beside the fixed ToC. */
.legal__body { flex: 1 1 0; min-width: 0; }
.legal__body > * { max-width: none; }
.legal__body h2 { margin-bottom: var(--gap-16); }
.legal__body h3 { margin: var(--gap-24) 0; }
.legal__body h4 { margin: var(--gap-24) 0 20px; }
.legal__body h5,
.legal__body h6 { margin: 20px 0 var(--gap-16); }
.legal__body p { margin-bottom: var(--gap-16); }
.legal__body > p:last-child { margin-bottom: 0; }
.legal__body ul, .legal__body ol { margin: 0 0 var(--gap-16); padding-left: 1.5em; }
.legal__body ul { list-style: disc; }
.legal__body ol { list-style: decimal; }
.legal__body li { margin-bottom: var(--gap-8); }
.legal__body a { text-decoration: underline; }
.legal__lead { font-weight: var(--font-weight-bold); }

/* Figure: 2px rule, 20px gutter, 36px above and below. */
.legal__body blockquote {
  margin: 36px 0; padding-left: 20px;
  border-left: 2px solid var(--scheme-border, var(--scheme-7-border));
}
.legal__body blockquote p:last-child { margin-bottom: 0; }

.legal__body table { width: 100%; border-collapse: collapse; margin-bottom: var(--gap-16); }
.legal__body th, .legal__body td {
  text-align: left; vertical-align: top;
  padding: var(--gap-12) var(--gap-16);
  border-bottom: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-7-border));
  font-size: var(--text-sizes-text-regular);
}
.legal__body th { font-weight: var(--font-weight-bold); }

/* The mobile disclosure is markup-only on desktop. */
.legal__toc-toggle { display: none; }


/* -------------------------------------------------------------
   LEGAL PAGES — stacked layout

   This has to sit AFTER section 29, not inside the section 22
   responsive block. Section 29 is appended at the end of the
   stylesheet, so overrides written earlier lost on source order at
   equal specificity — which is why the ToC never collapsed.

   Below 992 the two columns become one and the table of contents
   turns into a disclosure that starts closed, so the reader meets
   the document itself rather than a screen of links.
   ------------------------------------------------------------- */
@media (max-width: 991px) {
  .legal { flex-direction: column; gap: var(--gap-32); }

  .legal__toc {
    position: static;
    flex: 0 0 auto;
    width: 100%;
    max-height: none;
    overflow: visible;
    gap: 0;
    border: var(--stroke-divider-width) solid var(--scheme-border, var(--scheme-7-border));
    border-radius: var(--radius-small);
  }
  /* The visible heading is replaced by the button's own label. */
  .legal__toc-title { display: none; }

  .legal__toc-toggle {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--gap-8); width: 100%;
    padding: var(--gap-16);
    border: 0; background: none; color: inherit; cursor: pointer;
    text-align: left; font: inherit;
    font-size: var(--text-sizes-text-medium);
    font-weight: var(--font-weight-bold);
  }
  .legal__toc-toggle .icon { flex: 0 0 auto; transition: transform 0.2s ease; }
  /* keyboard-arrow-up already points up, so the CLOSED state is the
     rotated one and opening returns it to its natural orientation. */
  .legal__toc-toggle .icon { transform: rotate(180deg); }
  .legal__toc[data-open="true"] .legal__toc-toggle .icon { transform: rotate(0deg); }

  /* Closed by default. */
  .legal__toc-list { display: none; padding: 0 var(--gap-8) var(--gap-8); }
  .legal__toc[data-open="true"] .legal__toc-list { display: flex; }
  .legal__toc-list a {
    font-size: var(--text-sizes-text-regular);
    padding-block: 12px;
  }

  /* The body no longer shares a row, so it takes the full width. */
  .legal__body { flex: 0 0 auto; width: 100%; }
}


/* =============================================================
   30. FORM VALIDATION + MODALS

   Not in Figma — authored here. Three semantic colours are added
   because the palette has no error or success role. Values chosen
   against the surfaces they actually sit on:

     --color-error-on-dark  #FFB4AB on Color/Dark  7.12:1
     --color-error          #B3261E on white       6.54:1
                            white on #B3261E       6.54:1
     --color-success        #146C4E on white       6.39:1
                            white on #146C4E       6.39:1

   These belong in the Figma variable collection so the file and the
   build stop diverging.
   ============================================================= */
:root {
  --color-error:         #b3261e;
  --color-error-on-dark: #ffb4ab;
  --color-success:       #146c4e;
}

/* ---- Inline field errors ------------------------------------
   The message element is always in the DOM with aria-live, so a
   screen reader announces it the moment it is filled, and stays
   referenced by aria-describedby so re-focusing the field re-reads
   it. `:empty` keeps it out of the layout until it has something
   to say — no reserved gap, no layout shift beyond the message
   itself. The message text is what satisfies 1.4.1: colour is
   never the only signal that a field failed. */
.field-error {
  display: flex;
  align-items: flex-start;
  gap: var(--gap-8);
  margin: 0;
  font-size: var(--text-sizes-text-small);
  color: var(--color-error-on-dark);
}
.field-error:empty { display: none; }
.field-error .icon { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 2px; }

/* 1px is the Figma stroke weight; at 7.12:1 against the navy it
   reads clearly without thickening the control. */
.field[aria-invalid="true"] {
  border-color: var(--color-error-on-dark);
  background: var(--opacity-white-15);
}
.fieldset[data-invalid="true"] legend,
.consent[data-invalid="true"] > span { color: var(--color-error-on-dark); }
.consent[data-invalid="true"] input { outline: 2px solid var(--color-error-on-dark); outline-offset: 2px; }
.fieldset .field-error,
.consent-error { margin-top: var(--gap-8); }

/* ---- Submit result modal ------------------------------------
   Native <dialog> so focus trapping, Esc-to-close, inertness of the
   page behind, and focus restore all come from the platform rather
   than from script we would have to keep correct. */
.modal {
  width: min(480px, calc(100vw - 48px));
  padding: 0;
  border: 0;
  border-radius: var(--radius-medium);
  background: var(--color-white);
  color: var(--color-neutral-darker);
}
.modal::backdrop { background: rgb(2 22 35 / 0.6); }
.modal__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-16);
  padding: var(--gap-40);
  text-align: center;
}
.modal__icon {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  color: var(--color-white);
}
.modal__icon--success { background: var(--color-success); }
.modal__icon--error   { background: var(--color-error); }
/* "Check your inbox to confirm" is neither success nor failure — the
   signup is real but unconfirmed, so it takes the brand teal rather than
   the green that means done. Color/Default Dark, not Color/Default:
   white on #317993 is 4.90:1, which clears AA but sits close to the
   line for a 32px glyph; #215F74 gives 7.11:1 with no visible change to
   the hue at disc size. */
.modal__icon--pending { background: var(--color-default-dark); }
.modal__icon .icon { width: 32px; height: 32px; }
.modal__title { margin: 0; font-size: var(--text-sizes-heading-5); font-weight: var(--font-weight-extrabold); }
.modal__body  { margin: 0; font-size: var(--text-sizes-text-regular); color: var(--color-neutral-dark); }
.modal__body a { color: var(--color-default); }
.modal .actions { margin-top: var(--gap-8); }

@media (max-width: 767px) {
  .modal__inner { padding: var(--gap-32) var(--gap-24); }
}

/* ---- Error on the CTA card ----------------------------------
   The waitlist sits on a photograph under a 72% overlay, not on
   flat navy, so the error colour's contrast would vary with the
   image. #FFB4AB clears 4.5:1 against Color/Dark (7.12:1) but
   falls to 3.75:1 over the brightest part of card-1.png — a fail.
   A solid plate in the overlay's own base colour makes it
   deterministic at 8.41:1 without touching the artwork, the
   overlay, or the error colour used everywhere else.
   12px matches the radius of the input it sits under. */
.field-error--plate {
  align-self: flex-start;
  max-width: 100%;
  padding: var(--gap-8) var(--gap-12);
  border-radius: 12px;
  background: var(--color-dark-dark);
}
.signup input[aria-invalid="true"] {
  border-color: var(--color-error-on-dark);
  background: var(--opacity-white-15);
}

/* ---- Accessibility fixes (WCAG 2.1 AA audit, Oct 2026) ----------
   O1  Focus rings contrast with the surface around the button, not
       with the button's own text colour (white ring on the light page
       was 1.12:1; dark ring on navy was 1.42:1).
   P2  Field edges at >= 3:1 against navy (fill alone was 1.33:1).
   P6  Placeholder text at >= 4.5:1 (was 4.41:1).
   ---------------------------------------------------------------- */
.button--primary:focus-visible     { outline: 2px solid var(--color-dark);  outline-offset: 3px; }
.button--primary-alt:focus-visible { outline: 2px solid var(--color-white); outline-offset: 3px; }
.field,
.signup input[type="email"] { border-color: rgba(255, 255, 255, 0.6); }
.field::placeholder,
.signup input[type="email"]::placeholder { color: rgba(255, 255, 255, 0.72); }
/* Error state must still win over the new resting border. */
.field[aria-invalid="true"],
.signup input[type="email"][aria-invalid="true"] { border-color: var(--color-error-on-dark); }

/* ---- Accessibility fixes, minor items (Oct 2026) -----------------
   P4/P5  Hero badges rebuilt as real text (were images of text).
          Sizes are in container-query units so they scale exactly
          like the old PNGs did inside the same .hero__badge boxes.
   P7     Wide legal tables scroll inside their own box at 320 px.
   P8     Stat labels are paragraphs now; keep the heading look.
   ---------------------------------------------------------------- */
.badge-card { container-type: inline-size; }
.badge-card--status  { aspect-ratio: 432 / 315; }
.badge-card--tagline { aspect-ratio: 488 / 310; }
.badge-card__inner {
  position: absolute; display: flex; flex-direction: column; justify-content: center;
  box-shadow: 0 2.5cqw 7cqw rgba(3, 7, 8, 0.16);
}
.badge-card--status .badge-card__inner {
  inset: 19.7% 14.8% 20.6% 14.6%; align-items: center; text-align: center;
  background: var(--color-white); border-radius: 8.3cqw;
}
.badge-card--tagline .badge-card__inner {
  inset: 15.2% 9.8% 15.5% 9.8%; align-items: flex-start; padding-inline: 6.6cqw;
  border-radius: 5.3cqw;
  background: linear-gradient(121deg, var(--color-default) 0%, var(--color-dark) 100%);
}
.badge-card__big   { font-family: var(--font-family-body); font-weight: 800; font-size: 18.5cqw; line-height: 1; color: var(--color-dark); letter-spacing: 0.01em; }
.badge-card__small { font-family: var(--font-family-body); font-size: 7.3cqw; line-height: 1.2; color: var(--color-neutral-dark); margin-top: 3cqw; }
.badge-card__tag   { margin: 0; font-family: var(--font-family-heading); font-weight: 600; font-size: 8.4cqw; line-height: 1.25; color: var(--color-white); white-space: nowrap; }

.table-scroll { overflow-x: auto; max-width: 100%; }
.table-scroll:focus-visible { outline: 2px solid var(--color-dark); outline-offset: 2px; }

p.stat__label { margin: 0; font-weight: var(--font-weight-medium); letter-spacing: var(--letter-spacing-heading); }
