/* ==========================================================================
   MD Diagnostics & Heart Centre
   Design system — "the trace"
   Signature: the ECG pulse, drawn from the logo, used as the page's
   structural rule (dividers, hero trace, card hover).
   ========================================================================== */

/* ---------- tokens ---------- */
:root {
  /* red family — sampled from the logo mark */
  --red-600: #e5121e;
  --red-700: #c10d18;
  --red-800: #8e070f;
  --red-900: #4e0409;
  --red-100: #ffe1e2;
  --red-50: #fff3f3;

  /* the wordmark blue — secondary, keeps the page off monochrome */
  --navy-700: #1b3a6b;
  --navy-900: #0e1f3c;

  --ink: #16181d;
  --slate: #5b6070;
  --line: #e9e1df;
  --line-soft: #f2ecea;
  --paper: #fbf8f7;
  --white: #fff;

  --shadow-sm: 0 1px 2px rgba(22, 24, 29, .05), 0 4px 12px rgba(22, 24, 29, .04);
  --shadow-md: 0 2px 4px rgba(22, 24, 29, .05), 0 12px 32px rgba(78, 4, 9, .08);
  --shadow-lg: 0 24px 60px rgba(78, 4, 9, .14);

  --r-sm: 6px;
  --r-md: 12px;
  --r-lg: 20px;
  --r-xl: 28px;

  --shell: 1240px;
  --gut: clamp(20px, 5vw, 48px);

  /* Three faces, three jobs.
     Archivo — a grotesque with more grip than Helvetica; tightens well at
       display sizes without going gappy.
     Instrument Sans — same grotesque genus, warmer texture, set for reading.
     IBM Plex Mono — the data face. Package codes, prices, parameter counts,
       department codes and turnaround times come off requisition slips and
       analyser printouts, so they are set as data rather than as marketing. */
  --f-display: Archivo, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --f-body: "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --f-label: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --ease: cubic-bezier(.2, .7, .3, 1);
  /* overshoots slightly — used only where something should feel physically
     seated (button press release, filter chips, copy confirmation) */
  --ease-seat: cubic-bezier(.34, 1.4, .5, 1);
}

*,
*::before,
*::after { box-sizing: border-box; }

/* `clip` (with `hidden` as the older fallback) stops the off-canvas mobile
   drawer from widening the document's scrollable area. */
html {
  -webkit-text-size-adjust: 100%;
  /* Chrome on Android paints a translucent blue box over whatever you tap.
     It is the browser's stand-in for a press state; every tappable thing here
     has its own, so the box is only ever a rectangle in the wrong colour
     drawn across a rounded pill. Keyboard focus is unaffected — that runs on
     :focus-visible, further down. */
  -webkit-tap-highlight-color: transparent;
  scroll-behavior: smooth;
  overflow-x: hidden;
  overflow-x: clip;
  /* the header is sticky, so an anchored heading would otherwise land
     underneath it — services.html#cardiology and friends */
  scroll-padding-top: 104px;
}
@media (max-width: 720px) { html { scroll-padding-top: 84px; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  overflow-x: clip;
}

/* height:auto keeps the intrinsic-size attributes from becoming a fixed height.
   Anything that needs a fixed box (tiles, hero, portraits) overrides it below. */
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }

/* Archivo sets loose at display sizes — the negative tracking below is what
   keeps big headings from looking gappy. */
h1, h2, h3, h4 {
  font-family: var(--f-display);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.03em;
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: clamp(2.4rem, 5.6vw, 4.1rem); letter-spacing: -.038em; }
h2 { font-size: clamp(1.95rem, 4.2vw, 3.05rem); }
h3 { font-size: clamp(1.2rem, 2vw, 1.5rem); letter-spacing: -.018em; }
h4 { font-size: 1.06rem; letter-spacing: -.01em; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

:focus-visible {
  outline: 3px solid var(--red-600);
  outline-offset: 3px;
  border-radius: 3px;
}

::selection { background: var(--red-600); color: #fff; }

/* ---------- layout primitives ---------- */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gut);
}

.section { padding-block: clamp(44px, 6.2vw, 80px); }
.section--tight { padding-block: clamp(32px, 4.2vw, 54px); }
.section--flush-top { padding-top: 0; }
.section--flush-bottom { padding-bottom: 0; }
/* the promo band leads the page: it sits closer under the header than a
   normal section would, and lets the hero's own top padding set the gap
   below it rather than adding a second one */
.section--promo { padding-block: clamp(22px, 2.6vw, 38px) 0; }

.section--dark {
  background: var(--red-900);
  color: #fff;
  position: relative;
  overflow: hidden;
}
.section--dark::before {
  content: "";
  position: absolute;
  inset: -40% 20% auto -20%;
  height: 130%;
  background: radial-gradient(50% 50% at 30% 40%, rgba(229, 18, 30, .5), transparent 70%);
  pointer-events: none;
}
.section--dark > * { position: relative; }
.section--dark p { color: rgba(255, 255, 255, .76); }

.section--paper-alt { background: var(--white); }

/* ---------- the eyebrow: department codes, not decorative numbering ---------- */
.eyebrow {
  font-family: var(--f-label);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--red-700);
  display: inline-flex;
  align-items: center;
  gap: .6em;
  margin-bottom: 1.1rem;
}
.eyebrow::before {
  content: "";
  width: 26px;
  height: 2px;
  background: var(--red-600);
}
.section--dark .eyebrow { color: #ff9ba0; }
.section--dark .eyebrow::before { background: #ff9ba0; }

.lede {
  font-size: clamp(1.03rem, 1.5vw, 1.19rem);
  color: var(--slate);
  max-width: 62ch;
}
.section--dark .lede { color: rgba(255, 255, 255, .78); }

.head {
  max-width: 720px;
  margin-bottom: clamp(24px, 3.2vw, 38px);
}
.head--center {
  margin-inline: auto;
  text-align: center;
}
.head--center .eyebrow { justify-content: center; }
.head--center .lede { margin-inline: auto; }

.head--split {
  max-width: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 26rem);
  gap: 32px;
  align-items: end;
}
@media (max-width: 820px) {
  .head--split { grid-template-columns: 1fr; align-items: start; }
}

/* ==========================================================================
   SIGNATURE — the pulse
   ========================================================================== */
.pulse-rule {
  display: flex;
  align-items: center;
  gap: 0;
  width: 100%;
}
.pulse-rule::before,
.pulse-rule::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}
.pulse-rule svg { flex: none; width: 96px; height: 26px; display: block; }
.pulse-rule path {
  fill: none;
  stroke: var(--red-600);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.section--dark .pulse-rule::before,
.section--dark .pulse-rule::after { background: rgba(255, 255, 255, .16); }
.section--dark .pulse-rule path { stroke: #ff5a63; }

/* a divider between two sections shouldn't float in 200px of nothing */
.pulse-band { margin-top: clamp(-40px, -3.6vw, -24px); }
.pulse-band + .section { padding-top: clamp(30px, 4vw, 48px); }

/* hero trace */
.trace { display: block; width: 100%; height: 100%; }
.trace path {
  fill: none;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.trace .trace__line {
  stroke: var(--red-600);
  stroke-dasharray: var(--len, 2000);
  stroke-dashoffset: var(--len, 2000);
  animation: trace-draw 5s var(--ease) infinite;
}
.trace .trace__ghost { stroke: rgba(229, 18, 30, .16); }
.trace__dot {
  fill: var(--red-600);
  filter: drop-shadow(0 0 6px rgba(229, 18, 30, .9));
}
@keyframes trace-draw {
  0% { stroke-dashoffset: var(--len, 2000); }
  55%, 100% { stroke-dashoffset: 0; }
}

/* ---------- the trace, given a job ----------
   The header's bottom edge is a live readout. Its flat baseline is the rule
   under the header; the red portion is how far through the page you are, so
   the motif that decorates the hero also tells you where you stand. The
   waveform is generated in JS to the real header width, so beats keep their
   shape instead of stretching. */
.scroll-trace {
  position: absolute;
  inset: auto 0 0 0;
  height: 12px;
  pointer-events: none;
  z-index: 2;
}
.scroll-trace svg { display: block; width: 100%; height: 100%; overflow: visible; }
.scroll-trace path {
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.scroll-trace .st__ghost { stroke: var(--line); }
.scroll-trace .st__live {
  stroke: var(--red-600);
  filter: drop-shadow(0 0 3px rgba(229, 18, 30, .5));
}
/* until JS measures and draws, the plain rule stands in */
.site-header:not(.has-trace) { border-bottom: 1px solid var(--line); }

/* ==========================================================================
   BUTTONS
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6em;
  font-family: var(--f-body);
  font-size: .97rem;
  font-weight: 600;
  letter-spacing: -.005em;
  padding: 14px 24px;
  border-radius: 999px;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: transform .18s var(--ease), background .18s var(--ease),
              color .18s var(--ease), border-color .18s var(--ease), box-shadow .18s var(--ease);
  white-space: nowrap;
}
/* lift on hover, then actually seat under the finger on press — the press
   state is what makes a tap feel acknowledged on a phone, where there is no
   hover to lean on */
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0) scale(.97); transition-duration: .06s; }
.btn svg { flex: none; transition: transform .18s var(--ease); }
.btn:hover svg { transform: scale(1.08); }

.btn--primary { background: var(--red-600); color: #fff; box-shadow: 0 6px 20px rgba(229, 18, 30, .28); }
.btn--primary:hover { background: var(--red-700); box-shadow: 0 12px 28px rgba(229, 18, 30, .34); }

.btn--wa { background: #16a34a; color: #fff; box-shadow: 0 6px 20px rgba(22, 163, 74, .26); }
.btn--wa:hover { background: #128a3f; box-shadow: 0 12px 28px rgba(22, 163, 74, .32); }

.btn--ghost { border-color: var(--line); background: var(--white); color: var(--ink); }
.btn--ghost:hover { border-color: var(--ink); }

.btn--onDark { border-color: rgba(255, 255, 255, .3); color: #fff; background: transparent; }
.btn--onDark:hover { background: #fff; color: var(--red-900); border-color: #fff; }

.btn--sm { padding: 10px 18px; font-size: .88rem; }
.btn--lg { padding: 17px 30px; font-size: 1.03rem; }
.btn--block { width: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }

/* text link with an arrow */
.tlink {
  font-weight: 600;
  font-size: .95rem;
  display: inline-flex;
  align-items: center;
  gap: .45em;
  color: var(--red-700);
  border-bottom: 1.5px solid transparent;
  transition: border-color .18s var(--ease), gap .18s var(--ease);
}
.tlink:hover { border-color: currentColor; gap: .8em; }
.section--dark .tlink { color: #ff9ba0; }

/* ==========================================================================
   HEADER
   ========================================================================== */
.topbar {
  background: var(--red-900);
  color: rgba(255, 255, 255, .82);
  font-size: .82rem;
}
.topbar .shell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 40px;
  padding-block: 6px;
}
.topbar__list { display: flex; gap: 22px; flex-wrap: wrap; align-items: center; }
.topbar a { display: inline-flex; align-items: center; gap: .45em; transition: color .18s; }
.topbar a:hover { color: #fff; }
.topbar__note { font-family: var(--f-label); font-size: .74rem; letter-spacing: .04em; text-transform: uppercase; color: #ff9ba0; }
@media (max-width: 880px) { .topbar { display: none; } }

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--paper);
  transition: box-shadow .2s var(--ease);
}
/* The blur only applies at desktop widths. A backdrop-filter makes the header
   the containing block for position:fixed descendants, which would trap the
   off-canvas mobile drawer inside the header's own box. */
@media (min-width: 1151px) {
  .site-header {
    background: rgba(251, 248, 247, .86);
    backdrop-filter: blur(14px);
  }
}
.site-header.is-stuck { box-shadow: var(--shadow-sm); }
.site-header .shell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 76px;
  padding-block: 10px;
}

.brand { display: flex; align-items: center; gap: 11px; flex: none; }
.brand img { height: 46px; width: auto; transition: height .2s var(--ease); }
.site-header.is-stuck .brand img { height: 40px; }
.brand__text { display: grid; line-height: 1.05; }
.brand__text strong {
  font-family: var(--f-display);
  font-size: 1.22rem;
  font-weight: 700;
  letter-spacing: -.035em;
  color: var(--navy-900);
}
.brand__text em {
  font-style: normal;
  font-family: var(--f-label);
  font-size: .64rem;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--red-600);
}
@media (max-width: 420px) {
  .brand img { height: 40px; }
  .brand__text strong { font-size: 1.06rem; }
  .brand__text em { font-size: .58rem; letter-spacing: .06em; }
}

.nav {
  display: flex;
  align-items: center;
  gap: 4px;
  position: relative;
  /* the blob palette — the ramp plus one navy, so the burst is red with a
     single cool fleck in it rather than nine identical dots */
  --goo-1: var(--red-600);
  --goo-2: var(--red-700);
  --goo-3: #ff4a52;
  --goo-4: var(--navy-700);
}
.nav a {
  position: relative;
  z-index: 1;
  padding: 9px 11px;
  border-radius: 999px;
  font-size: .92rem;
  font-weight: 500;
  color: var(--slate);
  transition: color .18s var(--ease);
  white-space: nowrap;
}
/* the pill grows into place rather than blinking on — cheap to render and it
   makes a 9-item nav feel less like a wall of text */
.nav a::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 999px;
  background: var(--line-soft);
  opacity: 0;
  transform: scale(.82);
  transition: opacity .18s var(--ease), transform .24s var(--ease-seat);
}
.nav a:hover { color: var(--ink); }
.nav a:hover::before { opacity: 1; transform: scale(1); }
.nav a[aria-current="page"] { color: var(--red-700); font-weight: 600; }
.nav a[aria-current="page"]::before { opacity: 1; transform: scale(1); background: var(--red-50); }

/* The accounts ride in the side rail on a desktop, and the rail is not
   rendered below 900px — so the drawer carries them on a phone instead. Kept
   out of the header row, where the nav is a line of page links and two icons
   would read as two more of them. */
.nav__social { display: none; }

/* ---- the Doctors submenu ----
   One nav item that opens. Up top it is a panel under the trigger, driven by
   :hover and :focus-within so a keyboard reaches it with no script at all; in
   the drawer it is an indented list under the link, driven by the chevron
   button. The two live in non-overlapping media blocks rather than fighting
   each other in the cascade — the drawer half sits with the rest of the
   drawer, further down. */
/* The trigger is a button, not a link: there is no doctors index to go to any
   more, only the three profiles under it. It has to carry the nav link's look
   by hand — `.nav a` cannot reach a <button>, and widening every one of those
   selectors to :is(a, button) would raise their specificity against the
   submenu rules that sit below them. */
.nav__trigger {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: .32em;
  padding: 9px 11px;
  background: none;
  border: 0;
  border-radius: 999px;
  font-family: var(--f-body);
  font-size: .92rem;
  font-weight: 500;
  color: var(--slate);
  cursor: pointer;
  white-space: nowrap;
  transition: color .18s var(--ease);
}
.nav__trigger::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 999px;
  background: var(--line-soft);
  opacity: 0;
  transform: scale(.82);
  transition: opacity .18s var(--ease), transform .24s var(--ease-seat);
}
.nav__trigger:hover { color: var(--ink); }
.nav__trigger:hover::before { opacity: 1; transform: scale(1); }
/* aria-current="true", not "page" — the trigger is the current *section*, and
   there is no page behind it to be on */
.nav__trigger[aria-current] { color: var(--red-700); font-weight: 600; }
.nav__trigger[aria-current]::before { opacity: 1; transform: scale(1); background: var(--red-50); }
.nav__chev { width: 13px; height: 13px; flex: none; }
.nav__sub a {
  display: grid;
  gap: 1px;
  white-space: normal;
}
.nav__sub a::before { border-radius: var(--r-sm); }
.nav__sub a strong { font-size: .93rem; font-weight: 600; color: inherit; }
.nav__sub a span {
  font-family: var(--f-label);
  font-size: .61rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--slate);
}
.nav__sub a:hover strong { color: var(--red-700); }
.nav__sub a[aria-current="page"] span { color: var(--red-600); }
/* the goo hides the flat pill on the current link, since the blob is standing
   in for it — but the blob only ever tracks a top-level item, so the marker on
   the open doctor has to come back */
.nav.has-goo .nav__sub a[aria-current="page"]::before { opacity: 1; transform: scale(1); }

@media (min-width: 1151px) {
  /* over the scroll trace, which is also a child of the header */
  .nav__group { position: relative; z-index: 3; }
  .nav__chev { transition: transform .2s var(--ease); }
  .nav__group:hover .nav__chev,
  .nav__group:focus-within .nav__chev,
  .nav__group.is-open .nav__chev { transform: rotate(180deg); }
  .nav__sub {
    position: absolute;
    top: calc(100% + 11px);
    left: 50%;
    transform: translate(-50%, -6px);
    width: 264px;
    display: grid;
    gap: 2px;
    padding: 8px;
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-md);
    opacity: 0;
    visibility: hidden;
    transition: opacity .18s var(--ease), transform .22s var(--ease-seat), visibility .18s var(--ease);
  }
  /* the pointer has to cross the gap between trigger and panel to reach the
     list; without this bridge the hover drops halfway and the panel shuts */
  .nav__sub::before { content: ""; position: absolute; inset: -13px 0 auto 0; height: 13px; }
  .nav__group:hover > .nav__sub,
  .nav__group:focus-within > .nav__sub,
  .nav__group.is-open > .nav__sub {
    opacity: 1;
    visibility: visible;
    transform: translate(-50%, 0);
  }
  .nav__sub a { padding: 9px 12px; border-radius: var(--r-sm); }
}

/* ---------- the gooey nav ----------
   After React Bits' GooeyNav. The blobs are welded by an SVG alpha
   threshold rather than the original's blur() + contrast(100) over a black
   backing plate: that trick only vanishes on a dark page, and this header is
   warm off-white and translucent. The threshold also leaves the fill colour
   alone, so the pill stays brand red instead of clamping to pure #f00.
   Everything below is inert until main.js builds the layer, so with
   JavaScript off — or under reduced motion, or in the drawer — the flat
   red-50 pill above is still what marks the current page. */
.goo-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

.nav__goo {
  position: absolute;
  inset: 0;
  z-index: 0;          /* under the links, over the header's background */
  pointer-events: none;
  filter: url(#nav-goo);
}
.nav__pill {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  border-radius: 999px;
  background: var(--goo-1);
  /* duration is set from JS — 0ms when the pill is being placed, the glide
     length when it is travelling */
  transition-property: left, top, width, height;
  transition-timing-function: var(--ease);
  transition-duration: 0ms;
}
.nav__particle,
.nav__dot {
  display: block;
  width: 15px;
  height: 15px;
  border-radius: 999px;
  opacity: 0;
}
.nav__particle {
  position: absolute;
  top: calc(50% - 7.5px);
  left: calc(50% - 7.5px);
  animation: nav-particle var(--time) ease 1 -200ms;
}
.nav__dot {
  background: var(--color);
  animation: nav-dot var(--time) ease 1 -200ms;
}
@keyframes nav-particle {
  0% {
    transform: rotate(0deg) translate(var(--start-x), var(--start-y));
    opacity: 1;
    animation-timing-function: cubic-bezier(.55, 0, 1, .45);
  }
  70% {
    transform: rotate(calc(var(--rotate) * .5))
               translate(calc(var(--end-x) * 1.2), calc(var(--end-y) * 1.2));
    opacity: 1;
    animation-timing-function: ease;
  }
  85% {
    transform: rotate(calc(var(--rotate) * .66)) translate(var(--end-x), var(--end-y));
    opacity: 1;
  }
  100% {
    transform: rotate(calc(var(--rotate) * 1.2))
               translate(calc(var(--end-x) * .5), calc(var(--end-y) * .5));
    opacity: 1;
  }
}
@keyframes nav-dot {
  0%   { transform: scale(0); opacity: 0; animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  25%  { transform: scale(calc(var(--scale) * .25)); }
  38%  { opacity: 1; }
  65%  { transform: scale(var(--scale)); opacity: 1; animation-timing-function: ease; }
  85%  { transform: scale(var(--scale)); opacity: 1; }
  100% { transform: scale(0); opacity: 0; }
}

/* the pill is the page marker now, so the flat one underneath it goes */
.nav.has-goo a[aria-current="page"]::before,
.nav.has-goo .nav__trigger[aria-current]::before { opacity: 0; }
/* is-lit is on whichever link the pill is currently sitting under, which is
   not always the current page — during the glide it is the one you came
   from. It also has to outrank :hover, or the grey hover pill would sit on
   top of the red one for as long as the cursor stayed put after a click. */
/* snaps rather than fades, so the label whitening, the red landing under it
   and the burst are one event — removing the class still fades out, because
   that transition comes from the base .nav a rule */
.nav.has-goo a.is-lit,
.nav.has-goo .nav__trigger.is-lit { color: #fff; transition-duration: 0s; }
.nav.has-goo a.is-lit::before,
.nav.has-goo .nav__trigger.is-lit::before { opacity: 0; }
.nav.is-gliding a:hover::before,
.nav.is-gliding .nav__trigger:hover::before { opacity: 0; }

@media (max-width: 1150px) { .nav__goo { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .nav__pill { transition: none; }
  .nav__particle, .nav__dot { animation: none; }
  .nav a[aria-current="page"]::after { animation: none; }
}

/* The drawer masthead only exists once the nav becomes a panel; in the desktop
   row it would be a logo sitting in the middle of the links. */
.nav__head { display: none; }

/* The marker for the current page in the drawer — one cardiac cycle, beating
   at a resting rate. It is the header's ECG line cut down to a single beat, so
   the two read as the same signature rather than two different ideas. */
@keyframes nav-beat {
  0%, 100% { opacity: .6; transform: translateY(-50%) scaleY(.9); }
  6% { opacity: 1; transform: translateY(-50%) scaleY(1); }
  16% { opacity: .75; transform: translateY(-50%) scaleY(.94); }
  24% { opacity: 1; transform: translateY(-50%) scaleY(1); }
  40% { opacity: .6; transform: translateY(-50%) scaleY(.9); }
}

.header-cta { display: flex; align-items: center; gap: 10px; flex: none; }
/* Call is an icon here, not a labelled button. The number is written out in
   full in the top bar directly above it, so the word "Call now" was captioning
   something the page already says — and at 42px this survives every width down
   to the phone instead of being dropped when space got tight. The label lives
   on aria-label/title for anyone who needs it. */
.header-cta .btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  flex: none;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--white);
  color: var(--ink);
  transition: color .18s var(--ease), border-color .18s var(--ease),
              transform .18s var(--ease), box-shadow .18s var(--ease);
}
.header-cta .btn-icon:hover {
  color: var(--red-600);
  border-color: var(--red-100);
  transform: translateY(-2px);
  box-shadow: var(--shadow-sm);
}
.header-cta .btn-icon:active { transform: translateY(0) scale(.94); transition-duration: .06s; }
/* the fixed bottom bar carries a full-width Call button below this width */
@media (max-width: 720px) { .header-cta .btn-icon { display: none; } }
/* There is no width at which this button is the only WhatsApp on screen: above
   720px the floating bubble is parked bottom-right, and at 720px and below the
   fixed bottom bar takes over. Either one outranks it — both stay put while
   the header scrolls away — so it was simply the third of three, alongside the
   footer's social icon, all opening the same chat.
   The markup is left in place in all nine files; deleting this rule brings it
   back everywhere. */
.header-cta .btn--wa { display: none; }

.nav-toggle {
  display: none;
  width: 46px;
  height: 46px;
  border: 1px solid var(--line);
  background: var(--white);
  border-radius: 12px;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  flex: none;
}
.nav-toggle span {
  display: block;
  width: 19px;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform .25s var(--ease), opacity .2s var(--ease);
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 1150px) {
  .nav-toggle { display: flex; }
  /* The drawer is a child of the header and positioned, so it painted over
     its own close button — the hamburger turned into an X that nothing could
     tap, leaving Escape and a ~30px strip of scrim as the only way out. The
     panel's top padding was always sized to clear this row; it just needed to
     be above the panel rather than under it. */
  .brand,
  .header-cta { position: relative; z-index: 4; }
  /* The panel is nearly the full width of a phone, so a brand left sitting on
     top of it straddles the panel edge — mark on the paper, wordmark on the
     white, a seam through the middle. It steps aside instead and leaves the
     row to the close button; the panel's own top edge stays clean. */
  .brand { transition: opacity .2s var(--ease), visibility .2s var(--ease); }
  .site-header.is-drawer-open .brand { opacity: 0; visibility: hidden; }
  /* The drawer carries its own logo and close button now, so the header row no
     longer has to float above the panel to keep the hamburger tappable. The
     whole cluster — call icon and hamburger both — steps aside while the
     drawer is open, the way the brand does, leaving one close control instead
     of a second X and a call button stranded on top of the panel. */
  .header-cta { transition: opacity .2s var(--ease), visibility .2s var(--ease); }
  .site-header.is-drawer-open .header-cta { opacity: 0; visibility: hidden; }
  /* Same for the two floating things: both outrank the panel on z-index, and
     a WhatsApp pill sitting in the middle of the menu reads as a menu item. */
  .wa-float,
  .social-rail { transition: opacity .2s var(--ease), visibility .2s var(--ease); }
  .site-header.is-drawer-open ~ .wa-float,
  .site-header.is-drawer-open ~ .social-rail { opacity: 0; visibility: hidden; }
  .nav {
    position: fixed;
    inset: 0 0 0 auto;
    /* above the scroll trace, which is also a child of the header and would
       otherwise draw its waveform across the open drawer */
    z-index: 3;
    width: min(340px, 86vw);
    background: var(--white);
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    /* the panel opens with its own masthead at the top, so it no longer has to
       reserve room for the header row sitting above it */
    padding: 0 20px 32px;
    border-left: 1px solid var(--line);
    transform: translateX(100%);
    transition: transform .32s var(--ease);
    overflow-y: auto;
    box-shadow: var(--shadow-lg);
  }
  .nav.is-open { transform: translateX(0); }
  /* the drawer masthead: logo left, close right, hairline underneath. It is
     sticky so the mark stays put while a ten-item list scrolls past it. */
  .nav__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    position: sticky;
    top: 0;
    z-index: 2;
    /* bleeds to the panel edges through the panel's own side padding */
    margin: 0 -20px 12px;
    padding: 14px 16px 14px 20px;
    background: var(--white);
    border-bottom: 1px solid var(--line);
  }
  .nav__brand { display: flex; align-items: center; gap: 10px; min-width: 0; }
  .nav__brand img { width: 40px; height: 40px; flex: none; }
  .nav__brand-text { display: grid; line-height: 1.05; min-width: 0; }
  .nav__brand-text strong {
    font-family: var(--f-display);
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: -.035em;
    color: var(--navy-900);
  }
  .nav__brand-text em {
    font-style: normal;
    font-family: var(--f-label);
    font-size: .58rem;
    font-weight: 500;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--red-600);
  }
  .nav__close {
    width: 40px;
    height: 40px;
    flex: none;
    display: grid;
    place-items: center;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--white);
    color: var(--ink);
    cursor: pointer;
    transition: background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
  }
  .nav__close:hover,
  .nav__close:focus-visible { background: var(--red-600); border-color: var(--red-600); color: var(--white); }
  .nav__close svg { width: 18px; height: 18px; }

  .nav a {
    padding: 14px 16px;
    border-radius: var(--r-md);
    font-size: 1.05rem;
    /* links arrive just behind the panel so the drawer reads as one movement
       instead of a block of text sliding in */
    opacity: 0;
    transform: translateX(16px);
    transition: opacity .28s var(--ease), transform .28s var(--ease), color .18s var(--ease);
  }
  .nav.is-open a {
    opacity: 1;
    transform: none;
    transition-delay: calc(var(--i, 0) * 32ms + 80ms);
  }
  /* Press feedback in place of the tap highlight we just turned off: the pill
     seats immediately on touch. :hover is no help here — on a touchscreen it
     latches after the tap and stays lit on the link you just left. */
  .nav a:active::before { opacity: 1; transform: scale(1); transition-duration: .06s; }
  .nav a:active { color: var(--ink); }

  /* the submenu in the drawer: the trigger takes a full row with the chevron
     at the end of it, and the doctors sit underneath behind a rule so the
     indent reads as "inside Doctors" rather than as three more top-level items */
  .nav__trigger {
    width: 100%;
    justify-content: space-between;
    padding: 14px 16px;
    border-radius: var(--r-md);
    font-size: 1.05rem;
    /* arrives with the links either side of it, see .nav.is-open a */
    opacity: 0;
    transform: translateX(16px);
    transition: opacity .28s var(--ease), transform .28s var(--ease), color .18s var(--ease);
  }
  .nav.is-open .nav__trigger {
    opacity: 1;
    transform: none;
    transition-delay: calc(var(--i, 0) * 32ms + 80ms);
  }
  .nav__trigger:active::before { opacity: 1; transform: scale(1); transition-duration: .06s; }
  .nav__trigger:active { color: var(--ink); }
  .nav__chev { display: block; width: 17px; height: 17px; transition: transform .24s var(--ease); }
  .nav__group.is-open .nav__chev { transform: rotate(180deg); }
  /* the current section carries the same beat the current page does */
  .nav__trigger[aria-current] { padding-left: 56px; }
  .nav__trigger[aria-current]::after {
    content: "";
    position: absolute;
    left: 16px;
    top: 50%;
    width: 30px;
    height: 16px;
    transform: translateY(-50%);
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 18'%3E%3Cpath d='M1 9h8.4l2.6-6.6L16.6 16l3-8 2.6 4H39' fill='none' stroke='%23e5121e' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") left center / contain no-repeat;
    animation: nav-beat 2.8s var(--ease) infinite;
  }
  .nav__sub {
    display: none;
    gap: 0;
    margin: 2px 0 8px 16px;
    padding-left: 10px;
    border-left: 2px solid var(--line);
  }
  .nav__group.is-open > .nav__sub { display: grid; }
  .nav__sub a { padding: 11px 14px; border-radius: var(--r-md); }
  .nav__sub a strong { font-size: .97rem; font-weight: 500; }

  /* Instagram and YouTube, parked at the foot of the drawer. margin-top:auto
     floats them to the bottom edge while the menu is short, and simply lets
     them follow the last link once the list is long enough to scroll. */
  .nav__social {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-top: auto;
    padding-top: 16px;
    border-top: 1px solid var(--line);
  }
  .nav__social-label {
    flex: none;
    margin-right: 6px;
    font-family: var(--f-label);
    font-size: .62rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--slate);
  }
  /* square taps, the mark's own red — the same treatment the rail gives them */
  .nav__social a {
    width: 44px;
    height: 44px;
    flex: none;
    padding: 0;
    display: grid;
    place-items: center;
    font-size: 0;
    color: var(--red-600);
  }
  .nav__social a:active { color: var(--red-700); }
  .nav__social svg { width: 20px; height: 20px; }

  /* the current page carries a beat on its left edge */
  .nav a[aria-current="page"] { padding-left: 56px; }
  .nav a[aria-current="page"]::after {
    content: "";
    position: absolute;
    left: 16px;
    top: 50%;
    width: 30px;
    height: 16px;
    transform: translateY(-50%);
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 18'%3E%3Cpath d='M1 9h8.4l2.6-6.6L16.6 16l3-8 2.6 4H39' fill='none' stroke='%23e5121e' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") left center / contain no-repeat;
    animation: nav-beat 2.8s var(--ease) infinite;
  }
  .nav-scrim {
    position: fixed;
    inset: 0;
    background: rgba(22, 24, 29, .4);
    opacity: 0;
    pointer-events: none;
    transition: opacity .3s var(--ease);
    z-index: 55;
  }
  .nav-scrim.is-open { opacity: 1; pointer-events: auto; }
}
/* This used to push the first link clear of the header row above the panel.
   The panel now starts with its own masthead, which owns that space. */

/* ==========================================================================
   HERO
   ========================================================================== */
.hero {
  position: relative;
  padding-block: clamp(30px, 3.6vw, 52px) clamp(36px, 4.4vw, 62px);
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  top: -30%;
  right: -10%;
  width: 62vw;
  height: 100vh;
  background: radial-gradient(45% 45% at 60% 40%, rgba(229, 18, 30, .1), transparent 70%);
  pointer-events: none;
}
.hero .shell { position: relative; }

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr);
  gap: clamp(26px, 3.6vw, 48px);
  align-items: center;
}
@media (max-width: 940px) { .hero__grid { grid-template-columns: 1fr; } }

.hero h1 { margin-bottom: 20px; }
.hero h1 em {
  font-style: normal;
  color: var(--red-600);
  position: relative;
}
.hero__lede { font-size: clamp(1.05rem, 1.6vw, 1.22rem); color: var(--slate); max-width: 46ch; margin-bottom: 30px; }
.hero__intl {
  display: flex;
  align-items: center;
  gap: 14px;
  max-width: 440px;
  margin-top: 18px;
  padding: 10px 12px;
  border: 1.5px solid var(--red-600);
  border-radius: 999px;
  background: var(--white);
  box-shadow: var(--shadow-md);
  color: var(--ink);
  cursor: pointer;
  transition: background-color .18s var(--ease), box-shadow .18s var(--ease);
}
.hero__intl:hover { background: var(--red-50); box-shadow: var(--shadow-lg); }
.hero__intl-icon {
  flex: none;
  box-sizing: content-box;
  padding: 9px;
  border-radius: 50%;
  background: var(--red-600);
  color: #fff;
}
.hero__intl-text { display: grid; gap: 2px; flex: 1; min-width: 0; }
.hero__intl-label {
  font-family: var(--f-label);
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--red-700);
}
.hero__intl strong { font-family: var(--f-display); font-size: 1.05rem; font-weight: 600; line-height: 1.25; }
/* the card is a link, so it carries a real button at its end — a bare arrow
   read as decoration, not as something to tap */
.hero__intl-cta {
  flex: none;
  padding: 11px 18px;
  border-radius: 999px;
  background: var(--red-600);
  color: #fff;
  font-size: .92rem;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 6px 20px rgba(229, 18, 30, .28);
  transition: transform .18s var(--ease), background .18s var(--ease);
}
.hero__intl:hover .hero__intl-cta { background: var(--red-700); transform: translateX(2px); }
.hero__intl:active .hero__intl-cta { transform: scale(.96); transition-duration: .06s; }
/* on a narrow phone the globe goes so the label and the button both fit on
   one line inside the pill */
@media (max-width: 420px) {
  .hero__intl { padding-left: 22px; gap: 10px; }
  .hero__intl-icon { display: none; }
}

.hero__proof {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  margin-top: 32px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
}
.hero__proof li {
  font-family: var(--f-label);
  font-size: .78rem;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--slate);
  display: flex;
  align-items: center;
  gap: .5em;
}
.hero__proof li::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--red-600);
  flex: none;
}

.hero__media { position: relative; }
.hero__frame {
  position: relative;
  border-radius: var(--r-xl);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  aspect-ratio: 4 / 3.1;
  background: var(--red-900);
}
.hero__frame img { width: 100%; height: 100%; object-fit: cover; }
.hero__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(200deg, rgba(78, 4, 9, .06) 20%, rgba(78, 4, 9, .72));
}
.hero__trace {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 42%;
  height: 78px;
  z-index: 2;
  pointer-events: none;
}
.hero__frame .trace .trace__line { stroke: #ff3b45; }
.hero__frame .trace .trace__ghost { stroke: rgba(255, 255, 255, .18); }
.hero__frame .trace__dot { fill: #fff; }

.hero__badge {
  position: absolute;
  left: 24px;
  bottom: 84px;
  right: 24px;
  z-index: 3;
  color: #fff;
}
.hero__badge strong {
  font-family: var(--f-display);
  font-size: clamp(1.08rem, 1.7vw, 1.35rem);
  font-weight: 700;
  letter-spacing: -.02em;
  display: block;
  max-width: 20ch;
}
.hero__badge span {
  font-family: var(--f-label);
  font-size: .74rem;
  letter-spacing: .075em;
  text-transform: uppercase;
  color: #ff9ba0;
}

/* quick-book card floating over the hero media */
.bookcard {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 22px;
  box-shadow: var(--shadow-md);
  margin-top: -46px;
  margin-left: clamp(0px, 3vw, 40px);
  margin-right: clamp(0px, 3vw, 40px);
  position: relative;
  z-index: 4;
}
.bookcard h3 { font-size: 1.12rem; margin-bottom: 4px; }
.bookcard p { font-size: .9rem; color: var(--slate); margin-bottom: 14px; }
.bookcard__row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 480px) { .bookcard__row { grid-template-columns: 1fr; } }

/* ==========================================================================
   CARDS / GRIDS
   ========================================================================== */
.grid { display: grid; gap: clamp(14px, 1.7vw, 20px); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1000px) {
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
}

/* service tile: photo + code + name */
/* ---- usp card: an icon in a soft disc, a claim, a sentence ----
   No image and nothing to click, so it stays quieter than .tile — the border
   lifts to red on hover rather than the whole card jumping off the page. */
.usp {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(22px, 2.6vw, 30px);
  text-align: center;
  transition: border-color .25s var(--ease), box-shadow .25s var(--ease);
}
.usp:hover { border-color: var(--red-100); box-shadow: var(--shadow-sm); }
.usp__icon {
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  margin: 0 auto 16px;
  border-radius: 50%;
  background: var(--red-50);
  color: var(--red-600);
}
.usp__icon svg { width: 26px; height: 26px; }
.usp h3 {
  font-size: 1.08rem;
  letter-spacing: -.02em;
  margin-bottom: 8px;
}
.usp p { color: var(--slate); font-size: .95rem; }

.tile {
  position: relative;
  display: block;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease), border-color .25s var(--ease);
}
.tile:hover,
.tile:focus-visible { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: transparent; }
.tile__img { aspect-ratio: 4 / 3; overflow: hidden; background: var(--line-soft); }
.tile__img img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s var(--ease); }
.tile:hover .tile__img img,
.tile:focus-visible .tile__img img { transform: scale(1.05); }
/* same underline pulse the feature cards use, so every hoverable surface on
   the site resolves the same way */
.tile::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 3px;
  background: var(--red-600);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .4s var(--ease);
}
.tile:hover::after,
.tile:focus-visible::after { transform: scaleX(1); }
.tile__body { padding: 18px 20px 20px; }
.tile__code {
  font-family: var(--f-label);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .085em;
  text-transform: uppercase;
  color: var(--red-700);
  display: block;
  margin-bottom: 6px;
}
.tile__body h3 { font-size: 1.13rem; margin-bottom: 6px; }
.tile__body p { font-size: .9rem; color: var(--slate); line-height: 1.55; }

/* plain feature card with the hover pulse */
.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(18px, 2.4vw, 26px);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
  position: relative;
  overflow: hidden;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.card h3 { margin-bottom: 8px; }
.card p { font-size: .95rem; color: var(--slate); }
.card__icon {
  width: 46px;
  height: 46px;
  border-radius: 13px;
  background: var(--red-50);
  color: var(--red-600);
  display: grid;
  place-items: center;
  margin-bottom: 16px;
}
.card__icon svg { width: 23px; height: 23px; }

.card__pulse {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 4px;
  background: var(--red-600);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .4s var(--ease);
}
.card:hover .card__pulse { transform: scaleX(1); }

.section--dark .card {
  background: rgba(255, 255, 255, .05);
  border-color: rgba(255, 255, 255, .12);
}
.section--dark .card p { color: rgba(255, 255, 255, .74); }
.section--dark .card__icon { background: rgba(255, 255, 255, .1); color: #ff9ba0; }

/* ==========================================================================
   STATS
   ========================================================================== */
.stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
@media (max-width: 760px) { .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stats > div { background: var(--white); padding: clamp(16px, 2.2vw, 24px); }
.stats dt {
  font-family: var(--f-display);
  font-size: clamp(2rem, 3.6vw, 2.9rem);
  font-weight: 700;
  letter-spacing: -.035em;
  color: var(--red-600);
  line-height: 1;
  margin-bottom: 8px;
  font-variant-numeric: tabular-nums;
}
.stats dd {
  margin: 0;
  font-family: var(--f-label);
  font-size: .74rem;
  letter-spacing: .055em;
  text-transform: uppercase;
  color: var(--slate);
  line-height: 1.5;
}
.section--dark .stats { background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .14); }
.section--dark .stats > div { background: var(--red-900); }
.section--dark .stats dt { color: #fff; }
.section--dark .stats dd { color: rgba(255, 255, 255, .6); }

/* ==========================================================================
   PACKAGE TABLE — reads like a lab requisition
   ========================================================================== */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 28px;
}
.filters button {
  font-family: var(--f-label);
  font-size: .76rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--white);
  color: var(--slate);
  cursor: pointer;
  transition: all .18s var(--ease);
}
.filters button:hover { border-color: var(--ink); color: var(--ink); }
.filters button:active { transform: scale(.95); transition-duration: .06s; }
.filters button[aria-pressed="true"] {
  background: var(--red-600);
  border-color: var(--red-600);
  color: #fff;
  transform: none;
}

/* how many packages the current filter leaves — without it the list just
   changes length and you have to count */
.filter-count {
  font-family: var(--f-label);
  font-size: .76rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--slate);
  font-variant-numeric: tabular-nums;
  margin: -14px 0 22px;
}
.filter-count b { color: var(--red-700); font-weight: 500; }

.pkg-list { display: grid; gap: 12px; }

/* filtered rows arrive in sequence, which shows the list rebuilding rather
   than making it look like the page reloaded */
@keyframes pkg-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
.pkg.is-entering {
  animation: pkg-in .4s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 38ms);
}

.pkg {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr) auto auto;
  gap: 20px;
  align-items: center;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 20px 22px;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), transform .2s var(--ease);
}
.pkg:hover { border-color: var(--red-600); box-shadow: var(--shadow-sm); transform: translateY(-2px); }
.pkg[hidden] { display: none; }

.pkg__code {
  font-family: var(--f-label);
  font-size: .74rem;
  font-weight: 500;
  letter-spacing: .07em;
  font-variant-numeric: tabular-nums;
  color: var(--red-700);
  border-right: 1px solid var(--line);
  padding-right: 20px;
  align-self: stretch;
  display: flex;
  align-items: center;
}
.pkg__name { min-width: 0; }
.pkg__name h3 { font-size: 1.09rem; margin-bottom: 4px; }
.pkg__meta {
  font-size: .84rem;
  color: var(--slate);
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
}
.pkg__meta span { display: inline-flex; align-items: center; gap: .4em; }
.pkg__price { text-align: right; font-variant-numeric: tabular-nums; }
.pkg__price b {
  font-family: var(--f-display);
  font-size: 1.45rem;
  font-weight: 700;
  letter-spacing: -.03em;
  display: block;
  line-height: 1.1;
}

@media (max-width: 860px) {
  .pkg { grid-template-columns: 1fr auto; gap: 8px 16px; padding: 18px; }
  .pkg__code { grid-column: 1 / -1; border-right: 0; padding-right: 0; padding-bottom: 6px; }
  .pkg__name { grid-column: 1; }
  .pkg__price { grid-column: 2; }
  .pkg .btn { grid-column: 1 / -1; margin-top: 6px; }
}

.tag {
  font-family: var(--f-label);
  font-size: .66rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--red-50);
  color: var(--red-700);
  display: inline-block;
}
.tag--home { background: #e8f7ee; color: #15803d; }
.tag--centre { background: #eef2fb; color: var(--navy-700); }

/* ==========================================================================
   OFFERS
   ========================================================================== */
/* two classes so this beats `.card p` (0,1,1) rather than losing to it */
.offer .offer__pct {
  font-family: var(--f-display);
  font-size: clamp(2.3rem, 4.4vw, 3.2rem);
  font-weight: 700;
  letter-spacing: -.04em;
  line-height: 1;
  color: var(--red-600);
  margin-bottom: 12px;
}
.section--dark .offer .offer__pct { color: #ff5a63; }
.offer__code {
  display: inline-flex;
  align-items: center;
  gap: .6em;
  font-family: var(--f-label);
  font-size: .76rem;
  font-weight: 500;
  letter-spacing: .075em;
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
  border: 1.5px dashed var(--red-600);
  color: var(--red-700);
  border-radius: 8px;
  padding: 8px 14px;
  margin-top: 18px;
}
/* A discount code exists to be quoted back to us, so the code is the button:
   tap it and it's on your clipboard, ready to paste into the WhatsApp message. */
button.offer__code {
  cursor: pointer;
  background: none;
  transition: background .18s var(--ease), color .18s var(--ease),
              border-color .18s var(--ease), transform .2s var(--ease-seat);
}
button.offer__code:hover { background: var(--red-50); }
button.offer__code:active { transform: scale(.96); }
button.offer__code.is-copied {
  border-style: solid;
  background: #e8f7ee;
  border-color: #15803d;
  color: #15803d;
}
.offer__code svg { width: 14px; height: 14px; flex: none; }

.offer__terms {
  font-size: .82rem;
  color: var(--slate);
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

/* ==========================================================================
   SPLIT (image + text)
   ========================================================================== */
.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(24px, 3.6vw, 48px);
  align-items: center;
}
@media (max-width: 900px) { .split { grid-template-columns: 1fr; } }
.split--flip .split__media { order: 2; }
@media (max-width: 900px) { .split--flip .split__media { order: 0; } }

/* A doctor's page opens on a passport-style portrait, which wants a portrait
   frame and wants to stop growing well before it dominates the row — the
   plain .split__media below is cut for landscape photography of the centre.
   The hairline matters: these are scans on a near-white ground, and without
   it the photo bleeds into the paper. */
.split--profile { grid-template-columns: minmax(0, 340px) minmax(0, 1fr); align-items: start; }
@media (max-width: 900px) { .split--profile { grid-template-columns: 1fr; } }
.split--profile .split__media {
  aspect-ratio: 4 / 5;
  max-width: 340px;
  border: 1px solid var(--line);
  background: var(--white);
}

.split__media {
  border-radius: var(--r-xl);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  aspect-ratio: 4 / 3.2;
  position: relative;
}
.split__media img { width: 100%; height: 100%; object-fit: cover; }

.checks { list-style: none; margin: 22px 0 0; padding: 0; display: grid; gap: 12px; }
.checks li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: .97rem;
  color: var(--slate);
}
.checks li strong { color: var(--ink); font-weight: 600; }
.checks svg { flex: none; width: 21px; height: 21px; color: var(--red-600); margin-top: 2px; }
.section--dark .checks li { color: rgba(255, 255, 255, .76); }
.section--dark .checks li strong { color: #fff; }
.section--dark .checks svg { color: #ff5a63; }

/* ==========================================================================
   PEOPLE
   ========================================================================== */
.person {
  display: block;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.person:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.person__img { aspect-ratio: 4 / 5; overflow: hidden; background: var(--line-soft); }
.person__img img { width: 100%; height: 100%; object-fit: cover; filter: saturate(.92); transition: transform .5s var(--ease); }
.person:hover .person__img img { transform: scale(1.04); }
.person__body { padding: 18px 20px 22px; }
.person__body h3 { font-size: 1.1rem; margin-bottom: 3px; }
/* "SENIOR CONSULTANT · RADIOLOGY" runs to two lines in a monospaced face
   while "CONSULTANT · PATHOLOGY" fits on one. Reserving both lines keeps the
   biographies on a shared baseline across the row. */
.person__role {
  font-family: var(--f-label);
  font-size: .64rem;
  line-height: 1.5;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--red-700);
  margin-bottom: 10px;
  min-height: 3em;
}
.person__body p { font-size: .88rem; color: var(--slate); line-height: 1.55; }

/* A passport headshot has no business being 560px wide, which is what a 4:5
   plate comes to in a two-up row. This variant turns the card on its side: a
   fixed portrait plate on the left, the biography beside it, and the row takes
   its height from the text rather than from the photo. */
.person--row { display: grid; grid-template-columns: 152px minmax(0, 1fr); }
.person--row .person__img { aspect-ratio: auto; height: 100%; }
.person--row .person__body { padding: 20px 22px; }
/* the reserved second line is there to align a row of tall cards; side by side
   with the photo there is nothing to align to */
.person--row .person__role { min-height: 0; }
@media (max-width: 540px) { .person--row { grid-template-columns: 108px minmax(0, 1fr); } }
/* No portrait on file: the card runs text-only, like .dossier--noplate. */
.person--noplate { grid-template-columns: minmax(0, 1fr); }

/* ==========================================================================
   GALLERY
   ========================================================================== */
.gallery {
  columns: 3;
  column-gap: 16px;
}
@media (max-width: 900px) { .gallery { columns: 2; } }
@media (max-width: 560px) { .gallery { columns: 1; } }
.gallery figure {
  margin: 0 0 16px;
  break-inside: avoid;
  border-radius: var(--r-md);
  overflow: hidden;
  position: relative;
  cursor: zoom-in;
  background: var(--line-soft);
}
.gallery img { width: 100%; transition: transform .5s var(--ease); }
.gallery figure:hover img { transform: scale(1.04); }
.gallery figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 26px 16px 14px;
  background: linear-gradient(transparent, rgba(78, 4, 9, .85));
  color: #fff;
  font-family: var(--f-label);
  font-size: .72rem;
  letter-spacing: .055em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .25s var(--ease), transform .25s var(--ease);
}
.gallery figure:hover figcaption { opacity: 1; transform: translateY(0); }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(20, 3, 5, .92);
  display: grid;
  place-items: center;
  padding: 24px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s var(--ease);
}
.lightbox.is-open { opacity: 1; pointer-events: auto; }
.lightbox img {
  max-width: min(1100px, 92vw);
  max-height: 84vh;
  border-radius: var(--r-md);
  transform: scale(.96);
  transition: transform .3s var(--ease), opacity .18s var(--ease);
}
.lightbox.is-open img { transform: none; }
.lightbox.is-swapping img { opacity: 0; transform: scale(.99); }

/* stepping through the set beats closing and reopening twelve times */
.lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .28);
  background: rgba(20, 3, 5, .45);
  color: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background .18s var(--ease), border-color .18s var(--ease), transform .18s var(--ease);
}
.lightbox__nav:hover { background: var(--red-600); border-color: var(--red-600); }
.lightbox__nav:active { transform: translateY(-50%) scale(.93); }
.lightbox__nav svg { width: 22px; height: 22px; }
.lightbox__prev { left: clamp(10px, 3vw, 28px); }
.lightbox__next { right: clamp(10px, 3vw, 28px); }
.lightbox__count {
  position: absolute;
  left: 50%;
  bottom: clamp(14px, 3vw, 26px);
  transform: translateX(-50%);
  font-family: var(--f-label);
  font-size: .76rem;
  letter-spacing: .08em;
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, .72);
}
@media (max-width: 620px) {
  .lightbox__nav { width: 44px; height: 44px; top: auto; bottom: 14px; transform: none; }
  .lightbox__nav:active { transform: scale(.93); }
  .lightbox__count { bottom: 26px; }
}

.lightbox__close {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .3);
  background: transparent;
  color: #fff;
  font-size: 1.4rem;
  cursor: pointer;
  line-height: 1;
}
.lightbox__close:hover { background: #fff; color: var(--red-900); }

/* ==========================================================================
   HOME PROMO — a changing facility panel, with the doctor's video beside it
   One row, two jobs: the carousel shows the place, the video shows the
   person. The panel's left edge is a bulge rather than a straight seam, so
   the photograph reads as one piece with the copy instead of being cropped
   next to it. The split is 1.55/1 because the video is a vertical short —
   a wide frame would be mostly letterbox.
   ========================================================================== */
.promo {
  --promo-copy: 45%;
  --promo-pad: clamp(18px, 2.4vw, 32px);
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: clamp(16px, 1.8vw, 24px);
  align-items: stretch;
}

.promo__stage {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--red-900);
  box-shadow: var(--shadow-md);
}

/* Default — no JS — is every slide stacked in the flow: nothing is parked
   behind a control that isn't running. main.js adds .is-live, which is what
   collapses the stack into a single crossfading frame. */
.promo__slide {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--promo-copy);
  align-items: stretch;
}

.promo__shot { position: relative; overflow: hidden; background: var(--red-900); }
/* the frame is close to square, so a wide room shot loses its ends — each
   slide names the part of its photograph worth keeping in --shot-pos */
.promo__shot img {
  width: 100%;
  height: 100%;
  min-height: 100%;
  object-fit: cover;
  object-position: var(--shot-pos, 50% 50%);
  /* the settle out of the zoom runs for most of the slide's turn on screen,
     so movement reads as breathing rather than as a transition */
  transition: transform 4.6s linear;
}

.promo__copy {
  position: relative;
  z-index: 2;
  background: var(--red-900);
  color: #fff;
  padding: var(--promo-pad);
  padding-bottom: calc(var(--promo-pad) + 18px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* the bulge — same fill as the panel, so only its left arc is ever seen */
.promo__copy::before {
  content: "";
  position: absolute;
  top: -14%;
  bottom: -14%;
  left: 0;
  width: 38%;
  transform: translateX(-52%);
  background: var(--red-900);
  border-radius: 50%;
  pointer-events: none;
}
.promo__copy > * { position: relative; }
.promo__copy .eyebrow { color: #ff9ba0; margin-bottom: .5rem; }
.promo__copy .eyebrow::before { display: none; }
.promo__copy h3 {
  font-size: clamp(1.2rem, 1.65vw, 1.5rem);
  line-height: 1.06;
  letter-spacing: -.026em;
  margin-bottom: .4rem;
}
.promo__copy p {
  color: rgba(255, 255, 255, .76);
  font-size: .88rem;
  line-height: 1.45;
  max-width: 34ch;
  margin-bottom: .95rem;
}
.promo__copy .btn { align-self: flex-start; }

/* pan-y: the browser keeps vertical scroll, but a sideways drag is left to
   the swipe handler — without it Chrome claims the pan and fires
   pointercancel, so the swipe never reaches pointerup */
.promo__stage.is-live { display: grid; touch-action: pan-y; }
.promo__stage.is-live img { -webkit-user-drag: none; user-select: none; }
.promo__stage.is-live .promo__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity .38s var(--ease), visibility 0s linear .38s;
}
.promo__stage.is-live .promo__slide.is-active {
  position: relative;
  opacity: 1;
  visibility: visible;
  transition: opacity .38s var(--ease);
}
.promo__stage.is-live .promo__shot img { transform: scale(1.07); }
.promo__stage.is-live .promo__slide.is-active .promo__shot img { transform: none; }

@media (min-width: 901px) {
  .promo__stage { min-height: clamp(258px, 21vw, 318px); }
}
/* below this the panel is narrow enough that the photograph can spare the
   room; above it, the copy gets the extra width instead */
@media (min-width: 1180px) {
  .promo { --promo-copy: 47%; }
}

/* built by main.js, so they only exist where they work */
.promo__dots {
  position: absolute;
  z-index: 3;
  right: 0;
  bottom: clamp(14px, 1.7vw, 22px);
  width: var(--promo-copy);
  padding-inline: var(--promo-pad);
  display: flex;
  gap: 8px;
}
.promo__dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, .34);
  cursor: pointer;
  transition: width .3s var(--ease), background .18s var(--ease);
}
.promo__dot:hover { background: rgba(255, 255, 255, .62); }
.promo__dot[aria-current="true"] { width: 26px; background: #fff; }

/* ---- the video card: poster now, YouTube only once it is asked for ---- */
.promo__video {
  display: grid;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #0b0c0f;
  box-shadow: var(--shadow-md);
}
.promo__video iframe {
  width: 100%;
  height: 100%;
  min-height: 220px;
  border: 0;
  display: block;
}

.ytlite {
  position: relative;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: #0b0c0f;
  cursor: pointer;
  display: block;
}
.ytlite img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .6s var(--ease), opacity .25s var(--ease);
}
.ytlite:hover img { transform: scale(1.035); opacity: .9; }
.ytlite__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
}
.ytlite__play svg {
  width: clamp(56px, 6.5vw, 72px);
  height: auto;
  filter: drop-shadow(0 8px 22px rgba(0, 0, 0, .45));
  transition: transform .2s var(--ease-seat);
}
/* YouTube's own resting grey, going red on intent — the control should be
   recognisable as what it is before it is clicked */
.ytlite__shell { fill: #212121; fill-opacity: .82; transition: fill .18s var(--ease), fill-opacity .18s var(--ease); }
.ytlite:hover .ytlite__shell,
.ytlite:focus-visible .ytlite__shell { fill: #f00; fill-opacity: 1; }
.ytlite:hover .ytlite__play svg { transform: scale(1.07); }
.ytlite:active .ytlite__play svg { transform: scale(.96); }

@media (max-width: 900px) {
  .promo { grid-template-columns: 1fr; }
  .promo__slide { grid-template-columns: 1fr; }
  /* stacked, the photo and the video are paying for the same screen twice —
     both are cropped shorter than their 16:9 source so the pair still fits
     above the hero */
  .promo__shot { aspect-ratio: 2 / 1; }
  .promo__shot img { min-height: 0; }
  /* the bulge turns with the layout — it is the top edge of the panel now */
  .promo__copy::before {
    top: 0;
    bottom: auto;
    left: -14%;
    right: -14%;
    width: auto;
    height: 34%;
    transform: translateY(-52%);
  }
  .promo__dots {
    width: 100%;
    justify-content: center;
    padding-inline: var(--promo-pad);
  }
  .promo__video { aspect-ratio: 16 / 9; }
}

/* ==========================================================================
   ACCORDION
   ========================================================================== */
.accordion { border-top: 1px solid var(--line); }
/* overflow:hidden lets main.js animate the panel's height open and shut;
   without it <details> snaps */
.accordion details { border-bottom: 1px solid var(--line); overflow: hidden; }
.accordion summary {
  list-style: none;
  cursor: pointer;
  padding: 22px 44px 22px 0;
  position: relative;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 1.08rem;
  letter-spacing: -.015em;
  transition: color .18s var(--ease);
}
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary:hover { color: var(--red-700); }
.accordion summary::after {
  content: "";
  position: absolute;
  right: 8px;
  top: 50%;
  width: 12px;
  height: 12px;
  border-right: 2px solid var(--red-600);
  border-bottom: 2px solid var(--red-600);
  transform: translateY(-70%) rotate(45deg);
  transition: transform .25s var(--ease);
}
.accordion details[open] summary::after { transform: translateY(-25%) rotate(-135deg); }
.accordion .acc__body { padding: 0 44px 24px 0; color: var(--slate); font-size: .97rem; }

/* ==========================================================================
   FORMS
   ========================================================================== */
.field { display: grid; gap: 7px; margin-bottom: 16px; }
.field label {
  font-family: var(--f-label);
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--slate);
}
.field input,
.field select,
.field textarea {
  font-family: var(--f-body);
  font-size: 1rem;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 13px 15px;
  width: 100%;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.field textarea { min-height: 118px; resize: vertical; }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--red-600);
  box-shadow: 0 0 0 3px rgba(229, 18, 30, .14);
}
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
@media (max-width: 560px) { .field-row { grid-template-columns: 1fr; } }

.form-note { font-size: .82rem; color: var(--slate); margin-top: 12px; }

/* Validation is handled in JS rather than left to the browser bubble, so the
   message sits next to the field it belongs to and survives a second attempt. */
.field.is-invalid input,
.field.is-invalid select,
.field.is-invalid textarea {
  border-color: var(--red-600);
  box-shadow: 0 0 0 3px rgba(229, 18, 30, .12);
}
/* the label above is a label and gets the data face; this is a sentence and
   gets the reading face */
.field__error {
  font-family: var(--f-body);
  font-size: .84rem;
  line-height: 1.45;
  color: var(--red-700);
  display: none;
}
.field.is-invalid .field__error { display: block; }
.field.is-invalid input,
.field.is-invalid select,
.field.is-invalid textarea { animation: nudge .3s var(--ease); }
@keyframes nudge {
  25% { transform: translateX(-4px); }
  60% { transform: translateX(3px); }
  100% { transform: none; }
}

/* what happened after you pressed the button — the form hands off to
   WhatsApp, which is invisible if the tab opens behind the window */
.form-status {
  display: none;
  align-items: flex-start;
  gap: 10px;
  margin-top: 16px;
  padding: 13px 16px;
  border-radius: var(--r-md);
  background: #e8f7ee;
  border: 1px solid #b7e3c8;
  color: #15803d;
  font-size: .9rem;
}
.form-status.is-on { display: flex; animation: pkg-in .35s var(--ease) both; }
.form-status svg { width: 18px; height: 18px; flex: none; margin-top: 2px; }
.form-status a { text-decoration: underline; font-weight: 600; }

.form-panel {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: clamp(20px, 3vw, 30px);
  box-shadow: var(--shadow-sm);
}

/* ==========================================================================
   CONTACT / INFO ROWS
   ========================================================================== */
.info-list { display: grid; gap: 2px; }
.info-list > div {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 16px;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
  align-items: start;
}
.info-list .info__icon {
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: var(--red-50);
  color: var(--red-600);
  display: grid;
  place-items: center;
}
.info-list .info__icon svg { width: 20px; height: 20px; }
.info-list dt {
  font-family: var(--f-label);
  font-size: .7rem;
  letter-spacing: .075em;
  text-transform: uppercase;
  color: var(--slate);
  margin-bottom: 3px;
}
.info-list dd { margin: 0; font-size: 1.02rem; font-weight: 500; }
.info-list dd a:hover { color: var(--red-700); }
.section--dark .info-list > div { border-color: rgba(255, 255, 255, .14); }
.section--dark .info-list .info__icon { background: rgba(255, 255, 255, .1); color: #ff9ba0; }
.section--dark .info-list dt { color: rgba(255, 255, 255, .55); }

/* ==========================================================================
   MAP
   ========================================================================== */
.map {
  border-radius: var(--r-xl);
  overflow: hidden;
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  background: var(--line-soft);
  line-height: 0;
}
.map iframe { width: 100%; height: clamp(300px, 42vw, 460px); border: 0; display: block; }

/* ==========================================================================
   PAGE HEAD (inner pages)
   ========================================================================== */
/* An inner page is somewhere you arrived on purpose, so its head only has to
   name the page and get out of the way — the home page is the one that gets
   to open with a full-height statement. Everything below is sized to keep the
   first real row of content inside the fold on a laptop. */
.pagehead {
  background: var(--red-900);
  color: #fff;
  position: relative;
  overflow: hidden;
  padding-block: clamp(24px, 3vw, 40px);
}
.pagehead::before {
  content: "";
  position: absolute;
  inset: -60% -20% auto 30%;
  height: 180%;
  background: radial-gradient(45% 45% at 50% 50%, rgba(229, 18, 30, .55), transparent 70%);
}
.pagehead::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 155, 160, .6), transparent);
}
.pagehead .shell { position: relative; }
/* smaller than the home page's h1 by design — this is a signpost, not a hero.
   The measure is capped because at the shell's full 1240px a shortened
   heading sets as one 60-character line, which reads as a stretched banner. */
.pagehead h1 {
  font-size: clamp(1.85rem, 3.4vw, 2.6rem);
  max-width: 30ch;
  margin-bottom: 10px;
}
/* :not(.crumbs) because the crumb trail is a <p> too, and this rule would
   otherwise outrank .crumbs on font-size and measure */
.pagehead p:not(.crumbs) {
  color: rgba(255, 255, 255, .78);
  max-width: 54ch;
  font-size: 1rem;
  line-height: 1.55;
}
.pagehead .eyebrow { color: #ff9ba0; margin-bottom: .7rem; }
.pagehead .eyebrow::before { background: #ff9ba0; }

/* The band above already reads as a break, so the section under it does not
   need its full opening padding as well — the two were stacking into about
   170px of empty page before the first row of content. */
.pagehead + .section { padding-top: clamp(40px, 5vw, 68px); }

/* Lives on .pagehead and nowhere else — the colours are white-on-red, so the
   same markup on a light section renders invisible. A back-link on paper wants
   .tlink instead. */
.crumbs {
  font-family: var(--f-label);
  font-size: .72rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .5);
  margin-top: 14px;
}
.crumbs a:hover { color: #fff; }
.crumbs span { margin-inline: 8px; }

/* ==========================================================================
   CTA BAND
   ========================================================================== */
.cta-band {
  background: linear-gradient(120deg, var(--red-800), var(--red-600) 60%, #ff3b45);
  color: #fff;
  border-radius: var(--r-xl);
  padding: clamp(26px, 3.6vw, 42px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 28px;
  align-items: center;
  box-shadow: var(--shadow-lg);
}
@media (max-width: 820px) { .cta-band { grid-template-columns: 1fr; } }
.cta-band h2 { font-size: clamp(1.7rem, 3.2vw, 2.5rem); margin-bottom: 10px; }
.cta-band p { color: rgba(255, 255, 255, .85); max-width: 46ch; }
.cta-band .btn--ghost { background: #fff; border-color: #fff; }

/* ==========================================================================
   FOOTER
   ========================================================================== */
.site-footer {
  background: #21070a;
  color: rgba(255, 255, 255, .68);
  padding-block: clamp(34px, 4.4vw, 54px) 0;
  font-size: .93rem;
}
.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 48px);
}
@media (max-width: 900px) { .footer__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .footer__grid { grid-template-columns: 1fr; } }
/* the popular-test list runs to seventeen names, twice what the other footer
   lists hold. Widening its column and setting it in two keeps it level with
   its neighbours instead of dragging the footer down by another 200px. */
@media (min-width: 901px) {
  .footer__grid {
    grid-template-columns: minmax(0, 1.24fr) minmax(0, .62fr) minmax(0, 1.95fr) minmax(0, .95fr);
  }
  /* auto-fill rather than a fixed two, so the list falls back to one column
     on the narrower desktops instead of wrapping every name onto two lines */
  .footer__tests { grid-template-columns: repeat(auto-fill, minmax(196px, 1fr)); gap: 9px 20px; }
}

.footer__logo {
  background: #fff;
  border-radius: var(--r-md);
  padding: 14px 18px;
  display: inline-block;
  margin-bottom: 20px;
}
/* big enough that the arc wordmark in the logo is actually legible */
.footer__logo img { height: 96px; width: auto; }

/* the centre's own strapline, straight off the card */
.footer__tagline {
  font-family: var(--f-display);
  font-style: italic;
  font-size: 1.05rem;
  color: #ff9ba0;
  margin-bottom: 10px;
}

.site-footer h4 {
  color: #fff;
  font-family: var(--f-label);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .085em;
  text-transform: uppercase;
  margin-bottom: 16px;
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.site-footer a { transition: color .18s var(--ease); }
.site-footer a:hover { color: #ff9ba0; }

.socials { display: flex; gap: 10px; margin-top: 20px; }
.socials a {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .18);
  display: grid;
  place-items: center;
  transition: all .2s var(--ease);
}
.socials a:hover { background: var(--red-600); border-color: var(--red-600); color: #fff; }
.socials svg { width: 17px; height: 17px; }

.footer__legal {
  margin-top: clamp(26px, 3.4vw, 40px);
  border-top: 1px solid rgba(255, 255, 255, .12);
  padding-block: 22px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  justify-content: space-between;
  font-size: .82rem;
  color: rgba(255, 255, 255, .48);
}

/* The build credit is the one link down here that has to announce itself —
   a name in running text reads as text, not as somewhere you can go. Brighter
   than its neighbours, underlined, and it warms to the house pink on hover. */
.footer__credit a {
  color: rgba(255, 255, 255, .82);
  text-decoration: underline;
  text-decoration-color: rgba(255, 155, 160, .55);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.footer__credit a:hover,
.footer__credit a:focus-visible {
  color: #ff9ba0;
  text-decoration-color: #ff9ba0;
}

.disclaimer {
  font-size: .8rem;
  color: rgba(255, 255, 255, .4);
  line-height: 1.6;
  border-top: 1px solid rgba(255, 255, 255, .08);
  padding-block: 18px 26px;
}

/* ==========================================================================
   FLOATING ACTIONS
   ========================================================================== */
.wa-float {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 90;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: #16a34a;
  color: #fff;
  padding: 13px 20px 13px 15px;
  border-radius: 999px;
  font-weight: 600;
  font-size: .94rem;
  box-shadow: 0 10px 30px rgba(22, 163, 74, .4);
  transition: transform .2s var(--ease), box-shadow .2s var(--ease);
}
.wa-float:hover { transform: translateY(-3px); box-shadow: 0 16px 38px rgba(22, 163, 74, .5); }
.wa-float svg { width: 24px; height: 24px; flex: none; }
.wa-float::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 999px;
  border: 2px solid #16a34a;
  animation: ring 2.6s var(--ease) infinite;
}
@keyframes ring {
  0% { transform: scale(1); opacity: .7; }
  70%, 100% { transform: scale(1.32); opacity: 0; }
}

/* ---- the social rail ----
   The accounts, parked against the right edge and vertically centred, so it
   never argues with the WhatsApp pill sitting in the bottom corner. It reads
   as a tab clipped to the side of the page: rounded and shadowed on the left,
   square and borderless where it meets the viewport edge.

   It rides along on a phone too, just narrower — see the compacting rule
   below. Vertically centred keeps it clear of the mobile bar at the bottom
   and of the header at the top, so it never fights either. */
.social-rail {
  position: fixed;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  z-index: 80;
  display: grid;
  gap: 2px;
  padding: 6px;
  background: var(--white);
  border: 1px solid var(--line);
  border-right: 0;
  border-radius: var(--r-md) 0 0 var(--r-md);
  box-shadow: -6px 0 26px rgba(22, 24, 29, .09);
}
.social-rail a {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  /* the mark's own red — grey read as disabled next to a red logo */
  color: var(--red-600);
  transition: background .2s var(--ease), color .2s var(--ease);
}
.social-rail a:hover,
.social-rail a:focus-visible { background: var(--red-600); color: var(--white); }
.social-rail svg { width: 18px; height: 18px; }

/* Below 900px the rail stops being an edge tab and becomes a corner dock.
   A phone gutter is 20px and the tab is 45px wide, so parked mid-edge it
   clips the last word of every full-width line; the bottom-right corner is
   both empty and where a floating control is expected, next to the WhatsApp
   pill that already lives there. It stays a permanent, visible thing on the
   page — it just stops sitting on the text. */
@media (max-width: 900px) {
  .social-rail {
    top: auto;
    bottom: 92px;
    right: 14px;
    transform: none;
    padding: 5px;
    border-right: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-md);
  }
  .social-rail a { width: 36px; height: 36px; }
  .social-rail svg { width: 17px; height: 17px; }
}
/* the WhatsApp pill is gone at this width and the tab bar owns the bottom
   strip, so the dock sits on the bar rather than on the pill */
@media (max-width: 720px) {
  .social-rail { bottom: calc(var(--bar-h) + 14px); }
}

.mobile-bar { display: none; }
@media (max-width: 720px) {
  .wa-float { display: none; }
  /* A tab bar, not a tray of buttons: four equal columns, icon over label,
     thumb-sized targets. The padding carries the home-indicator inset so the
     labels clear the gesture bar on a modern phone. */
  /* one number for the bar's height: the bar is sized by it, and the drawer
     and the page body both hold themselves clear of it */
  :root { --bar-h: calc(66px + env(safe-area-inset-bottom)); }

  /* Two ways into the same menu, a thumb-reach apart, is one too many. At this
     width the bar's Menu tab is the way in and the hamburger goes. */
  .nav-toggle { display: none; }

  .mobile-bar {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    position: fixed;
    inset: auto 0 0 0;
    z-index: 90;
    height: var(--bar-h);
    box-sizing: border-box;
    background: var(--white);
    border-top: 1px solid var(--line);
    box-shadow: 0 -6px 24px rgba(22, 24, 29, .1);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  }
  .mobile-bar__item {
    display: grid;
    justify-items: center;
    align-content: center;
    gap: 5px;
    padding: 4px 2px;
    background: none;
    border: 0;
    font-family: var(--f-body);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--slate);
    cursor: pointer;
    transition: color .18s var(--ease);
  }
  .mobile-bar__item svg { width: 22px; height: 22px; }
  .mobile-bar__item:hover,
  .mobile-bar__item:focus-visible,
  .mobile-bar__item:active { color: var(--red-600); }
  /* the tab for the page you are already on */
  .mobile-bar__item[aria-current="page"] { color: var(--red-600); }

  body { padding-bottom: calc(var(--bar-h) + 18px); }

  /* The drawer stops where the bar starts rather than running under it. Left
     full-height, its last link sits beneath the bar and cannot be scrolled
     clear — the bar is painted over the drawer's own scroll area, so no amount
     of bottom padding inside the drawer reaches past it. */
  .nav {
    bottom: var(--bar-h);
    border-bottom: 1px solid var(--line);
    padding-bottom: 24px;
  }
}

/* ==========================================================================
   DOCTOR PROFILE — the report sheet
   ==========================================================================
   What these three people produce is a signed report, and this site's whole
   claim is that the one who signs yours works in this building. So the
   profiles borrow that document's grammar instead of the usual clinic-site
   template of hero photo, icon cards and a stats row: mono field labels down
   the left, checkable facts at reading size on the right, a hairline between
   every row, and the consultant's sign-off at the foot.

   Two rules hold the whole thing together. Archivo appears exactly twice on
   the page — the name in the masthead and the name in the sign-off — and mono
   carries every label in between; on the rest of the site mono is an accent,
   here it is the spine. And the measure is narrow: every other page is a wide
   two-column split, but a document is a column. */

.shell--narrow { max-width: 960px; }

/* ---------- the sheet ----------
   Lifts over the red masthead so the page opens on the particulars rather
   than on another band of padding. The section owns no top padding at all;
   the negative margin is the only thing setting the overlap. */
.pagehead--plate { padding-bottom: clamp(66px, 8vw, 108px); }
.pagehead + .section--sheet { position: relative; z-index: 1; padding-top: 0; }
.dossier {
  margin-top: clamp(-72px, -6vw, -40px);
  display: grid;
  grid-template-columns: 224px minmax(0, 1fr);
  gap: clamp(24px, 4vw, 44px);
  padding: clamp(22px, 3vw, 34px);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-md);
}
@media (max-width: 720px) {
  .dossier { grid-template-columns: 1fr; justify-items: start; }
}
/* No portrait on file for this consultant, so the sheet runs the particulars
   the full width rather than holding a gap or standing in a placeholder. The
   opening line carries the top of the sheet on its own, so it is set larger. */
.dossier--noplate { grid-template-columns: minmax(0, 1fr); }
.dossier--noplate .dossier__intro {
  font-size: clamp(1.15rem, 2vw, 1.42rem);
  max-width: 40ch;
  margin-bottom: 26px;
}

/* The portraits are passport scans — grey, formal, a little stiff. Rather
   than crop them into editorial headshots they are mounted as what they
   actually are: an affixed ID photograph. Square corners against the sheet's
   rounded ones, one hairline, no shadow. 4:5 is the passport ratio. */
.dossier__photo {
  width: 100%;
  max-width: 224px;
  aspect-ratio: 4 / 5;
  border: 1px solid var(--line);
  background: var(--line-soft);
  overflow: hidden;
}
.dossier__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

.dossier__intro {
  font-size: clamp(1.05rem, 1.6vw, 1.22rem);
  line-height: 1.45;
  color: var(--ink);
  font-weight: 500;
  margin-bottom: 22px;
  max-width: 46ch;
}

/* the particulars: label left, fact right, hairline between */
.fields { display: grid; }
.fields > div {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: 6px 20px;
  padding: 14px 0;
  border-top: 1px solid var(--line);
}
.fields > div:last-child { border-bottom: 1px solid var(--line); }
.fields dt {
  font-family: var(--f-label);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--slate);
  padding-top: .2em;
}
.fields dd { margin: 0; font-size: 1.02rem; line-height: 1.5; color: var(--ink); }
@media (max-width: 560px) {
  .fields > div { grid-template-columns: 1fr; }
}

/* ---------- the section head ----------
   In a document the field name is the heading, so these are set as labels
   rather than as display type — which is also what keeps Archivo down to two
   appearances a page. */
.sheet-head {
  font-family: var(--f-label);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--red-700);
  padding-bottom: 12px;
  border-bottom: 1.5px solid var(--ink);
}
.sheet-note {
  margin: 18px 0 6px;
  max-width: 62ch;
  color: var(--slate);
  font-size: 1rem;
  line-height: 1.6;
}

/* ---------- the ledger ----------
   One component, used twice: the training record and the list of what the
   doctor reads. The left column types the entry — DEGREE, POST, NOW, or a
   panel code — so the shape of a career is legible without reading it: two
   degrees, a teaching post, the current job. That is the whole reason the
   graduation-cap icons went; a cap beside "MBBS" says nothing the word
   doesn't. The institution sits at reading size because it is the part a
   patient can actually go and check. */
.ledger { list-style: none; margin: 0; padding: 0; }
.ledger__row {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: 4px 20px;
  padding: 20px 0;
  border-bottom: 1px solid var(--line);
}
.ledger__type {
  font-family: var(--f-label);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--slate);
  padding-top: .35em;
  display: flex;
  align-items: baseline;
  gap: .6em;
}
.ledger__row h3 {
  font-family: var(--f-body);
  font-size: 1.06rem;
  font-weight: 600;
  color: var(--navy-900);
  margin-bottom: 3px;
  line-height: 1.35;
}
.ledger__row p { color: var(--slate); font-size: .97rem; line-height: 1.55; }
/* the current post is the one entry a reader is looking for */
.ledger__row.is-now .ledger__type { color: var(--red-700); }
.ledger__row.is-now .ledger__type::before {
  content: "";
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: var(--red-600);
  align-self: center;
  margin-top: -.1em;
}
@media (max-width: 560px) {
  .ledger__row { grid-template-columns: 1fr; gap: 8px; }
  .ledger__type { padding-top: 0; }
}

/* ---------- the week strip ----------
   Opening hours were three sentences of prose. A schedule is a shape, so it
   is drawn as one: seven cells, the days the doctor is in filled. A patient
   can see "not Saturday" without reading. The in/out state is carried in text
   for screen readers as well as in colour. */
.week + .week { margin-top: 30px; }
.week__label {
  font-family: var(--f-label);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--slate);
  margin-bottom: 12px;
}
.week__days { list-style: none; margin: 0; padding: 0; display: flex; gap: 6px; }
.week__day {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-family: var(--f-label);
  font-size: .78rem;
  font-weight: 500;
  color: var(--slate);
  background: var(--white);
}
.week__day abbr { text-decoration: none; border: 0; }
.week__day.is-in {
  background: var(--red-600);
  border-color: var(--red-600);
  color: var(--white);
  /* the one orchestrated moment on the page: the strip fills left to right as
     it comes into view, the way a schedule gets marked off. Rides the
     existing .reveal stagger, so reduced motion switches it off for free. */
  transform: scale(.6);
  opacity: 0;
  transition: transform .34s var(--ease-seat), opacity .2s var(--ease);
  transition-delay: calc(var(--i, 0) * 45ms + .12s);
}
.reveal.is-in .week__day.is-in { transform: none; opacity: 1; }
.week__day.is-part {
  background: var(--red-50);
  border-color: var(--red-600);
  color: var(--red-700);
}
.week__time {
  margin-top: 12px;
  font-size: 1rem;
  color: var(--ink);
}
.week__time span { color: var(--slate); }
@media (max-width: 400px) {
  .week__day { width: 34px; height: 34px; font-size: .72rem; }
}

/* ---------- the credential ----------
   The ledger above states the qualifications; this is the paper behind them.
   Mounted the way the portrait is — hairline, square corners, no shadow —
   because it is the same kind of object: a document affixed to a sheet, not a
   picture placed on a page. The particulars are set beside it rather than left
   inside the scan, so the registration number can be read, and checked against
   the council's own register, without opening the image at all. The scan is
   for the reader who wants to see the seal. */
.credential {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: clamp(20px, 3vw, 36px);
  align-items: start;
  margin-top: 26px;
}
.credential figure {
  margin: 0;
  border: 1px solid var(--line);
  background: var(--line-soft);
  overflow: hidden;
  cursor: zoom-in;
}
.credential figure img { width: 100%; height: auto; display: block; }
.credential figure:focus-visible { outline: 2px solid var(--red-600); outline-offset: 3px; }
/* a scan of a certificate reads as an illustration, not as a control, so the
   affordance is stated on the mount instead of waiting for a hover */
.credential figcaption {
  display: flex;
  align-items: center;
  gap: .55em;
  padding: 9px 12px;
  border-top: 1px solid var(--line);
  background: var(--white);
  font-family: var(--f-label);
  font-size: .66rem;
  font-weight: 500;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--slate);
  transition: color .18s var(--ease);
}
.credential figcaption svg { width: 13px; height: 13px; flex: none; }
.credential figure:hover figcaption,
.credential figure:focus-visible figcaption { color: var(--red-700); }
/* the first .fields row carries its own top padding; pulling it up sets the
   label on the same line as the top edge of the mount */
.credential .fields { margin-top: -14px; }
@media (max-width: 720px) {
  .credential { grid-template-columns: 1fr; }
  .credential figure { max-width: 380px; }
  .credential .fields { margin-top: 0; }
}

/* ---------- the sign-off ----------
   The page's signature, and the site's promise in one block: a rule, the
   name, the degrees and the designation, set where a consultant's attribution
   sits at the foot of a report. Typeset, not handwritten — this is the line
   printed under the scrawl, not the scrawl. */
.signoff {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: clamp(24px, 4vw, 48px);
  padding-top: 26px;
  border-top: 1.5px solid var(--ink);
}
.signoff__name {
  display: block;
  font-family: var(--f-display);
  font-size: clamp(1.3rem, 2.4vw, 1.75rem);
  font-weight: 700;
  letter-spacing: -.03em;
  color: var(--navy-900);
  line-height: 1.1;
  margin-bottom: 8px;
}
.signoff__meta {
  display: block;
  font-family: var(--f-label);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--slate);
  line-height: 1.7;
}
.signoff__meta strong { color: var(--red-700); font-weight: 500; }
.signoff__block { text-align: right; }
.signoff .btn-row { align-self: end; }
@media (max-width: 720px) {
  .signoff { grid-template-columns: 1fr; align-items: start; }
  .signoff__block { text-align: left; order: -1; }
}

/* ---------- the other two ----------
   With no doctors index to go back to, the foot of each profile points
   sideways at the colleagues instead. */
.alsoseen { display: grid; gap: 2px; }
.alsoseen a {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  padding: 18px 4px;
  border-bottom: 1px solid var(--line);
  transition: padding .2s var(--ease);
}
.alsoseen a:first-child { border-top: 1px solid var(--line); }
.alsoseen a:hover { padding-left: 14px; }
.alsoseen strong {
  display: block;
  font-family: var(--f-body);
  letter-spacing: normal;
  text-transform: none;
  font-size: 1.06rem;
  font-weight: 600;
  color: var(--navy-900);
  transition: color .18s var(--ease);
}
.alsoseen a:hover strong { color: var(--red-700); }
.alsoseen span {
  font-family: var(--f-label);
  font-size: .68rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--slate);
}
.alsoseen svg { width: 17px; height: 17px; flex: none; color: var(--red-600); }

/* ==========================================================================
   MOTION — reveal on scroll
   ========================================================================== */
/* Shorter and shallower than a typical scroll reveal. This is a clinic, not a
   showreel — the content should look like it settled, not like it flew in.
   --i is set by main.js for siblings that arrive together; the hand-placed
   data-d values still win where they exist. */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .55s var(--ease), transform .55s var(--ease);
  transition-delay: calc(var(--i, 0) * 65ms);
}
.reveal.is-in { opacity: 1; transform: none; }
.reveal[data-d="1"] { transition-delay: .08s; }
.reveal[data-d="2"] { transition-delay: .16s; }
.reveal[data-d="3"] { transition-delay: .24s; }
.reveal[data-d="4"] { transition-delay: .32s; }

/* Page load runs as one sequence rather than four things appearing together:
   eyebrow, headline, lede, buttons, proof — the order you'd read them in. The
   photograph comes up alongside the headline so the fold never looks empty. */
@keyframes hero-in {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: none; }
}
.hero__grid .eyebrow,
.hero__grid h1,
.hero__lede,
.hero__grid .btn-row,
.hero__intl,
.hero__proof,
.hero__media { animation: hero-in .68s var(--ease) both; }
.hero__grid .eyebrow { animation-delay: .04s; }
.hero__grid h1 { animation-delay: .12s; }
.hero__media { animation-delay: .18s; }
.hero__lede { animation-delay: .22s; }
.hero__grid .btn-row { animation-delay: .3s; }
.hero__intl { animation-delay: .34s; }
.hero__proof { animation-delay: .38s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* the delays matter as much as the durations here — a zeroed animation that
     still waits 0.38s to start leaves the hero's proof list invisible for
     0.38s, which is exactly the flash this setting exists to prevent */
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    transition-delay: 0s !important;
  }
  .reveal { opacity: 1; transform: none; }
  .trace .trace__line { stroke-dashoffset: 0 !important; }
  .trace__dot, .wa-float::before { display: none; }
}

/* ---------- utilities ---------- */
.u-center { text-align: center; }
.u-mt-lg { margin-top: clamp(22px, 2.8vw, 34px); }
.u-mt-md { margin-top: 24px; }
.u-mb-md { margin-bottom: 24px; }
.visually-hidden {
  position: absolute !important;
  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: -9999px;
  top: 0;
  z-index: 999;
  background: var(--red-600);
  color: #fff;
  padding: 12px 18px;
  border-radius: 0 0 var(--r-md) 0;
}
.skip-link:focus { left: 0; }

/* ==========================================================================
   Rate list — tests.html
   549 line items off the counter rate list. The job here is scanning, not
   browsing: the name is the thing you match against a prescription, the
   price is the thing you compare, so the price is set in the data face and
   given its own column rather than being folded into a sentence.
   ========================================================================== */

.rate-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 20px;
  margin-bottom: 22px;
}

.rate-search {
  position: relative;
  flex: 1 1 340px;
  display: flex;
  align-items: center;
}
.rate-search svg {
  position: absolute;
  left: 15px;
  width: 17px;
  height: 17px;
  color: var(--slate);
  pointer-events: none;
}
.rate-search input {
  width: 100%;
  font-family: var(--f-body);
  font-size: 1rem;
  color: var(--ink);
  padding: 14px 42px 14px 44px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--white);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.rate-search input::placeholder { color: var(--slate); opacity: .85; }
.rate-search input:focus {
  outline: none;
  border-color: var(--red-600);
  box-shadow: 0 0 0 4px var(--red-50);
}
.rate-search input::-webkit-search-cancel-button { display: none; }
.rate-search__clear {
  position: absolute;
  right: 8px;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: 50%;
  background: var(--line-soft);
  color: var(--slate);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.rate-search__clear:hover { background: var(--red-100); color: var(--red-800); }

.rate-tools .filters { margin-bottom: 0; }

/* Each department keeps its own heading so the list never loses its place
   when you have scrolled 200 rows into pathology. */
.rate-group { margin-top: clamp(26px, 3.4vw, 40px); }
.rate-group__head {
  position: relative;
  padding-bottom: 14px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.rate-group__head h2 {
  font-family: var(--f-display);
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  letter-spacing: -.01em;
  margin: 0 0 4px;
}
.rate-group__head p {
  margin: 0;
  color: var(--slate);
  font-size: .95rem;
  max-width: 62ch;
}
.rate-group__count {
  position: absolute;
  top: 2px;
  right: 0;
  font-family: var(--f-label);
  font-size: .72rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--red-700);
  font-variant-numeric: tabular-nums;
}

.rate-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
}
@media (min-width: 980px) {
  /* Two columns halves a 400-row scroll. Order stays alphabetical
     left-to-right, which is how the printed list reads. */
  .rate-list { grid-template-columns: 1fr 1fr; column-gap: 40px; }
}

.rate__row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 14px;
  padding: 11px 4px 11px 0;
  border-bottom: 1px solid var(--line-soft);
}
.rate__row:hover { background: var(--red-50); }
.rate__row[hidden] { display: none; }

.rate__name {
  font-size: .95rem;
  line-height: 1.35;
  color: var(--ink);
}
.rate__price {
  font-family: var(--f-label);
  font-size: .9rem;
  font-weight: 500;
  color: var(--navy-700);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.rate__price--ask {
  font-size: .74rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--slate);
}

.rate__book {
  font-family: var(--f-label);
  font-size: .7rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 6px 13px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--white);
  color: var(--slate);
  cursor: pointer;
  transition: all .18s var(--ease);
}
.rate__book:hover { background: #16a34a; border-color: #16a34a; color: #fff; }
.rate__book:active { transform: scale(.94); transition-duration: .06s; }

.rate-group__empty,
.rate-noresult {
  color: var(--slate);
  font-size: .95rem;
  padding: 18px 0;
}
.rate-noresult { max-width: 60ch; }
.rate-noresult a { color: var(--red-700); text-decoration: underline; }

.rate-note {
  margin-top: clamp(26px, 3vw, 38px);
  padding-top: 22px;
  border-top: 1px solid var(--line);
  color: var(--slate);
  font-size: .88rem;
  line-height: 1.65;
  max-width: 80ch;
}

@media (max-width: 520px) {
  .rate__row { grid-template-columns: 1fr auto; row-gap: 6px; }
  .rate__book { grid-column: 2; }
  .rate__price { grid-row: 1; grid-column: 2; }
  .rate__name { grid-column: 1; grid-row: 1 / span 2; }
}
