/* ==========================================================================
   ENTYTI v3 :: _tokens.css
   Design foundation for the Entyti pharmacy OS marketing site.
   Light theme, one accent colour (teal) that always means "action".
   Mobile first: every scale starts at 360px and grows to 1440px.
   No frameworks, no CDN, no third party request. Inter is the brand typeface
   and is SELF HOSTED from ./assets/fonts, so the brand face is what a chemist
   on Android Chrome actually sees, with no external connection.
   House rules honoured: no gradients as decoration, no glassmorphism,
   no shadow on every surface, no emoji, no em dashes.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. BRAND TYPEFACE (self hosted, brand kit v1.0 names Inter)
   Variable woff2, latin subset first. font-display: swap so text paints
   immediately in the fallback and reflows to Inter when it lands.
   Pages should also preload the latin file:
     <link rel="preload" href="./assets/fonts/inter-latin-var.woff2"
           as="font" type="font/woff2" crossorigin>
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("./assets/fonts/inter-latin-var.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("./assets/fonts/inter-latin-ext-var.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* Force the light palette even when the OS is in dark mode. Form controls,
     scrollbars and the UA default colours follow this keyword. */
  color-scheme: light;

  /* ---- Brand core (brand kit v1.0) ---- */
  --teal:            #00C2A8;   /* Primary Teal   */
  --navy:            #08111F;   /* Midnight Navy  */
  --ink:             #111827;   /* Text           */
  --bg:              #F8FAFC;   /* Background     */

  /* ---- Teal ramp (derived) ---- */
  --teal-050:        #E6FAF6;
  --teal-100:        #C4F2EA;
  --teal-200:        #8FE6D8;
  --teal-400:        #16CFB6;
  --teal-500:        var(--teal);
  --teal-600:        #00A891;
  --teal-700:        #00806F;   /* accessible teal for text on light */
  --teal-800:        #045F53;

  /* ---- Navy ramp (dark bands, footers, product frames) ---- */
  --navy-800:        #0C1729;
  --navy-700:        #101F36;
  --navy-600:        #16294514;  /* reserved, translucent navy wash */
  --navy-line:       #1E2C42;
  --navy-fg:         #F1F5F9;
  --navy-fg-muted:   #9FB0C4;

  /* ---- Neutral / surface ---- */
  --surface:         #FFFFFF;
  --surface-2:       #F1F5F9;
  --surface-3:       #E8EDF3;
  --line:            #E5E7EB;
  --line-strong:     #CBD5E1;
  --ink-2:           #374151;   /* body copy */
  /* Secondary copy. Darkened from #6B7280 so it clears 4.5:1 on the tinted
     --surface-2 panel as well as on white. #6B7280 measured 4.41:1 there. */
  --muted:           #5B626F;   /* 5.60:1 on #F1F5F9, 6.13:1 on #FFFFFF */
  /* Captions and meta. Darkened from #94A3B8, which measured 2.45:1 on --bg. */
  --muted-2:         #64748B;   /* 4.60:1 on #F8FAFC */

  /* ---- Status ---- */
  --success:         #0E9F6E;   /* dots and rules only, never small text */
  --success-fg:      #0B7A55;   /* 4.81:1 on --success-bg, use for badge text */
  --success-bg:      #E7F7F0;
  --rolling:         #B45309;   /* "rolling out", never "live" */
  --rolling-bg:      #FDF3E3;
  --danger:          #B42318;

  /* ---- Type ---- */
  --font: Inter, "Segoe UI", system-ui, -apple-system, Roboto, Helvetica, Arial, sans-serif;
  --font-num: Inter, "Segoe UI", system-ui, sans-serif;

  /* Fluid scale. Min value is the 360px reading, max is the 1440px reading.
     Floors were raised on 2026-07-20: --fs-sm bottomed out at 13.1px on a
     393px phone and carried card copy, list items, form labels, footer links
     and button text, all of which are real reading copy. See the mobile
     override under section 1b: below 768px --fs-sm is 16px and --fs-xs is
     13px, so nothing a chemist has to read is under 16px on a phone. */
  --fs-xs:   0.8125rem;                            /* 13px, incidental labels */
  --fs-sm:   clamp(0.875rem, 0.85rem + 0.12vw, 0.9375rem);
  --fs-base: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --fs-md:   clamp(1.0625rem, 1.02rem + 0.22vw, 1.1875rem);
  --fs-lg:   clamp(1.1875rem, 1.11rem + 0.36vw, 1.375rem);   /* lead text    */
  --fs-h4:   clamp(1.0625rem, 1.01rem + 0.26vw, 1.25rem);
  --fs-h3:   clamp(1.25rem, 1.15rem + 0.45vw, 1.625rem);
  --fs-h2:   clamp(1.75rem, 1.42rem + 1.45vw, 3rem);
  --fs-h1:   clamp(2.25rem, 1.62rem + 2.8vw, 4.25rem);
  --fs-display: clamp(2.5rem, 1.6rem + 4vw, 5rem);

  --lh-tight: 1.05;
  --lh-head:  1.14;
  --lh-body:  1.62;
  --ls-tight: -0.032em;
  --ls-head:  -0.022em;
  --ls-wide:  0.09em;

  --fw-body: 450;
  --fw-med:  500;
  --fw-semi: 600;
  --fw-bold: 800;
  --fw-black: 900;

  /* ---- Space scale (4px base, fluid at the top end) ---- */
  --s-1:  4px;
  --s-2:  8px;
  --s-3:  12px;
  --s-4:  16px;
  --s-5:  20px;
  --s-6:  24px;
  --s-7:  32px;
  --s-8:  40px;
  --s-9:  48px;
  --s-10: 64px;
  --s-11: 80px;
  --s-12: 112px;

  --gutter:   clamp(20px, 5vw, 40px);
  --section-y: clamp(56px, 8vw, 112px);
  --block-y:   clamp(32px, 5vw, 56px);

  /* ---- Radii ---- */
  --r-xs: 6px;
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 20px;
  --r-2xl: 28px;
  --r-pill: 999px;

  /* ---- Shadows. Used sparingly: raised buttons, the drawer, the modal. ---- */
  --sh-xs: 0 1px 2px rgba(8, 17, 31, 0.06);
  --sh-sm: 0 1px 3px rgba(8, 17, 31, 0.08), 0 1px 2px rgba(8, 17, 31, 0.04);
  --sh-md: 0 8px 24px rgba(8, 17, 31, 0.08);
  --sh-lg: 0 24px 60px rgba(8, 17, 31, 0.16);

  /* ---- Containers ---- */
  --w-narrow: 720px;
  --w-page:   1160px;
  --w-wide:   1320px;

  /* ---- Chrome heights (used to reserve page space) ---- */
  --nav-h: 60px;
  --stickybar-h: 64px;

  /* ---- Motion ---- */
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --t-fast: 0.14s;
  --t-med:  0.22s;
  --z-nav: 60;
  --z-drawer: 70;
  --z-stickybar: 55;
}

@media (min-width: 900px) {
  :root { --nav-h: 72px; }
}

/* --------------------------------------------------------------------------
   1b. MOBILE READING FLOOR
   On a phone every consumer of --fs-sm is body copy: card paragraphs, list
   items, form labels, chips, button labels, nav and footer links. 13px is
   below the mobile readability floor and below the 16px iOS threshold that
   stops Safari zooming the page when an input takes focus. Lift the whole
   small step to 16px under 768px and leave the desktop scale alone.
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
  :root {
    --fs-sm: 1rem;        /* 16px */
    --fs-xs: 0.8125rem;   /* 13px, badges, eyebrows, captions only */
  }
}

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

/* The [hidden] attribute must beat any component display rule. Without this,
   .btn { display: inline-flex } silently outranks the UA hidden rule and the
   step navigation shows every button at once. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 16px);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-2);
  font-family: var(--font);
  font-size: var(--fs-base);
  font-weight: var(--fw-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  /* Reserve room so the fixed mobile bar never covers page content. */
  padding-bottom: calc(var(--stickybar-h) + env(safe-area-inset-bottom, 0px));
}

@media (min-width: 768px) {
  body { padding-bottom: 0; }
}

/* Body scroll lock, applied by _site.js when the drawer or modal is open. */
body.is-locked { overflow: hidden; }

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

h1, h2, h3, h4, h5, h6 { margin: 0; color: var(--ink); }
p, ul, ol, figure, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }

h1 {
  font-size: var(--fs-h1);
  font-weight: var(--fw-black);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  text-wrap: balance;
}
h2 {
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  line-height: var(--lh-head);
  letter-spacing: var(--ls-head);
  text-wrap: balance;
}
h3 {
  font-size: var(--fs-h3);
  font-weight: var(--fw-bold);
  line-height: 1.22;
  letter-spacing: var(--ls-head);
}
h4 {
  font-size: var(--fs-h4);
  font-weight: var(--fw-semi);
  line-height: 1.3;
  letter-spacing: -0.012em;
}

a { color: var(--teal-700); text-decoration: none; }
a:hover { color: var(--teal-800); text-decoration: underline; text-underline-offset: 3px; }

strong, b { font-weight: var(--fw-semi); color: var(--ink); }
small { font-size: var(--fs-sm); }

hr { border: 0; border-top: 1px solid var(--line); margin: var(--s-8) 0; }

:focus-visible {
  outline: 2px solid var(--teal-700);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}
::selection { background: var(--teal-100); color: var(--navy); }

/* --------------------------------------------------------------------------
   3. LAYOUT
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--w-page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--narrow { max-width: var(--w-narrow); }
.wrap--wide   { max-width: var(--w-wide); }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: var(--block-y); }
.section + .section { border-top: 1px solid var(--line); }
.section--plain + .section--plain { border-top: 0; }

.stack > * + * { margin-top: var(--s-4); }
.stack-lg > * + * { margin-top: var(--s-6); }

.shead { max-width: 62ch; margin-bottom: clamp(28px, 4vw, 48px); }
.shead .eyebrow { margin-bottom: var(--s-3); }
.shead p { margin-top: var(--s-4); color: var(--muted); font-size: var(--fs-md); }

.lead { font-size: var(--fs-lg); color: var(--ink-2); line-height: 1.5; max-width: 56ch; }
.muted { color: var(--muted); }
.small { font-size: var(--fs-sm); }
.num { font-variant-numeric: tabular-nums; }
.center { text-align: center; }
.center .shead { margin-inline: auto; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--teal-700);
}

.grid { display: grid; gap: var(--s-4); }
@media (min-width: 640px) { .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 640px) { .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 640px) { .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px){ .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Horizontal snap rail on small screens, plain grid from 760px up. */
.rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 80%;
  gap: var(--s-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  margin-inline: calc(var(--gutter) * -1);
  padding: 2px var(--gutter) var(--s-3);
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { scroll-snap-align: start; }
@media (min-width: 760px) {
  .rail {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    overflow: visible;
    margin-inline: 0;
    padding: 0;
    gap: var(--s-4);
  }
}

/* --------------------------------------------------------------------------
   4. BUTTONS
   Primary = navy solid, the main action. Teal = the accent action.
   Ghost = quiet. All three clear 44px touch targets on mobile.
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 46px;
  padding: 12px 20px;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  letter-spacing: -0.006em;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.55; pointer-events: none; }
.btn svg { width: 18px; height: 18px; }

.btn-primary { background: var(--navy); color: #FFFFFF; box-shadow: var(--sh-xs); }
.btn-primary:hover { background: var(--navy-700); color: #FFFFFF; }

.btn-teal { background: var(--teal); color: var(--navy); box-shadow: var(--sh-xs); }
.btn-teal:hover { background: var(--teal-400); color: var(--navy); }

.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line-strong); }
.btn-ghost:hover { background: var(--surface); border-color: var(--navy); color: var(--ink); }

.btn-quiet { background: transparent; color: var(--ink-2); padding-inline: 10px; }
.btn-quiet:hover { color: var(--ink); background: var(--surface-2); }

.btn-lg { min-height: 52px; padding: 15px 26px; font-size: var(--fs-base); border-radius: var(--r-md); }
.btn-sm { min-height: 40px; padding: 9px 14px; }
.btn-block { display: flex; width: 100%; }

/* On a navy band the ghost button inverts. */
.dark .btn-ghost { color: var(--navy-fg); border-color: #2A3B55; }
.dark .btn-ghost:hover { background: var(--navy-700); border-color: var(--navy-fg-muted); color: var(--navy-fg); }
.dark .btn-primary { background: #FFFFFF; color: var(--navy); }
.dark .btn-primary:hover { background: #E2E8F0; color: var(--navy); }

.cta-row { display: flex; flex-wrap: wrap; gap: var(--s-3); }
/* Full width on the narrowest phones, and allowed to wrap. Button labels are
   16px on mobile now, and the longest label in the copy deck, "Book a demo on
   your own stock", lands within a pixel of the column width at 393px. nowrap
   there would clip the label rather than wrap it. */
@media (max-width: 419px) { .cta-row .btn { width: 100%; white-space: normal; } }

/* --------------------------------------------------------------------------
   5. CARDS
   -------------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(20px, 3vw, 28px);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.card h3, .card h4 { letter-spacing: -0.015em; }
.card p { color: var(--muted); font-size: var(--fs-sm); line-height: 1.55; }
.card-hover { transition: border-color var(--t-med) var(--ease), box-shadow var(--t-med) var(--ease); }
.card-hover:hover { border-color: var(--line-strong); box-shadow: var(--sh-md); }
.card-flat { background: var(--surface-2); border-color: transparent; }
.card-accent { border-color: var(--teal-200); }
.card-accent::before {
  content: "";
  display: block;
  width: 28px;
  height: 3px;
  border-radius: 2px;
  background: var(--teal);
}
.card .card-foot { margin-top: auto; padding-top: var(--s-3); border-top: 1px solid var(--line); font-size: var(--fs-sm); }

.dark .card { background: var(--navy-700); border-color: var(--navy-line); }
.dark .card p { color: var(--navy-fg-muted); }
.dark .card .card-foot { border-top-color: var(--navy-line); }

/* Icon plate. Inline SVG only, never an emoji. */
.icon {
  width: 40px;
  height: 40px;
  border-radius: var(--r-sm);
  display: grid;
  place-items: center;
  background: var(--teal-050);
  color: var(--teal-800);
}
.icon svg { width: 20px; height: 20px; }
.dark .icon { background: rgba(0, 194, 168, 0.14); color: var(--teal-200); }

/* --------------------------------------------------------------------------
   5b. SCREENSHOT CAPTIONS
   Owned here, not per page. Every product screenshot carries a "demo shop
   data" caption (copy deck section 8), so the caption is real reading copy
   and has to clear AA. The compound selector is deliberate: it outranks the
   page level `.shot figcaption` rules, so a page that has not been cleaned up
   yet still renders an accessible caption. Page agents: delete your local
   `.shot figcaption` font-size and color declarations, they are redundant.
   -------------------------------------------------------------------------- */
figure.shot figcaption,
figure.shot .cap,
.shot-frame + figcaption {
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--muted-2);
}
.dark figure.shot figcaption,
.dark figure.shot .cap { color: var(--navy-fg-muted); }

/* --------------------------------------------------------------------------
   6. BADGES
   -------------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  letter-spacing: 0.02em;
  line-height: 1.4;
  white-space: nowrap;
}
/* A badge inside a flex column card must hug its text, not stretch. */
.card > .badge, .stack > .badge { align-self: flex-start; }
.badge-teal { background: var(--teal-050); border-color: var(--teal-100); color: var(--teal-800); }
/* --success itself measured 3.06:1 on --success-bg at 13px, which is not
   large text. --success-fg is the accessible pairing. */
.badge-live { background: var(--success-bg); border-color: #BFE8D7; color: var(--success-fg); }
.badge-roadmap { background: var(--rolling-bg); border-color: #F0DDBB; color: var(--rolling); }
.badge-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.dark .badge { background: rgba(255, 255, 255, 0.06); border-color: var(--navy-line); color: var(--navy-fg-muted); }
.dark .badge-teal { background: rgba(0, 194, 168, 0.12); border-color: rgba(0, 194, 168, 0.3); color: var(--teal-200); }

/* --------------------------------------------------------------------------
   7. NAVY BAND
   -------------------------------------------------------------------------- */
.dark {
  background: var(--navy);
  color: var(--navy-fg-muted);
}
.dark h1, .dark h2, .dark h3, .dark h4 { color: var(--navy-fg); }
.dark p { color: var(--navy-fg-muted); }
.dark a { color: var(--teal-200); }
.dark a:hover { color: #FFFFFF; }
.dark .eyebrow { color: var(--teal-200); }
.dark .lead { color: #CBD5E1; }
.dark .muted { color: var(--navy-fg-muted); }
.dark + .section { border-top: 0; }
.section.dark + .section.dark { border-top: 1px solid var(--navy-line); }

/* Conversion strip between content blocks. Moved out of how-it-works.html so
   there is exactly one definition of it. */
.cta-strip {
  display: grid;
  gap: var(--s-4);
  align-items: center;
  margin-top: clamp(28px, 4vw, 44px);
  padding: var(--s-6);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.cta-strip p { margin: 0; color: var(--ink-2); font-size: var(--fs-base); font-weight: var(--fw-med); }
@media (min-width: 760px) { .cta-strip { grid-template-columns: 1fr auto; } }

/* ---- Panels inside a navy band inherit the band's text colours ----
   The CTA strip paragraph measured 1.60:1 because `.cta-strip p` set the light
   theme body colour and the panel behind it is navy. Fixing the one page would
   have left the trap armed for the next page that drops a card or a strip into
   a dark section, so the inheritance is stated once, here, as a rule about
   containers rather than about that one paragraph.

   Specificity note: every selector below is at least two classes plus a type,
   so it outranks any single class page level rule regardless of source order.
   That is what stops the bug recurring. */
.dark .cta-strip,
section.dark .cta-strip,
.footer .cta-strip {
  background: var(--navy-700);
  border-color: var(--navy-line);
}
.dark .cta-strip p,
.dark .cta-strip li,
.dark .cta-strip .small,
.dark .cta-strip .muted,
.dark .card p,
.dark .card li,
.dark .panel p,
section.dark .cta-strip p,
section.dark .card p {
  color: var(--navy-fg-muted);
}
.dark .cta-strip h2,
.dark .cta-strip h3,
.dark .cta-strip h4,
.dark .cta-strip strong,
.dark .cta-strip .lead,
section.dark .cta-strip h2,
section.dark .cta-strip h3 {
  color: var(--navy-fg);
}
.dark .cta-strip a:not(.btn),
section.dark .cta-strip a:not(.btn) { color: var(--teal-200); }

/* --------------------------------------------------------------------------
   8. FORM CONTROLS
   -------------------------------------------------------------------------- */
.field { display: grid; gap: 6px; }
.field > .label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  color: var(--ink);
}
/* Hints and errors sit under a form control and are read while the user is
   deciding what to type. They are reading copy, not decoration, so they take
   the small step (16px on a phone) rather than the incidental step. */
.field .hint { font-size: var(--fs-sm); color: var(--muted); line-height: 1.45; }
.req { color: var(--teal-700); }
.opt { font-weight: var(--fw-med); color: var(--muted); }

input[type="text"], input[type="tel"], input[type="email"], input[type="number"], select, textarea {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  color: var(--ink);
  font: inherit;
  font-size: var(--fs-base);
  /* 16px minimum stops iOS zooming the page on focus. */
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
textarea { min-height: 96px; resize: vertical; line-height: 1.5; }
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%236B7280' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 18px;
  padding-right: 38px;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--teal-600);
  box-shadow: 0 0 0 3px rgba(0, 194, 168, 0.18);
}
input::placeholder, textarea::placeholder { color: var(--muted-2); }
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(180, 35, 24, 0.12);
}
.err {
  display: none;
  font-size: var(--fs-sm);
  font-weight: var(--fw-med);
  color: var(--danger);
}
.field.has-error .err { display: block; }

/* Chip choices, used for the multi select steps of the demo form. */
.chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.chip { position: relative; }
.chip input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.chip span {
  display: inline-flex;
  align-items: center;
  min-height: 44px;   /* full touch target, chips are the answer control */
  padding: 10px 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-med);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.chip input:checked + span {
  border-color: var(--teal-600);
  background: var(--teal-050);
  color: var(--teal-800);
}
.chip input:focus-visible + span { outline: 2px solid var(--teal-700); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   9. NAV, DRAWER, STICKY BAR, MODAL
   -------------------------------------------------------------------------- */
.nav {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  background: var(--bg);
  border-bottom: 1px solid transparent;
  transition: border-color var(--t-med) var(--ease), background var(--t-med) var(--ease);
}
.nav.is-stuck { border-bottom-color: var(--line); background: rgba(248, 250, 252, 0.94); }
.nav-inner { display: flex; align-items: center; gap: var(--s-4); height: var(--nav-h); }

.logo {
  display: inline-flex;
  align-items: center;
  min-height: 44px;   /* the wordmark is a home link, so it is a tap target */
  gap: 9px;
  color: var(--ink);
  font-size: 1.2rem;
  font-weight: var(--fw-bold);
  letter-spacing: -0.03em;
}
.logo:hover { color: var(--ink); text-decoration: none; }
.logo .mark { width: 26px; height: 26px; flex: none; }
.dark .logo { color: var(--navy-fg); }
.dark .logo:hover { color: var(--navy-fg); }

.nav-links { display: none; margin-left: auto; align-items: center; gap: var(--s-5); }
@media (min-width: 1120px) { .nav-links { gap: var(--s-6); } }
@media (min-width: 900px) { .nav-links { display: flex; } }
.nav-links a {
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-med);
}
.nav-links a:hover { color: var(--ink); text-decoration: none; }
.nav-links a[aria-current="page"] { color: var(--ink); font-weight: var(--fw-semi); }

.nav-cta { margin-left: auto; display: none; }
@media (min-width: 900px) { .nav-cta { display: inline-flex; margin-left: var(--s-5); } }

.burger {
  margin-left: auto;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--ink);
  cursor: pointer;
}
@media (min-width: 900px) { .burger { display: none; } }
.burger svg { width: 20px; height: 20px; }
.burger .ico-close { display: none; }
.burger[aria-expanded="true"] .ico-open { display: none; }
.burger[aria-expanded="true"] .ico-close { display: block; }

.drawer {
  position: fixed;
  inset: var(--nav-h) 0 0 auto;
  width: min(340px, 86vw);
  z-index: var(--z-drawer);
  background: var(--surface);
  border-left: 1px solid var(--line);
  box-shadow: var(--sh-lg);
  padding: var(--s-6) var(--s-6) calc(var(--s-8) + env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
  transform: translateX(100%);
  visibility: hidden;
  /* Visibility flips with a zero length transition, delayed on the way out so
     the slide still reads. Putting visibility in the timed list would make it
     compute as hidden for the first frame, and a hidden element cannot be
     focused, which breaks the drawer focus trap. */
  transition: transform var(--t-med) var(--ease), visibility 0s linear var(--t-med);
}
.drawer.is-open {
  transform: none;
  visibility: visible;
  transition: transform var(--t-med) var(--ease), visibility 0s linear 0s;
}
@media (min-width: 900px) { .drawer, .drawer-scrim { display: none; } }
.drawer a { display: block; padding: 13px 0; color: var(--ink); font-size: var(--fs-md); font-weight: var(--fw-semi); border-bottom: 1px solid var(--line); }
.drawer a:hover { color: var(--teal-800); text-decoration: none; }
.drawer .btn { margin-top: var(--s-6); }
.drawer .drawer-foot { margin-top: var(--s-6); font-size: var(--fs-sm); color: var(--muted); }
/* inline-block, not inline: an inline link cannot take a min-height, which is
   why the drawer's WhatsApp and email links measured 17px tall. */
.drawer .drawer-foot a { display: inline-block; min-height: 44px; padding: 11px 0; border: 0; font-size: inherit; font-weight: var(--fw-med); color: var(--teal-700); }

.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-drawer) - 1);
  background: rgba(8, 17, 31, 0.4);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t-med) var(--ease), visibility 0s linear var(--t-med);
}
.drawer-scrim.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--t-med) var(--ease), visibility 0s linear 0s;
}

.stickybar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-stickybar);
  display: flex;
  gap: var(--s-2);
  align-items: center;
  padding: 10px var(--s-4) calc(10px + env(safe-area-inset-bottom, 0px));
  background: rgba(255, 255, 255, 0.97);
  border-top: 1px solid var(--line);
}
@media (min-width: 768px) { .stickybar { display: none; } }
.stickybar .btn { flex: 1 1 auto; min-height: 44px; }
.stickybar .btn-ghost { flex: 0 0 auto; padding-inline: 14px; }

/* Modal. Uses <dialog>, so ::backdrop handles the scrim. */
dialog.modal {
  width: min(560px, calc(100vw - 24px));
  max-height: min(88vh, 760px);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink-2);
  box-shadow: var(--sh-lg);
  overflow: hidden;
}
dialog.modal::backdrop { background: rgba(8, 17, 31, 0.55); }
dialog.modal:not([open]) { display: none; }
.modal-head {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-5) var(--s-6) var(--s-4);
  border-bottom: 1px solid var(--line);
}
.modal-head h2 { font-size: var(--fs-h3); }
.modal-head p { font-size: var(--fs-sm); color: var(--muted); margin-top: 4px; }
.modal-close {
  margin-left: auto;
  width: 44px;    /* standalone control, so it takes a full touch target */
  height: 44px;
  flex: none;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--muted);
  cursor: pointer;
}
.modal-close:hover { color: var(--ink); border-color: var(--line-strong); }
.modal-close svg { width: 16px; height: 16px; }
.modal-body { padding: var(--s-5) var(--s-6); overflow-y: auto; max-height: 58vh; }
.modal-foot {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-6) calc(var(--s-5) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line);
  background: var(--surface-2);
}
.modal-foot .spacer { margin-left: auto; }

/* The demo form is five steps and six fields deep. On a phone a centred box
   with an inner scroll area is a cramped, easy to abandon experience, so below
   640px the dialog becomes a full height sheet: the head and the foot stay put
   and only the field area scrolls, using the whole screen. */
@media (max-width: 639px) {
  dialog.modal {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    border: 0;
    border-radius: 0;
  }
  dialog.modal[open] { display: flex; flex-direction: column; }
  dialog.modal > form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
  .modal-body { flex: 1 1 auto; min-height: 0; max-height: none; }
  .modal-head, .modal-body, .modal-foot { padding-inline: var(--s-5); }
  /* One control per row, nothing side by side, nothing cramped. */
  .step.is-active { gap: var(--s-5); }
  .chips { gap: 10px; }
}

.progress { display: flex; align-items: center; gap: 6px; margin-bottom: var(--s-5); }
.progress .dot { height: 4px; flex: 1; border-radius: 2px; background: var(--surface-3); }
.progress .dot.is-done { background: var(--teal); }
.progress .dot.is-now { background: var(--navy); }
.step { display: none; }
.step.is-active { display: grid; gap: var(--s-4); }
.step-title { font-size: var(--fs-h4); font-weight: var(--fw-bold); color: var(--ink); }
.step-count { font-size: var(--fs-xs); font-weight: var(--fw-semi); letter-spacing: var(--ls-wide); text-transform: uppercase; color: var(--muted); }
.form-status { font-size: var(--fs-sm); color: var(--muted); }
.form-status.is-error { color: var(--danger); }

/* Handoff panel. Shown when the site cannot post the request itself. It is a
   warning colour, not a success colour, because at that point nothing has been
   sent. The action inside it is a real anchor the user taps, never a scripted
   window.open, so no popup blocker can swallow the lead. */
.handoff {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid #F0DDBB;
  border-radius: var(--r-md);
  background: var(--rolling-bg);
}
.handoff .handoff-title { font-weight: var(--fw-semi); color: var(--rolling); font-size: var(--fs-base); }
.handoff p { font-size: var(--fs-sm); color: var(--ink-2); }
.handoff .btn { width: 100%; }
.step .icon.icon-warn { background: #F7E5C4; color: var(--rolling); }

/* --------------------------------------------------------------------------
   10. FOOTER
   -------------------------------------------------------------------------- */
.footer { background: var(--navy); color: var(--navy-fg-muted); padding-block: clamp(40px, 6vw, 72px) var(--s-8); }
.footer-grid { display: grid; gap: var(--s-8); }
@media (min-width: 720px) { .footer-grid { grid-template-columns: 1.4fr 1fr 1fr 1.2fr; gap: var(--s-6); } }
.footer h3 {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--navy-fg-muted);
  margin-bottom: var(--s-4);
}
.footer li + li { margin-top: 2px; }
/* Footer links measured 17px tall on a 393px phone because an inline <a> takes
   no vertical padding. inline-block plus padding-block gives a real 44px
   target without changing how the column reads. */
.footer li a, .footer .contact a {
  display: inline-block;
  min-height: 44px;
  padding-block: 11px;
  color: var(--navy-fg);
  font-size: var(--fs-sm);
  font-weight: var(--fw-med);
  line-height: 1.35;
}
.footer li a:hover, .footer .contact a:hover { color: var(--teal-200); text-decoration: none; }
/* The footer CTA is a real action, so it gets the full 44px too. .btn-sm on
   its own is 40px. */
.footer .btn { min-height: 44px; }
.footer .blurb { font-size: var(--fs-sm); max-width: 34ch; margin-top: var(--s-4); }
.footer-base {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-6);
  justify-content: space-between;
  align-items: center;
  margin-top: var(--s-9);
  padding-top: var(--s-5);
  border-top: 1px solid var(--navy-line);
  font-size: var(--fs-xs);
  color: var(--navy-fg-muted);
}

/* --------------------------------------------------------------------------
   11. UTILITIES AND MOTION
   -------------------------------------------------------------------------- */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.skip-link {
  position: absolute;
  left: var(--s-4);
  top: -60px;
  z-index: 100;
  padding: 10px 16px;
  background: var(--navy);
  color: #FFFFFF;
  border-radius: var(--r-sm);
  transition: top var(--t-fast) var(--ease);
}
.skip-link:focus { top: var(--s-3); color: #FFFFFF; text-decoration: none; }
.hide-mobile { display: none; }
@media (min-width: 768px) { .hide-mobile { display: initial; } .hide-desk { display: none; } }

/* --------------------------------------------------------------------------
   11b. LEGAL PROSE
   Used by privacy.html and terms.html so the legal pages are built from the
   same blocks as the rest of the site rather than hand rolled.
   -------------------------------------------------------------------------- */
.prose { max-width: 68ch; }
.prose > * + * { margin-top: var(--s-4); }
.prose h2 {
  font-size: var(--fs-h3);
  margin-top: var(--s-9);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
}
.prose h3 { font-size: var(--fs-h4); margin-top: var(--s-6); }
.prose p, .prose li { color: var(--ink-2); font-size: var(--fs-base); line-height: var(--lh-body); }
.prose ul { display: grid; gap: var(--s-3); padding-left: 0; }
.prose ul li { position: relative; padding-left: var(--s-5); }
.prose ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 10px;
  height: 2px;
  border-radius: 2px;
  background: var(--teal);
}
.prose .updated { font-size: var(--fs-sm); color: var(--muted); }
.prose dl { display: grid; gap: var(--s-4); }
.prose dt { font-weight: var(--fw-semi); color: var(--ink); }
.prose dd { margin: 4px 0 0; color: var(--ink-2); }

.reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.55s var(--ease), transform 0.55s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* No scroll driven fade, and therefore no pin either: without the fade the
     covering panel would slice the headline in half. Reduced motion gets a
     plain hero that scrolls away like any other section. */
  .hero-copy > div { animation: none !important; opacity: 1 !important; transform: none !important; }
  .hero--bleed { position: static !important; height: auto !important; }
  .hero--bleed .hero-copy { min-height: clamp(560px, 62vh, 680px) !important; height: auto !important; }
  main > section.hero + section { border-radius: 0 !important; box-shadow: none !important; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* The OS being in dark mode must not break a light-only page. */
@media (prefers-color-scheme: dark) {
  :root { color-scheme: light; }
  body { background: var(--bg); color: var(--ink-2); }
  .nav.is-stuck { background: rgba(248, 250, 252, 0.94); }
  .stickybar { background: rgba(255, 255, 255, 0.97); }
}

@media print {
  .nav, .drawer, .drawer-scrim, .stickybar, dialog.modal { display: none !important; }
  body { padding-bottom: 0; background: #FFFFFF; }
}

/* --------------------------------------------------------------------------
   12. v3.1 COMPONENTS (added 2026-07-20)
   Page rhythm, icon tiles, the feature ledger matrix, the layered hero and the
   field notes placeholder. Everything here reuses the tokens above. No new
   colour is introduced that is not derived from --teal or --navy.
   -------------------------------------------------------------------------- */

/* 12a. Band rhythm. A page of identical white sections reads as one long
   scroll with no landmarks, so alternate bands carry the eye. The tint is
   --surface-2, which every text token above was already contrast checked on. */
.section--alt { background: var(--surface-2); }
.section--alt + .section,
.section + .section--alt { border-top: 0; }

/* 12b. Icon tiles. Used by the pillar grid and by "what you are not charged
   extra for". One shape, two densities. */
.tiles {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: 1fr;
}
@media (min-width: 620px)  { .tiles { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .tiles--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1000px) { .tiles--4 { grid-template-columns: repeat(4, 1fr); } }

.tile {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-6);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color var(--t-med) var(--ease), box-shadow var(--t-med) var(--ease),
              transform var(--t-med) var(--ease);
}
.tile:hover { border-color: var(--teal-200); box-shadow: var(--sh-md); transform: translateY(-2px); }
.tile h3 { font-size: var(--fs-h4); letter-spacing: -0.015em; }
.tile p { margin: 0; color: var(--muted); font-size: var(--fs-sm); line-height: 1.55; }
.section--alt .tile { background: var(--surface); }

/* 12c. Feature ledger. A claim with a status badge beside it, grouped by
   theme. Two states only, live and rolling out, and the badge text is the
   claim, so it never renders as decoration. */
.ledger { display: grid; gap: var(--s-8); }
.ledger-group { display: grid; gap: 0; }
.ledger-group > h3 {
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  font-weight: var(--fw-semi);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--line-strong);
}
.lrow {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px var(--s-5);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--line);
}
.lrow dt { font-weight: var(--fw-semi); color: var(--ink); font-size: var(--fs-base); }
.lrow dd { margin: 0; color: var(--muted); font-size: var(--fs-sm); line-height: 1.5; }
/* The status is a second <dd> on the same <dt>, which is what a definition
   list allows. A bare <span> beside dt and dd is invalid and axe flags it. */
.lrow .lstatus { justify-self: start; margin-top: var(--s-2); }
@media (min-width: 760px) {
  .lrow { grid-template-columns: 15rem 1fr 10.5rem; align-items: baseline; }
  .lrow .lstatus { justify-self: end; margin-top: 0; }
}
.ledger-note { margin-top: var(--s-6); font-size: var(--fs-sm); color: var(--muted); max-width: 84ch; }
.ledger-note strong { color: var(--ink-2); }

/* 12c-ii. Ledger summary. The homepage version: one row per theme, a count,
   and the exceptions called out by name. The full matrix is on features.html
   because that is the page someone opens when they want the detail. */
.ledger-sum { border-top: 1px solid var(--line-strong); }
.lsrow {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px var(--s-5);
  padding: var(--s-5) 0;
  border-bottom: 1px solid var(--line);
}
.lsrow dt { font-weight: var(--fw-semi); color: var(--ink); font-size: var(--fs-md); }
.lsrow dd { margin: 0; color: var(--muted); font-size: var(--fs-sm); line-height: 1.5; }
.lsrow .lstatus { display: flex; flex-wrap: wrap; gap: var(--s-2); }
@media (min-width: 760px) {
  .lsrow { grid-template-columns: 17rem 1fr 13rem; align-items: baseline; }
  .lsrow .lstatus { justify-content: flex-end; }
}

/* 12d. Full bleed hero, pinned at every width (revised 2026-07-21).
   The photograph is the ground and the real product screenshots are
   composited into the laptop and phone screens by composite_hero.py, so
   nothing here invents UI. The copy sits over the calm part of the frame.

   The hero holds still and the page scrolls up over it. Pure position sticky:
   no scroll listener, no scroll hijack, no library. Wheel, trackpad, keyboard,
   scrollbar and Find on page all behave normally, and a visitor who wants past
   the hero can get past it. The sections below simply own a higher layer and
   an opaque background, so they cover it.

   The earlier build pinned only above 980px because the phone layout stacked
   the photograph above the copy and was taller than a phone viewport. It now
   overlays at every width instead, so the behaviour is the same everywhere.
   The trade is that the composited screens are small on a phone: they are
   scene, not something a visitor is meant to read, and the real screenshots
   further down the page are the readable ones. */
.hero--bleed {
  position: sticky;
  top: var(--nav-h);
  height: calc(100svh - var(--nav-h));
  padding: 0;
  background: var(--navy);
  overflow: hidden;
  z-index: 0;
}

/* Every band after the hero rides above it and must be opaque, or the hero
   shows through. A section without a declared background would otherwise be
   transparent over it. */
main > section:not(.hero) { position: relative; z-index: 1; background: var(--bg); }
main > section.section--alt { background: var(--surface-2); }
main > section.dark { background: var(--navy); }
/* The footer is a sibling of main, not a child, so it needs the same layer. */
.footer { position: relative; z-index: 1; }

/* The section that covers the hero reads as a panel sliding over it, not as a
   straight edge cutting the headline in half. Rounded top and an upward
   shadow are the whole trick. */
main > section.hero + section {
  border-top-left-radius: var(--r-2xl);
  border-top-right-radius: var(--r-2xl);
  box-shadow: 0 -30px 60px rgba(8, 17, 31, 0.16);
}

.hero-photo { position: absolute; inset: 0; }
.hero-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Phones crop hard, so hold the laptop screen in frame rather than the
     centre of the plate, which is the pharmacist's shirt. */
  object-position: 62% 50%;
}
/* Phone scrim runs top to bottom because the copy spans the full width. The
   wide scrim below replaces it once the copy moves into the left third. */
.hero-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(8, 17, 31, 0.93) 0%,
    rgba(8, 17, 31, 0.86) 42%,
    rgba(8, 17, 31, 0.62) 72%,
    rgba(8, 17, 31, 0.55) 100%);
}

.hero-copy {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  align-items: center;
  padding-block: var(--s-6);
}
.hero-copy .priceline { border-left-color: var(--teal); }

/* The caption is required on every product screenshot by the copy deck. It
   rides with the photograph, pinned to its bottom corner. */
.hero-photo .cap {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: var(--s-3);
  font-size: var(--fs-xs);
  color: var(--navy-fg-muted);
  z-index: 2;
}

/* A 360px viewport cannot hold the badge, three lines of display type, the
   lead, two buttons, the voice chip and the price line inside one screen.
   The chip and the badge are the two that carry least, so they go first. */
/* Under 768px the sticky action bar is fixed over the bottom of the viewport,
   so the hero has that much less room. Without this the last 64px of the
   photograph, and the screenshot caption sitting in it, are permanently
   hidden behind the bar. */
@media (max-width: 767px) {
  .hero--bleed { height: calc(100svh - var(--nav-h) - var(--stickybar-h)); }
}

@media (max-width: 600px) {
  .hero--bleed .badge { display: none; }
  .hero--bleed .voicechip { display: none; }
  .hero .lead { margin-bottom: var(--s-5); }
  .hero .priceline { font-size: var(--fs-sm); margin-top: var(--s-4); }
  .hero-photo .cap { right: auto; max-width: 78%; }
}

@media (min-width: 980px) {
  .hero-photo img { object-position: 70% 50%; }
  .hero-photo::after {
    background: linear-gradient(100deg,
      rgba(8, 17, 31, 0.94) 0%,
      rgba(8, 17, 31, 0.86) 26%,
      rgba(8, 17, 31, 0.55) 52%,
      rgba(8, 17, 31, 0.08) 72%);
  }
  .hero-copy { padding-block: var(--s-11); }
  .hero-copy > div { max-width: 42ch; }
  .hero-photo .cap {
    left: auto;
    right: var(--gutter);
    bottom: var(--s-4);
    padding: 6px 12px;
    border-radius: var(--r-pill);
    background: rgba(8, 17, 31, 0.72);
  }
}

/* Progressive enhancement, every width. Where scroll driven animation is
   supported the hero copy fades as the panel arrives, so no line is ever cut
   in half. Browsers without it get the plain pin, which already reads. */
@supports (animation-timeline: scroll()) {
  /* Longhands only. The `animation` shorthand resets animation-duration to
     0s, and a scroll driven animation needs it to stay `auto`, so the
     shorthand silently kills the effect. */
  .hero-copy > div {
    animation-name: heroFade;
    animation-duration: auto;
    animation-timing-function: linear;
    animation-fill-mode: both;
    animation-timeline: scroll(root block);
    animation-range: 0 60svh;
  }
  @keyframes heroFade {
    0%   { opacity: 1; transform: none; }
    62%  { opacity: 1; transform: none; }
    100% { opacity: 0; transform: translateY(-24px); }
  }
}

.voicechip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 9px 14px;
  border-radius: var(--r-pill);
  background: rgba(8, 17, 31, 0.86);
  border: 1px solid rgba(0, 194, 168, 0.42);
  color: #FFFFFF;
  font-size: var(--fs-sm);
  font-weight: var(--fw-med);
  line-height: 1.35;
  margin-top: var(--s-5);
}
.voicechip .dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--teal); flex: none;
  animation: pulse 2.4s var(--ease) infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

/* 12e. Field notes. There are no customers to quote yet, so the section
   states that instead of faking it. The slots are built and left empty on
   purpose, and this comment is the reason: filling them needs a real shop. */
.notes-empty {
  display: grid;
  gap: var(--s-5);
  padding: var(--s-8);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  background: var(--surface);
  text-align: left;
}
.notes-empty h3 { font-size: var(--fs-h4); }
.notes-empty p { color: var(--muted); max-width: 60ch; }
.notes-slots { display: grid; gap: var(--s-4); grid-template-columns: 1fr; }
@media (min-width: 760px) { .notes-slots { grid-template-columns: repeat(3, 1fr); } }
.notes-slot {
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--muted-2);
  font-size: var(--fs-sm);
  line-height: 1.5;
}
.notes-slot .who {
  display: flex; align-items: center; gap: var(--s-3);
  margin-bottom: var(--s-3);
}
.notes-slot .av {
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--surface-3); flex: none;
}
.notes-slot .ln {
  height: 9px; border-radius: 4px; background: var(--surface-3);
  margin-bottom: 9px;
}
.notes-slot .ln.short { width: 58%; }
