/* ==========================================================================
   Sarada Nursing Home — design system

   Direction: institutional warmth. A serif display face for authority, a warm
   ivory ground instead of clinical white, deep navy carried from the hospital's
   own signage, and gold used sparingly for emphasis. Depth comes from layered
   shadows and hairline rules rather than heavy boxes.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Navy — the primary voice, from the hospital board */
  --navy-950: #061626;
  --navy-900: #0a2540;
  --navy-800: #103356;
  --navy-700: #17456f;
  --navy-600: #22598b;
  --navy-500: #3573a9;
  --navy-200: #b9cde2;
  --navy-100: #dde8f3;
  --navy-50:  #eef4fa;

  /* Red — emergency and calls to action only. Never decorative. */
  --flip-time: .62s;
  --flip-ease: cubic-bezier(.34, .9, .3, 1);
  --red-800: #7f0f14;
  --red-700: #9c1218;
  --red-600: #be1622;
  --red-500: #d93b45;
  --red-100: #f8dcde;
  --red-50:  #fdf1f2;

  /* Gold — accents, highlights, the free-OP badge */
  --gold-700: #8a6410;
  --gold-600: #ab7d16;
  --gold-500: #c9971f;
  --gold-400: #e0b64e;
  --gold-100: #f6e8c8;
  --gold-50:  #fdf8ec;

  /* Green — availability, confirmations */
  --green-800: #0d4f30;
  --green-700: #126640;
  --green-600: #1a8354;
  --green-100: #cfe9dc;
  --green-50:  #eaf6f0;

  /* Neutrals — warm, never pure grey */
  --ink-900: #14181d;
  --ink-800: #232a33;
  --ink-700: #39424e;
  --ink-600: #55606e;
  --ink-500: #6f7b8a;
  --ink-400: #94a0ae;
  --ink-300: #bcc5d0;

  --rule:      #e2e0da;
  --rule-soft: #eeece7;
  --rule-navy: rgba(10, 37, 64, .1);

  --paper:  #ffffff;   /* cards sitting on the ground */
  --ground: #faf8f4;   /* the warm ivory page ground */
  --ground-deep: #f3efe8;
  /* The same ivory as bare channels, for the places that need it at partial
     alpha — a gradient fading paper over a photograph cannot take a hex. */
  --ground-rgb: 250 248 244;

  /* Type */
  --font-display: 'Newsreader', 'Iowan Old Style', 'Palatino Linotype', Georgia, serif;
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
               'Helvetica Neue', Arial, sans-serif;

  /* Fluid type scale */
  --step--1: clamp(.82rem, .79rem + .12vw, .875rem);
  --step-0:  clamp(1rem, .97rem + .16vw, 1.075rem);
  --step-1:  clamp(1.15rem, 1.09rem + .3vw, 1.32rem);
  --step-2:  clamp(1.4rem, 1.28rem + .6vw, 1.75rem);
  --step-3:  clamp(1.75rem, 1.53rem + 1.1vw, 2.45rem);
  --step-4:  clamp(2.15rem, 1.75rem + 2vw, 3.4rem);
  --step-5:  clamp(2.6rem, 1.9rem + 3.4vw, 4.6rem);

  /* Shape and depth */
  --wrap: 1200px;
  --r-sm: 8px;
  --r:    12px;
  --r-lg: 20px;
  --r-xl: 28px;

  --shadow-xs: 0 1px 2px rgba(10, 37, 64, .05);
  --shadow-sm: 0 1px 2px rgba(10, 37, 64, .05), 0 2px 6px -1px rgba(10, 37, 64, .05);
  --shadow:    0 2px 4px -1px rgba(10, 37, 64, .05), 0 8px 18px -6px rgba(10, 37, 64, .1);
  --shadow-lg: 0 4px 8px -2px rgba(10, 37, 64, .06), 0 20px 44px -12px rgba(10, 37, 64, .18);
  --shadow-xl: 0 8px 16px -4px rgba(10, 37, 64, .07), 0 34px 70px -18px rgba(10, 37, 64, .26);

  --header-h: 76px;
}

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

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

/* The blanket reduced-motion reset. It stops anything that was not written
   with the preference in mind, which is the right default.

   Two things are held out of it, and only two: the scroll reveals and the hero
   pictures. Both are opacity and nothing else under this preference — they do
   not travel, scale or spin — and both exist precisely to be what the site
   does INSTEAD of moving. Sweeping them into the reset crushed a deliberate
   half-second dissolve to a hundredth of a millisecond, which is a cut, and a
   cut is not gentler than a fade. It also made the reset the reason the whole
   site went inert for anyone with the preference on, rather than calm.

   They are excluded rather than re-asserted with a louder !important, because
   an exception that says "this rule does not apply to me" is easier to read
   than two rules shouting at each other. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *:not([data-reveal]):not(.hs-layer),
  *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--ink-700);
  background: var(--ground);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'kern' 1, 'liga' 1;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--navy-900);
  line-height: 1.12;
  letter-spacing: -.014em;
  margin: 0 0 .55em;
  text-wrap: balance;
}

h1 { font-size: var(--step-5); letter-spacing: -.026em; }
h2 { font-size: var(--step-3); letter-spacing: -.02em; }
h3 { font-size: var(--step-1); font-weight: 600; letter-spacing: -.012em; }
h4 { font-size: var(--step-0); }

p { margin: 0 0 1.15em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: var(--navy-600); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--navy-800); }

strong { font-weight: 650; color: var(--ink-800); }
em { font-style: italic; }

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

ul, ol { margin: 0 0 1.15em; padding-left: 1.2em; }
li { margin-bottom: .4em; }

code {
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: .88em; background: var(--ground-deep);
  padding: .12em .38em; border-radius: 4px; color: var(--navy-800);
}

hr { border: 0; border-top: 1px solid var(--rule); margin: 2.5rem 0; }

:focus-visible {
  outline: 2.5px solid var(--navy-600);
  outline-offset: 3px;
  border-radius: 3px;
}

::selection { background: var(--navy-900); color: #fff; }

/* Collapsed to a single pixel rather than pushed somewhere off the page.
   Parking it at left: -9999px, or moving it with a transform, both leave a
   real full-size box outside the viewport, and whether that turns into
   horizontal scroll depends on which element happens to be its containing
   block — which is why it showed up as 12px of sideways scroll on Facilities
   and nowhere else. A 1px box has nothing to overflow with. It still holds
   its place in the tab order and still opens to full size on focus. */
.skip-link {
  position: absolute; left: 0; top: 0; z-index: 300;
  /* Padding has to go too: under border-box a 1px width still leaves the
     padding standing, which kept this a 42x27 box rather than the single
     pixel intended. */
  width: 1px; height: 1px; padding: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
  background: var(--navy-900); color: #fff;
  border-radius: 0 0 var(--r-sm) 0;
  font-weight: 600; font-size: var(--step--1);
}
.skip-link:focus {
  width: auto; height: auto; overflow: visible;
  padding: .85rem 1.3rem; clip-path: none; color: #fff;
}

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

/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%; max-width: var(--wrap);
  margin-inline: auto; padding-inline: clamp(18px, 4vw, 40px);
}
.wrap-narrow { max-width: 800px; }
.wrap-mid    { max-width: 980px; }

.section { padding: clamp(3.5rem, 8vw, 7rem) 0; }
.section-tight { padding: clamp(2.5rem, 5vw, 4rem) 0; }
.section-paper { background: var(--paper); }
.section-deep  { background: var(--ground-deep); }

.section-navy {
  background: var(--navy-900); color: var(--navy-200);
  position: relative; overflow: hidden;
}
.section-navy h2, .section-navy h3 { color: #fff; }
.section-navy .lede { color: #9fb6cd; }

/* Hairline separators between same-coloured sections */
.section + .section:not(.section-navy):not(.section-deep):not(.section-paper) {
  border-top: 1px solid var(--rule-soft);
}

/* --------------------------------------------------------------------------
   Section headers
   -------------------------------------------------------------------------- */
.section-head { max-width: 46rem; margin-bottom: clamp(2rem, 4vw, 3.25rem); }
.section-head.center { margin-inline: auto; text-align: center; }
.section-head h2 { margin-bottom: .35em; }

.eyebrow {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--font-sans);
  font-size: .74rem; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--red-600);
  margin-bottom: 1rem;
}
.eyebrow::before {
  content: ''; width: 22px; height: 1.5px;
  background: currentColor; opacity: .55;
}
.section-head.center .eyebrow::after {
  content: ''; width: 22px; height: 1.5px;
  background: currentColor; opacity: .55;
}
.section-navy .eyebrow { color: var(--gold-400); }

.lede {
  font-size: var(--step-1); line-height: 1.55;
  color: var(--ink-600); font-weight: 400;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .6rem;
  padding: .85rem 1.55rem;
  font-family: var(--font-sans);
  font-size: .975rem; font-weight: 600; line-height: 1.2;
  letter-spacing: -.005em;
  border: 1.5px solid transparent; border-radius: var(--r-sm);
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background-color .18s ease, color .18s ease,
              border-color .18s ease, box-shadow .18s ease, transform .12s ease;
  min-height: 50px;
}
.btn:active { transform: translateY(1px); }
.btn svg { width: 18px; height: 18px; flex: none; }

.btn-primary {
  background: var(--navy-800); color: #fff;
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255,255,255,.1);
}
.btn-primary:hover { background: var(--navy-900); color: #fff; box-shadow: var(--shadow); }

.btn-emergency {
  background: var(--red-600); color: #fff;
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255,255,255,.13);
}
.btn-emergency:hover { background: var(--red-700); color: #fff; box-shadow: var(--shadow); }

.btn-gold { background: var(--gold-500); color: var(--navy-950); box-shadow: var(--shadow-sm); }
.btn-gold:hover { background: var(--gold-400); color: var(--navy-950); }

.btn-outline {
  background: var(--paper); color: var(--navy-800); border-color: var(--rule);
  box-shadow: var(--shadow-xs);
}
.btn-outline:hover {
  border-color: var(--navy-600); color: var(--navy-900);
  background: var(--paper); box-shadow: var(--shadow-sm);
}

.btn-ghost-light {
  background: rgba(255,255,255,.07); color: #fff;
  border-color: rgba(255,255,255,.28);
  backdrop-filter: blur(6px);
}
.btn-ghost-light:hover { background: rgba(255,255,255,.16); color: #fff; border-color: rgba(255,255,255,.5); }

.btn-whatsapp { background: #1da851; color: #fff; box-shadow: var(--shadow-sm); }
.btn-whatsapp:hover { background: #17853f; color: #fff; }

.btn-lg { padding: 1.05rem 2rem; font-size: 1.03rem; min-height: 58px; }
.btn-sm { padding: .5rem .95rem; font-size: .875rem; min-height: 40px; }
.btn-sm svg { width: 16px; height: 16px; }
.btn-block { width: 100%; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .45; pointer-events: none; }

.btn-row { display: flex; flex-wrap: wrap; gap: .75rem; }
.btn-row.center { justify-content: center; }

/* Text link with a moving arrow */
.link-arrow {
  display: inline-flex; align-items: center; gap: .4rem;
  font-weight: 600; font-size: .95rem;
  color: var(--navy-700); text-decoration: none;
}
.link-arrow svg { width: 16px; height: 16px; transition: transform .2s ease; }
.link-arrow:hover { color: var(--navy-900); }
.link-arrow:hover svg { transform: translateX(4px); }

/* --------------------------------------------------------------------------
   Emergency strip
   -------------------------------------------------------------------------- */
.emergency-bar {
  background: var(--red-700); color: #fff;
  font-size: .855rem; letter-spacing: .005em;
  padding: .48rem 0;
  position: relative; z-index: 110;
}
.emergency-bar .wrap {
  display: flex; align-items: center; justify-content: center;
  gap: .4rem 1.5rem; flex-wrap: wrap;
}
.emergency-bar-label {
  display: inline-flex; align-items: center; gap: .5rem;
  font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  font-size: .74rem;
}
.emergency-bar a {
  display: inline-flex; align-items: center; gap: .34rem;
  color: #fff; font-weight: 650; text-decoration: none; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.emergency-bar a:hover { color: #fff; text-decoration: underline; text-underline-offset: 3px; }
.emergency-bar svg { width: 14px; height: 14px; flex: none; opacity: .85; }
.emergency-bar .sep { opacity: .4; }

/* On a narrow phone the three items wrap and the separator is left stranded on
   a line of its own. Drop it, and drop the reception number too — the sticky
   bar and the contact page both carry it, and the emergency number is what
   matters at this width. */
@media (max-width: 620px) {
  .emergency-bar { font-size: .82rem; }
  .emergency-bar .wrap { gap: .35rem .9rem; }
  .emergency-bar .sep,
  .emergency-bar a.secondary { display: none; }
}

.pulse-dot {
  width: 7px; height: 7px; border-radius: 50%; background: #fff; flex: none;
  box-shadow: 0 0 0 0 rgba(255,255,255,.7);
  animation: pulse-ring 2.4s cubic-bezier(.66,0,0,1) infinite;
}
@keyframes pulse-ring {
  0%   { box-shadow: 0 0 0 0 rgba(255,255,255,.55); }
  70%  { box-shadow: 0 0 0 7px rgba(255,255,255,0); }
  100% { box-shadow: 0 0 0 0 rgba(255,255,255,0); }
}

/* --------------------------------------------------------------------------
   Masthead
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(250, 248, 244, .88);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--rule-soft);
}
/* The masthead carries more than the body copy does, so it gets its own,
   slightly wider measure. Without this the nav and buttons clip on laptops. */
.site-header .wrap { max-width: 1320px; }
.header-inner { display: flex; align-items: center; gap: 1rem; min-height: var(--header-h); }

.brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; margin-right: auto; }
.brand-mark { width: 40px; height: 40px; flex: none; }
.brand-text { display: flex; flex-direction: column; line-height: 1.08; gap: .12rem; }
/* The shared lockup, as used in the footer and on the token slip. The
   masthead's own, larger treatment is scoped to .site-header below. */
.brand-name {
  font-family: var(--font-display); font-weight: 750;
  font-size: clamp(1.45rem, 1.02rem + 1.9vw, 1.85rem); color: var(--navy-900);
  letter-spacing: -.022em; white-space: nowrap;
}
.brand-hl { color: var(--red-600); }
.site-footer .brand-hl { color: #f0857f; }
.brand-tag {
  font-family: var(--font-sans);
  font-size: .655rem; font-weight: 500; color: var(--ink-500);
  letter-spacing: .09em; text-transform: uppercase; white-space: nowrap;
}

/* The masthead name is sized to fill the fixed 76px bar rather than to a
   round number. Vertically the bar had room going spare — the lockup used
   only 45 of its 76px — so what actually caps the name is horizontal: it has
   to clear the menu button on a phone and the nine nav links on a laptop.
   That free width grows 1:1 with the viewport, which is why the middle term
   is a vw slope rather than a fixed step — the name takes exactly the room
   the bar frees up and stops. The floor holds 360px phones at the size they
   already had, where there is genuinely nothing left to give; the cap is
   where the lockup would start to overpower the nav, not where the bar runs
   out. Weight 780 is real rather than synthesized: fonts.css declares
   Newsreader's full 400–800 axis. */
.site-header .brand-text { line-height: 1; gap: .1rem; }
.site-header .brand { gap: .55rem; }
.site-header .brand-name {
  font-weight: 780;
  /* Fluid, and in rem so the name follows the reader's own text-size setting
     rather than ignoring it. The size is derived from the width the bar
     actually has — the viewport less the lockup's fixed furniture (page
     padding, badge, gaps, menu button) — because that free width grows 1:1
     with the screen while the furniture does not.

     The second term is a hard ceiling in px and it is the important one: a
     rem-based size grows when the phone's system text size is turned up, and
     an earlier version of this rule sat flush against the menu button with no
     slack, so on a real handset the name ran under it and was clipped. This
     term cannot grow with the root font, so it holds the name inside the bar
     whatever the reader's settings — and the divisors carry roughly 15% slack
     besides, for a fallback face that sets wider than Newsreader. */
  font-size: min(
    clamp(1.48rem, (100vw - 8.6rem) / 10.4, 2.4rem),
    (100vw - 134px) / 9.9
  );
  letter-spacing: -.026em;
}
/* The tagline used to be the widest thing in the lockup, pinning it at 230px
   and holding the name down with it. Letting it scale too hands that width
   back to the name, which is the part anyone actually reads. */
.site-header .brand-tag { font-size: clamp(.56rem, 1.6vw, .63rem); letter-spacing: .085em; }

.nav { display: flex; align-items: center; gap: .1rem; }
.nav a {
  position: relative;
  padding: .5rem .6rem; border-radius: var(--r-sm);
  font-size: .895rem; font-weight: 500; color: var(--ink-700);
  text-decoration: none; white-space: nowrap;
  transition: color .16s ease, background-color .16s ease;
}
.nav a:hover { color: var(--navy-900); background: rgba(10,37,64,.045); }
.nav a[aria-current="page"] { color: var(--navy-900); font-weight: 650; }
.nav a[aria-current="page"]::after {
  content: ''; position: absolute; left: .6rem; right: .6rem; bottom: .12rem;
  height: 2px; background: var(--red-600); border-radius: 2px;
}

.nav-ico { display: none; }

.nav-toggle {
  position: relative;
  display: none; width: 46px; height: 46px; flex: none;
  align-items: center; justify-content: center;
  background: var(--paper); border: 1.5px solid var(--rule);
  border-radius: var(--r-sm); cursor: pointer; color: var(--navy-800);
}
/* The two glyphs sit stacked and cross-fade with a quarter turn, so the
   button morphs instead of flicking. */
.nav-toggle svg {
  position: absolute; width: 22px; height: 22px;
  transition: opacity .18s ease, transform .26s cubic-bezier(.22, .85, .3, 1);
}
.nav-toggle .icon-close { opacity: 0; transform: rotate(-90deg) scale(.7); }
.nav-toggle[aria-expanded="true"] .icon-open  { opacity: 0; transform: rotate(90deg) scale(.7); }
.nav-toggle[aria-expanded="true"] .icon-close { opacity: 1; transform: none; }

/* Between 950 and 1200 the links stay inline but tighten up, and the brand
   yields a step of its size, so nine sections and the lockup share the bar. */
@media (min-width: 950px) and (max-width: 1199px) {
  /* Same idea as the base rule, but here the nine nav links are the
     furniture rather than the menu button, so far more width is subtracted:
     at 950 that lands on the size the name always had, and it grows back to
     full by 1200 as the links stop crowding it. */
  .site-header .brand-name {
    font-size: min(clamp(1.5rem, (100vw - 46rem) / 11, 2.15rem), (100vw - 720px) / 10.2);
  }
  .nav a { font-size: .815rem; padding: .45rem .42rem; }
  .header-inner { gap: .6rem; }
}

/* Once the name is at full size the 40px badge reads undersized beside it.
   Only from 1200 up, where the bar has width to spare — in the band below,
   a larger badge would take it straight back off the nav. */
@media (min-width: 1200px) {
  .site-header .brand-mark { width: 46px; height: 46px; }
  /* Here the full nav is the furniture, so the base rule's mobile constant
     does not describe this bar and cannot hold the name in. Its own ceiling
     does, and being in px it stays put when the root font is turned up. */
  .site-header .brand-name { font-size: min(2.4rem, (100vw - 830px) / 9.9); }
}

@media (max-width: 949px) {
  .nav-toggle { display: inline-flex; }

  /* Only the menu button shares the bar here, so the space between it and
     the lockup — and a couple of millimetres off the badge — is width the
     name can have instead. On a phone every pixel of it is spoken for. */
  .header-inner { gap: .5rem; }
  .site-header .brand { gap: .45rem; }
  .site-header .brand-mark { width: 38px; height: 38px; }

  /* The menu hangs off the sticky header itself (top: 100%), so it stays
     attached wherever the page has scrolled to — the old fixed position
     assumed the 33px top bar was still on screen and floated once it wasn't. */
  .nav {
    position: absolute; top: 100%; left: 0; right: 0;
    display: flex; flex-direction: column; align-items: stretch; gap: 2px;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    padding: .65rem clamp(12px, 3vw, 40px) .9rem;
    box-shadow: var(--shadow-lg);
    max-height: calc(100dvh - var(--header-h, 72px) - 8px);
    overflow-y: auto;
    overscroll-behavior: contain;
    opacity: 0; visibility: hidden; pointer-events: none;
    translate: 0 -10px;
    transition: opacity .2s ease, translate .26s cubic-bezier(.22, .85, .3, 1),
                visibility 0s linear .26s;
  }
  .nav.open {
    opacity: 1; visibility: visible; pointer-events: auto; translate: 0 0;
    transition: opacity .2s ease, translate .26s cubic-bezier(.22, .85, .3, 1);
  }

  /* Rows sized for thumbs: an icon well, a label, a full-width touch target. */
  .nav a {
    display: flex; align-items: center; gap: .9rem;
    padding: .62rem .7rem; border-radius: 12px;
    font-size: 1.02rem; color: var(--ink-700);
  }
  .nav a:active { background: var(--navy-50); }
  .nav a[aria-current="page"] { background: var(--navy-50); color: var(--navy-900); }
  .nav a[aria-current="page"]::after { content: none; }

  .nav-ico {
    display: grid; place-items: center; flex: none;
    width: 38px; height: 38px; border-radius: 10px;
    background: var(--navy-50); color: var(--navy-700);
    border: 1px solid var(--navy-100);
  }
  .nav-ico svg { width: 19px; height: 19px; }
  .nav a[aria-current="page"] .nav-ico {
    background: var(--navy-700); color: #fff; border-color: var(--navy-700);
  }

  /* Rows cascade in behind the panel; on close they simply go with it. */
  .nav a { opacity: 0; translate: 0 -6px;
           transition: opacity .22s ease, translate .28s cubic-bezier(.22, .85, .3, 1),
                       background-color .15s ease; }
  .nav.open a { opacity: 1; translate: 0 0; }
  .nav.open a:nth-child(2)  { transition-delay: 25ms; }
  .nav.open a:nth-child(3)  { transition-delay: 50ms; }
  .nav.open a:nth-child(4)  { transition-delay: 75ms; }
  .nav.open a:nth-child(5)  { transition-delay: 100ms; }
  .nav.open a:nth-child(6)  { transition-delay: 125ms; }
  .nav.open a:nth-child(7)  { transition-delay: 150ms; }
  .nav.open a:nth-child(8)  { transition-delay: 175ms; }
  .nav.open a:nth-child(9)  { transition-delay: 200ms; }
  .nav.open a:nth-child(n+10) { transition-delay: 220ms; }

  /* The page dims behind the open menu and stops scrolling under it. */
  html.nav-open { overflow: hidden; }
  html.nav-open body::before {
    content: ''; position: fixed; inset: 0; z-index: 99;
    background: rgba(6, 22, 38, .45);
    animation: nav-dim .25s ease both;
  }
  @keyframes nav-dim { from { opacity: 0; } to { opacity: 1; } }
}

/* Below 360px there is not room for both name and tagline, and the tagline is
   the half the hospital can spare — it is decorative, the name is not. */
@media (max-width: 359px) {
  .site-header .brand-tag { display: none; }
  .site-header .brand-mark { width: 34px; height: 34px; }
}

@media (prefers-reduced-motion: reduce) {
  .nav, .nav a, .nav-toggle svg { transition: none; }
  html.nav-open body::before { animation: none; }
}

@media (max-width: 760px) {
  .brand { min-width: 0; }
  .site-header .brand-name, .site-header .brand-tag { overflow: hidden; text-overflow: ellipsis; }
}

/* --------------------------------------------------------------------------
   Hero

   Copy and a segmented booking bar on the left; a line-art illustration of the
   hospital, sitting in a pale disc, on the right. The illustration draws
   itself in on load.
   -------------------------------------------------------------------------- */
.hero {
  position: relative; overflow: hidden; isolation: isolate;
  background:
    radial-gradient(46rem 30rem at 76% 34%, rgba(34, 89, 139, .10), transparent 64%),
    radial-gradient(32rem 24rem at 6% 92%,  rgba(201, 151, 31, .09), transparent 60%),
    linear-gradient(180deg, #f2f5fa 0%, #f7f6f2 100%);
  padding: clamp(2.25rem, 4.5vw, 4.25rem) 0 clamp(2.5rem, 5vw, 4.5rem);
}

.hero-grid { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: center; }
@media (min-width: 1000px) { .hero-grid { grid-template-columns: 1.06fr .94fr; } }

.hero-copy { max-width: 36rem; }

.hero-place {
  display: inline-flex; align-items: center; gap: .45rem;
  font-size: .82rem; font-weight: 600; color: var(--ink-600);
  margin-bottom: 1.1rem;
}
.hero-place svg { width: 15px; height: 15px; color: var(--red-600); flex: none; }

.hero h1 {
  font-size: clamp(2.4rem, 1.5rem + 4vw, 4.1rem);
  line-height: 1.05; letter-spacing: -.03em;
  font-weight: 400; color: var(--navy-900);
  margin-bottom: .35em;
}

.hero-lede {
  font-size: clamp(1.02rem, .98rem + .28vw, 1.16rem);
  line-height: 1.6; color: var(--ink-600);
  max-width: 32rem; margin-bottom: 1.9rem;
}

/* --------------------------------------------------------------------------
   Segmented booking bar
   -------------------------------------------------------------------------- */
.findbar {
  display: flex; align-items: stretch;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: .4rem .4rem .4rem 1.15rem;
  box-shadow: var(--shadow-lg);
  max-width: 41rem;
}

.findbar-field {
  display: flex; flex-direction: column; justify-content: center;
  flex: 1 1 0; min-width: 0; padding: .35rem .55rem;
}
/* Doctor names run much longer than "Today" or "Evening". */
.findbar-field:first-child { flex: 1.7 1 0; }

.findbar-field select {
  appearance: none; width: 100%;
  border: 0; background: transparent; padding: 0 1.1rem 0 0;
  font: inherit; font-size: .93rem; font-weight: 600;
  color: var(--navy-900); cursor: pointer;
  text-overflow: ellipsis;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2317456f' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right center; background-size: 15px;
}
.findbar-field select:focus { outline: none; }
.findbar-field:focus-within { border-radius: var(--r); box-shadow: 0 0 0 3px rgba(34,89,139,.16); }

.findbar-sep { width: 1px; background: var(--rule); margin: .55rem 0; flex: none; }

.findbar-go {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  flex: none; padding: 0 1.6rem; min-height: 52px;
  border: 0; border-radius: 999px;
  background: var(--red-600); color: #fff;
  font: inherit; font-size: .96rem; font-weight: 650;
  cursor: pointer;
  transition: background-color .18s ease, transform .12s ease;
}
.findbar-go:hover { background: var(--red-700); }
.findbar-go:active { transform: translateY(1px); }
.findbar-go svg { width: 17px; height: 17px; }

/* Live line under the bar */
.hero-live {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  margin: 1.15rem 0 0; font-size: .89rem; color: var(--ink-600);
}
.hero-live strong { color: var(--navy-900); font-weight: 650; }
.live-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--green-600); flex: none;
  box-shadow: 0 0 0 0 rgba(26, 131, 84, .6);
  animation: live-ping 2.6s cubic-bezier(.66, 0, 0, 1) infinite;
}
@keyframes live-ping {
  0%   { box-shadow: 0 0 0 0 rgba(26, 131, 84, .5); }
  70%  { box-shadow: 0 0 0 7px rgba(26, 131, 84, 0); }
  100% { box-shadow: 0 0 0 0 rgba(26, 131, 84, 0); }
}

/* --------------------------------------------------------------------------
   Illustration

   An axonometric drawing of the building that draws itself in, holds, fades
   and repeats. The loop is split in two so the timing stays sane: each path
   owns its own draw-on and fill-in, staggered by stage, while the parent owns
   the global fade — otherwise every path would need its own fade keyframes to
   disappear together.
   -------------------------------------------------------------------------- */
.hero-art {
  position: relative;
  display: grid; place-items: center;
  padding: clamp(.25rem, 1vw, .75rem);
}
.hero-art-disc {
  position: absolute; z-index: 0;
  width: min(80%, 23rem); aspect-ratio: 1;
  border-radius: 50%;
  background:
    radial-gradient(circle at 40% 32%, rgba(255,255,255,.9), transparent 60%),
    linear-gradient(158deg, rgba(34,89,139,.14), rgba(34,89,139,.04));
}
.hero-art-disc::after {
  content: ''; position: absolute; inset: -6%;
  border-radius: 50%; border: 1px solid rgba(34,89,139,.1);
}

.draw-art {
  position: relative; z-index: 1;
  /* Wider than the disc on purpose — the building breaking the circle reads
     as deliberate, where a drawing floating inside it reads as undersized. */
  width: min(100%, 36rem); height: auto;
  color: var(--navy-700);
  overflow: visible;
  animation: art-cycle 11s ease-in-out infinite;
}

.draw-art path {
  fill: none;
  stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1; stroke-dashoffset: 1;
  animation: draw-line 11s ease-out infinite, fill-in 11s ease-out infinite;
}

/* Tonal faces: top lightest, front mid, receding side darkest. --fo is the
   fill opacity the fill-in keyframes animate up to. */
.draw-art .f-top   { fill: #ffffff; --fo: .95; }
.draw-art .f-front { fill: #e9eff7; --fo: 1;   }
.draw-art .f-side  { fill: #d2dfee; --fo: 1;   }
.draw-art .ln-win  { fill: #ffffff; --fo: .8; stroke-width: 1.7; }
.draw-art .ln-win-lit { fill: var(--gold-100); --fo: .95; stroke-width: 1.7; }
.draw-art .ln-thin { stroke-width: 1.6; }
.draw-art .ln-hatch { stroke-width: 1.1; opacity: .55; }
.draw-art .ln-mark { stroke: var(--red-600); stroke-width: 3; }

/* Stage stagger. Same duration everywhere, so the phases stay locked. */
.draw-art .g1 { animation-delay: 0s,    0s;    }
.draw-art .g2 { animation-delay: .35s,  .35s;  }
.draw-art .g3 { animation-delay: .7s,   .7s;   }
.draw-art .g4 { animation-delay: 1.05s, 1.05s; }
.draw-art .g5 { animation-delay: 1.4s,  1.4s;  }
.draw-art .g6 { animation-delay: 1.75s, 1.75s; }

@keyframes draw-line {
  0%          { stroke-dashoffset: 1; }
  24%, 100%   { stroke-dashoffset: 0; }
}
@keyframes fill-in {
  0%, 16%     { fill-opacity: 0; }
  34%, 100%   { fill-opacity: var(--fo, 0); }
}
@keyframes art-cycle {
  0%          { opacity: 0; }
  5%, 86%     { opacity: 1; }
  96%, 100%   { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .draw-art,
  .draw-art path { animation: none; }
  .draw-art path { stroke-dashoffset: 0; fill-opacity: var(--fo, 0); }
  .live-dot { animation: none; }
}

/* --------------------------------------------------------------------------
   Quick links
   -------------------------------------------------------------------------- */
.quicklinks { background: var(--paper); border-bottom: 1px solid var(--rule-soft); padding: 1.75rem 0; }

.quick-rail {
  display: grid; gap: .8rem;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}
.quick {
  display: flex; flex-direction: column; align-items: center; gap: .7rem;
  padding: 1.15rem .7rem;
  border: 1px solid var(--rule); border-radius: var(--r-lg);
  background: var(--paper); text-decoration: none;
  text-align: center;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.quick:hover {
  border-color: var(--navy-200); box-shadow: var(--shadow);
  transform: translateY(-3px);
}
.quick-icon {
  display: grid; place-items: center;
  width: 46px; height: 46px; border-radius: 13px;
  background: var(--navy-50); border: 1px solid var(--navy-100);
  color: var(--navy-700);
  transition: transform var(--flip-time) var(--flip-ease),
              background-color .18s ease, color .18s ease, border-color .18s ease;
}
.quick-icon svg { width: 23px; height: 23px; }
.quick:hover .quick-icon { background: var(--navy-700); color: #fff; border-color: var(--navy-700); }
.quick > span:last-child {
  font-size: .855rem; font-weight: 600; color: var(--navy-900); line-height: 1.35;
}

@media (max-width: 1080px) {
  .quick-rail {
    display: flex; gap: .7rem;
    overflow-x: auto; scroll-snap-type: x mandatory;
    padding-bottom: .5rem; margin-inline: calc(clamp(18px, 4vw, 40px) * -1);
    padding-inline: clamp(18px, 4vw, 40px);
    scrollbar-width: none;
  }
  .quick-rail::-webkit-scrollbar { display: none; }
  .quick { flex: 0 0 auto; width: 8.5rem; scroll-snap-align: start; }
}

/* --------------------------------------------------------------------------
   Hero on smaller screens
   -------------------------------------------------------------------------- */
@media (max-width: 999px) {
  .hero-copy { max-width: 100%; }
  /* On one column the headline and the booking bar come first — finding a
     doctor is what the visit is for — and the drawing follows as a flourish
     instead of pushing the form below the fold. */
  .hero-art { order: 1; padding-block: .25rem 0; margin-top: 1.5rem; }
  .draw-art { width: min(100%, 26rem); }
  .hero-art-disc { width: min(88%, 21rem); }
}

@media (max-width: 760px) {
  .hero { padding-block: 1.75rem 2.25rem; }
  .hero h1 { font-size: clamp(2.1rem, 1.4rem + 3.2vw, 2.7rem); }
  .hero-lede { font-size: 1rem; margin-bottom: 1.5rem; }

  /* The pill cannot hold three fields and a button at this width, so it
     becomes a stacked card with a full-width action. */
  .findbar {
    flex-direction: column; align-items: stretch;
    border-radius: var(--r-lg); padding: .5rem;
    box-shadow: var(--shadow);
  }
  .findbar-field { padding: .6rem .75rem; }
  .findbar-sep { width: auto; height: 1px; margin: 0 .75rem; }
  .findbar-go { width: 100%; margin-top: .4rem; border-radius: var(--r); min-height: 50px; }
  .draw-art { width: min(100%, 19rem); }
  .hero-art-disc { width: min(100%, 17rem); }
}

/* --------------------------------------------------------------------------
   Facility mosaic

   Not a row of equals. The first tile is twice the size and carries the
   hospital's navy, the next two are wide, the rest are compact — so the eye
   is told where to start instead of being handed six identical boxes.

   Three layouts rather than one squeezed three ways. On a phone the tiles lie
   down: icon beside the text rather than above it, which is what turns six
   full-height boxes into a list you can actually scroll past. From 520px they
   stand up into a four-column mosaic, and from 900px into the full six-column
   one where the feature tile occupies two rows.

   The spans are written to survive a different number of tiles, because the
   list is editable in the admin panel: whatever the count, the first is the
   feature, the next two are wide, and everything after fills in two columns
   at a time with dense packing closing the gaps.
   -------------------------------------------------------------------------- */
.fac-bento {
  display: grid;
  gap: clamp(.7rem, 1.5vw, 1.1rem);
  grid-template-columns: 1fr;
}

.fac {
  position: relative; overflow: hidden;
  display: flex; gap: 1rem; align-items: flex-start;
  padding: clamp(1.1rem, 2.1vw, 1.6rem);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xs);
  transition: transform .22s ease, box-shadow .22s ease, border-color .22s ease;
}
.fac:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
  border-color: var(--navy-200);
}

.fac-icon {
  display: grid; place-items: center; flex: none;
  width: 46px; height: 46px; border-radius: 13px;
  background: var(--navy-50);
  border: 1px solid var(--navy-100);
  color: var(--navy-700);
  transition: background-color .22s ease, color .22s ease, transform .22s ease;
}
.fac-icon svg { width: 22px; height: 22px; }
.fac:hover .fac-icon { background: var(--navy-800); border-color: var(--navy-800); color: var(--gold-400); }

.fac-text { min-width: 0; }
.fac h3 { font-size: 1.03rem; margin: 0 0 .32em; line-height: 1.3; }
.fac p  { font-size: .88rem; color: var(--ink-600); margin: 0; line-height: 1.55; }

/* The feature tile. Navy, so it reads as the hospital speaking rather than as
   one more card, with a soft light behind the icon corner. */
.fac:first-child {
  background:
    radial-gradient(120% 90% at 12% 0%, rgba(224, 182, 78, .16), transparent 60%),
    linear-gradient(155deg, var(--navy-900), var(--navy-950));
  border-color: transparent;
}
.fac:first-child h3 { color: #fff; font-size: clamp(1.15rem, 1.6vw, 1.45rem); }
/* Measured on the navy: this is the lightest step that clears 4.5:1 there. */
.fac:first-child p  { color: #b9cbdd; font-size: .95rem; }
.fac:first-child .fac-icon {
  width: 54px; height: 54px; border-radius: 15px;
  background: rgba(255, 255, 255, .09);
  border-color: rgba(255, 255, 255, .16);
  color: var(--gold-400);
}
.fac:first-child .fac-icon svg { width: 26px; height: 26px; }
.fac:first-child:hover .fac-icon {
  background: var(--gold-400); border-color: var(--gold-400); color: var(--navy-950);
}

/* Standing up: from here the tiles are columns, not rows. */
@media (min-width: 520px) {
  .fac-bento {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-auto-flow: dense;
  }
  .fac { grid-column: span 2; flex-direction: column; gap: 1.05rem; }
  .fac:first-child { grid-column: 1 / -1; }
}

@media (min-width: 900px) {
  .fac-bento { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .fac { grid-column: span 2; }
  /* Two rows tall, and composed rather than centred: the mark sits at the top
     of the tile and the words at the bottom, which reads as a poster instead
     of a paragraph floating in a box. */
  .fac:first-child { grid-column: span 3; grid-row: span 2; justify-content: space-between; }
  .fac:nth-child(2),
  .fac:nth-child(3) { grid-column: span 3; }
}

/* --------------------------------------------------------------------------
   Grids and cards
   -------------------------------------------------------------------------- */
.grid { display: grid; gap: clamp(1rem, 2vw, 1.5rem); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(285px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.grid-split { grid-template-columns: 1fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
@media (min-width: 900px) { .grid-split { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px) { .grid-split.lean-left { grid-template-columns: 1.15fr .85fr; } }

.card {
  position: relative;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: clamp(1.4rem, 2.5vw, 1.85rem);
  box-shadow: var(--shadow-xs);
  transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.card > :last-child { margin-bottom: 0; }
.card h3 { margin-bottom: .4em; }
.card p { font-size: .955rem; color: var(--ink-600); line-height: 1.6; }

.card-link { display: block; text-decoration: none; color: inherit; }
.card-link:hover {
  border-color: var(--navy-200);
  box-shadow: var(--shadow);
  transform: translateY(-3px);
}
.card-link:hover h3 { color: var(--navy-700); }

.card-icon {
  display: grid; place-items: center;
  width: 52px; height: 52px; border-radius: 14px;
  margin-bottom: 1.25rem;
  background: var(--navy-50); color: var(--navy-700);
  border: 1px solid var(--navy-100);
  transition: transform var(--flip-time) var(--flip-ease),
              background-color .18s ease, color .18s ease, border-color .18s ease;
}
.card-icon svg { width: 25px; height: 25px; }
.card-icon.red   { background: var(--red-50);   color: var(--red-600);   border-color: var(--red-100); }
.card-icon.gold  { background: var(--gold-50);  color: var(--gold-600);  border-color: var(--gold-100); }
.card-icon.green { background: var(--green-50); color: var(--green-700); border-color: var(--green-100); }

/* A card carrying a photograph instead of an icon. The image runs the full
   width of the card and is cropped to a fixed ratio, so six cards line up
   whatever shape the photographs happen to be. */
.card-photo {
  display: block;
  /* Pull out to the card's edges — matches .card's own padding. */
  --card-pad: clamp(1.4rem, 2.5vw, 1.85rem);
  margin: calc(-1 * var(--card-pad)) calc(-1 * var(--card-pad)) 1.35rem;
  overflow: hidden;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: var(--navy-50);
}
.card-photo img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 9; object-fit: cover;
  transition: transform .45s cubic-bezier(.22,.85,.3,1);
}
.card-link:hover .card-photo img { transform: scale(1.045); }
@media (prefers-reduced-motion: reduce) {
  .card-link:hover .card-photo img { transform: none; }
}

.card-more { display: inline-flex; align-items: center; gap: .4rem; margin-top: 1.15rem;
  font-weight: 600; font-size: .92rem; color: var(--navy-700); }
.card-more svg { width: 16px; height: 16px; transition: transform .2s ease; }
.card-link:hover .card-more svg { transform: translateX(4px); }

/* Numbered feature card */
.card-num { counter-increment: cardnum; }
.card-num::before {
  content: counter(cardnum, decimal-leading-zero);
  position: absolute; top: 1.35rem; right: 1.5rem;
  font-family: var(--font-display); font-size: 1.5rem;
  color: var(--rule); font-weight: 600;
}

/* --------------------------------------------------------------------------
   Doctor cards

   Laid out as a portrait row rather than a card with a large image well.
   Until real photographs arrive an empty well reads as a broken image; a
   framed circular portrait reads as a deliberate placeholder.
   -------------------------------------------------------------------------- */
.doctor-card {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: clamp(1.4rem, 3vw, 1.9rem);
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-xs);
  transition: box-shadow .2s ease, transform .2s ease, border-color .2s ease;
}
.doctor-card:hover { box-shadow: var(--shadow); transform: translateY(-3px); border-color: var(--navy-200); }

/* A hairline of the hospital's own colours along the top edge, drawn in on
   hover. Scaled from the left rather than faded in, so it reads as the card
   being underlined rather than as a border blinking on. */
.doctor-card::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 3px;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: linear-gradient(90deg, var(--red-600), var(--gold-500));
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .32s cubic-bezier(.2, .8, .3, 1);
}
.doctor-card:hover::before,
.doctor-card:focus-within::before { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .doctor-card::before { transition: none; }
}

.doctor-top {
  display: flex; gap: 1.15rem; align-items: center;
  padding-bottom: 1.15rem; margin-bottom: 1.15rem;
  border-bottom: 1px solid var(--rule-soft);
}

.doctor-portrait {
  position: relative; flex: none;
  width: 104px; height: 104px; border-radius: 50%;
  overflow: hidden;
  background: var(--navy-50);
  border: 1px solid var(--navy-100);
  box-shadow: 0 0 0 5px var(--ground);
}
.doctor-portrait img,
.doctor-portrait > svg { width: 100%; height: 100%; object-fit: cover; display: block; }

.doctor-head { min-width: 0; }
.doctor-head h3 { margin-bottom: .3em; font-size: var(--step-1); line-height: 1.2; }
.doctor-quals {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: .72rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--red-700);
  background: var(--red-50); border: 1px solid var(--red-100);
  padding: .16rem .5rem; border-radius: 4px;
  margin: 0;
}
.doctor-head h3 a { color: inherit; text-decoration: none; }
.doctor-head h3 a:hover { color: var(--red-700); }

/* The speciality sits inside the head now rather than below the whole block,
   so name, degree and field read as one identity. */
.doctor-spec {
  font-size: .92rem; color: var(--ink-600);
  margin: .5rem 0 0; line-height: 1.5;
}

/* Only the fields the hospital has actually entered reach this list, so it is
   either populated or absent — never a row of blanks. */
.doctor-facts {
  display: flex; flex-wrap: wrap; gap: .4rem .5rem;
  list-style: none; margin: 0 0 1.05rem; padding: 0;
}
.doctor-facts li {
  display: inline-flex; align-items: center; gap: .38rem;
  font-size: .78rem; color: var(--ink-600);
  background: var(--ground); border: 1px solid var(--rule);
  padding: .26rem .55rem; border-radius: 999px;
}
.doctor-facts svg { width: 14px; height: 14px; color: var(--ink-500); flex: none; }

/* --------------------------------------------------------------------------
   Doctor card body

   A line of the doctor's own background, then the conditions patients come to
   them for. A session timetable and token meters used to sit here — accurate,
   but they turned a "meet our doctors" section into the reception desk's own
   screen. Availability belongs on the booking page; this card is for choosing
   who, not when.
   -------------------------------------------------------------------------- */
.doctor-bio {
  font-size: .92rem; color: var(--ink-600); line-height: 1.62;
  margin: 0 0 1.05rem;
}

.doctor-treats { margin: 0 0 1.15rem; }
.doctor-treats h4 {
  font-family: var(--font-sans);
  font-size: .7rem; font-weight: 700; letter-spacing: .11em;
  text-transform: uppercase; color: var(--ink-500);
  margin: 0 0 .5rem;
}
.doctor-treats ul {
  display: flex; flex-wrap: wrap; gap: .38rem;
  list-style: none; margin: 0; padding: 0;
}
.doctor-treats li {
  font-size: .8rem; color: var(--navy-800);
  background: var(--navy-50); border: 1px solid var(--navy-100);
  padding: .3rem .6rem; border-radius: 999px;
}
/* The overflow count is a quieter thing than a condition, so it is drawn as
   one: no fill, just a count pointing at the profile. */
.doctor-treats li.is-more {
  background: none; border-color: var(--rule); color: var(--ink-600);
}

/* Pinned to the bottom, so two cards whose bodies differ in length still line
   their buttons up with each other. */
.doctor-foot { margin-top: auto; }

/* The one piece of live state left on the card: whether they are consulting
   today. A day, and nothing finer — the moment this names a session or a time
   it is the timetable again. */
.doctor-avail {
  display: flex; align-items: center; gap: .5rem;
  margin: 0 0 .9rem;
  font-size: .84rem; font-weight: 600; color: var(--ink-600);
}
.doctor-dot {
  flex: none; width: 8px; height: 8px; border-radius: 50%;
  background: currentColor;
}
.doctor-avail.is-today { color: var(--green-700); }

/* Pinned to the bottom, so two cards whose bodies differ in height still line
   their buttons up. */
.doctor-actions {
  display: flex; flex-wrap: wrap; gap: .55rem;
  margin-top: auto;
}
.doctor-actions .btn { flex: 1 1 10rem; justify-content: center; }

/* On a phone the head stacks: side by side leaves the name a column too
   narrow, and "Dr. Gundavarapu Venkatesh" breaks across three lines beside a
   104px portrait. Stacked it gets the full width and reads in two. */
@media (max-width: 520px) {
  .doctor-top { flex-direction: column; align-items: flex-start; gap: .9rem; }
  .doctor-portrait { width: 84px; height: 84px; }
  .doctor-actions .btn { flex-basis: 100%; }
}

/* --------------------------------------------------------------------------
   Doctor cards (Doctors index)

   A row per doctor: portrait, who they are and what they treat, then the two
   things a patient came to do — read the profile or take a token.
   -------------------------------------------------------------------------- */
.doc-cards { display: grid; gap: 1.1rem; }

.doc-card {
  display: grid; gap: 1.25rem;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  padding: clamp(1.2rem, 2.6vw, 1.6rem);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xs);
  transition: box-shadow .2s ease, border-color .2s ease, transform .2s ease;
}
.doc-card:hover { box-shadow: var(--shadow); border-color: var(--navy-200); transform: translateY(-2px); }
@media (min-width: 800px) {
  .doc-card { grid-template-columns: auto minmax(0, 1fr) 15rem; }
}

.doc-card-portrait {
  flex: none; width: 96px; height: 96px;
  border-radius: 50%; overflow: hidden;
  background: var(--navy-50); border: 1px solid var(--navy-100);
  box-shadow: 0 0 0 5px var(--ground);
}
.doc-card-portrait img,
.doc-card-portrait > svg { display: block; width: 100%; height: 100%; object-fit: cover; }

.doc-card-body { min-width: 0; }
.doc-card-body h3 { font-size: var(--step-1); margin-bottom: .2em; }
.doc-card-body h3 a { color: inherit; text-decoration: none; }
.doc-card-body h3 a:hover { color: var(--navy-600); text-decoration: underline; }
.doc-card-quals {
  display: inline-block; margin: 0 0 .5rem;
  font-family: var(--font-sans);
  font-size: .72rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--red-700); background: var(--red-50);
  border: 1px solid var(--red-100); border-radius: 4px; padding: .16rem .5rem;
}
.doc-card-role { margin: 0 0 .8rem; font-size: .96rem; color: var(--ink-600); }

.doc-card-meta {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: .45rem .95rem;
  font-size: .86rem; color: var(--ink-600);
}
.doc-card-meta li { display: inline-flex; align-items: center; gap: .38rem; margin: 0; }
.doc-card-meta svg { width: 15px; height: 15px; flex: none; color: var(--navy-500); }

/* Below the three-column breakpoint the buttons span the card's full width. */
.doc-card-actions { display: grid; gap: .55rem; grid-column: 1 / -1; }
@media (min-width: 800px) { .doc-card-actions { grid-column: auto; } }

@media (max-width: 520px) {
  /* One column: portrait, then details, then two full-width buttons. */
  .doc-card { grid-template-columns: 1fr; }
  .doc-card-portrait { width: 76px; height: 76px; }
}

/* --------------------------------------------------------------------------
   Doctor profile
   -------------------------------------------------------------------------- */
.profile-layout { display: grid; gap: 1.75rem; align-items: start; }
@media (min-width: 900px) { .profile-layout { grid-template-columns: 20.5rem minmax(0, 1fr); } }

.profile-card {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  padding: clamp(1.35rem, 3vw, 1.8rem);
  text-align: center;
}
@media (min-width: 900px) { .profile-aside { position: sticky; top: 1.5rem; } }

.profile-portrait {
  width: 132px; height: 132px; margin: 0 auto 1.1rem;
  border-radius: 50%; overflow: hidden;
  background: var(--navy-50); border: 1px solid var(--navy-100);
  box-shadow: 0 0 0 6px var(--ground);
}
.profile-portrait img,
.profile-portrait > svg { display: block; width: 100%; height: 100%; object-fit: cover; }

.profile-name { font-size: var(--step-2); margin-bottom: .3rem; }
.profile-quals {
  display: inline-block; margin: 0 0 1.35rem;
  font-family: var(--font-sans);
  font-size: .72rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--red-700); background: var(--red-50);
  border: 1px solid var(--red-100); border-radius: 4px; padding: .16rem .5rem;
}

.profile-facts { margin: 0 0 1.35rem; text-align: left; }
.profile-facts > div {
  display: grid; gap: .1rem;
  padding: .7rem 0;
  border-top: 1px solid var(--rule-soft);
}
.profile-facts > div:first-child { border-top: 0; padding-top: 0; }
.profile-facts dt {
  font-size: .72rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-500);
}
.profile-facts dd { margin: 0; font-size: .94rem; color: var(--navy-900); }
.profile-timing { display: block; }

.profile-card .btn + .btn { margin-top: .55rem; }

.profile-block { margin-bottom: 2.25rem; }
.profile-block:last-of-type { margin-bottom: 1.75rem; }
.profile-block h2 {
  font-size: var(--step-2); margin-bottom: .8rem;
  padding-bottom: .6rem; border-bottom: 1px solid var(--rule);
}

.profile-list { list-style: none; margin: 0; padding: 0; }
@media (min-width: 620px) { .profile-list.two-col { columns: 2; column-gap: 2rem; } }
.profile-list li {
  display: flex; align-items: baseline; gap: .6rem;
  margin: 0; padding: .5rem 0;
  font-size: .95rem; color: var(--ink-700);
  break-inside: avoid;
}
.profile-list svg {
  width: 15px; height: 15px; flex: none;
  color: var(--gold-600); transform: translateY(2px);
}

/* --------------------------------------------------------------------------
   Service lists
   -------------------------------------------------------------------------- */
.service-list { list-style: none; padding: 0; margin: 0; display: grid; gap: .5rem; }
.service-list li {
  display: flex; align-items: flex-start; gap: .7rem;
  padding: .7rem .95rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  font-size: .94rem; margin: 0; color: var(--ink-700);
  transition: border-color .16s ease, transform .16s ease;
}
.service-list li:hover { border-color: var(--navy-200); transform: translateX(2px); }
.service-list svg { width: 17px; height: 17px; flex: none; margin-top: 3px; color: var(--green-600); }
@media (min-width: 680px) { .service-list.two-col { grid-template-columns: 1fr 1fr; } }

/* --------------------------------------------------------------------------
   Department panels (Services)

   Two long tick-lists side by side read as a spreadsheet and, with 14 items
   against 12, sat at different heights. Each department is a panel instead: a
   tinted header carrying the consultant who runs it, the list ruled and dense
   in the middle, and a booking link at the foot so the section leads somewhere.
   -------------------------------------------------------------------------- */
.dept-grid { display: grid; gap: 1.6rem; }
/* Stretch rather than start-align: the lists differ in length, and letting
   the panels match height keeps both booking links on the same line. */
@media (min-width: 940px) { .dept-grid { grid-template-columns: 1fr 1fr; } }

.dept {
  display: flex; flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: box-shadow .22s ease, border-color .22s ease, transform .22s ease;
}
.dept:hover { box-shadow: var(--shadow-lg); border-color: var(--navy-100); transform: translateY(-3px); }

.dept-head {
  position: relative;
  padding: clamp(1.5rem, 3vw, 2rem) clamp(1.4rem, 3vw, 2rem) 1.5rem;
  background: linear-gradient(168deg, var(--navy-50) 0%, var(--paper) 78%);
}
/* A hairline of the department's colour along the top edge. */
.dept-head::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--navy-700), var(--navy-200));
}
.dept-green .dept-head { background: linear-gradient(168deg, var(--green-50) 0%, var(--paper) 78%); }
.dept-green .dept-head::before { background: linear-gradient(90deg, var(--green-700), var(--green-100)); }

.dept-head .card-icon { margin-bottom: 1.1rem; }
.dept-head .eyebrow { display: block; margin-bottom: .35rem; color: var(--navy-600); }
.dept-green .dept-head .eyebrow { color: var(--green-700); }
.dept-head h2 { font-size: var(--step-2); margin-bottom: .55rem; }
.dept-lede { margin: 0; font-size: .96rem; color: var(--ink-600); max-width: 44ch; }

.dept-doc {
  display: flex; align-items: center; gap: .8rem;
  margin-top: 1.35rem; padding-top: 1.2rem;
  border-top: 1px dashed var(--rule);
}
.dept-doc-portrait {
  width: 46px; height: 46px; flex: none;
  border-radius: 50%; overflow: hidden;
  border: 1px solid var(--rule); background: var(--navy-50);
}
.dept-doc-portrait svg { display: block; width: 100%; height: 100%; }
.dept-doc-text strong { display: block; font-size: .95rem; color: var(--navy-900); line-height: 1.3; }
.dept-doc-text > span { font-size: .82rem; color: var(--ink-600); }

.dept-body { flex: 1; padding: 1.4rem clamp(1.4rem, 3vw, 2rem) 1.5rem; }
.dept-count {
  margin: 0 0 .5rem;
  font-size: .72rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-500);
}
.dept-count strong { font-size: .95rem; color: var(--navy-800); letter-spacing: 0; }

.dept-list { list-style: none; margin: 0; padding: 0; }
.dept-list li {
  display: flex; align-items: baseline; gap: .75rem;
  margin: 0; padding: .62rem .6rem .62rem .55rem;
  border-top: 1px solid var(--rule-soft);
  border-radius: var(--r-sm);
  font-size: .94rem; color: var(--ink-700);
  transition: background-color .16s ease, padding-left .16s ease, color .16s ease;
}
.dept-list li:hover { background: var(--navy-50); padding-left: .9rem; color: var(--navy-900); }
.dept-green .dept-list li:hover { background: var(--green-50); color: var(--green-800); }

.dept-mark {
  width: 7px; height: 7px; flex: none;
  border-radius: 50%; background: var(--navy-200);
  transition: transform .16s ease, background-color .16s ease, box-shadow .16s ease;
}
.dept-green .dept-mark { background: var(--green-100); }
.dept-list li:hover .dept-mark {
  background: var(--navy-600); box-shadow: 0 0 0 4px var(--navy-100);
}
.dept-green .dept-list li:hover .dept-mark {
  background: var(--green-600); box-shadow: 0 0 0 4px var(--green-100);
}

.dept-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: .9rem;
  padding: 1.15rem clamp(1.4rem, 3vw, 2rem);
  border-top: 1px solid var(--rule);
  background: var(--ground);
}
.dept-foot-note { font-size: .83rem; color: var(--ink-600); }

@media (prefers-reduced-motion: reduce) {
  .dept:hover { transform: none; }
  .dept-list li:hover { padding-left: .55rem; }
}

/* --------------------------------------------------------------------------
   Offers
   -------------------------------------------------------------------------- */
.offer-strip {
  background: linear-gradient(103deg, var(--gold-50) 0%, #fffdf7 55%, var(--gold-50) 100%);
  border-block: 1px solid var(--gold-100);
  padding: clamp(2rem, 4vw, 3rem) 0;
}
.offer-item { display: flex; gap: 1.1rem; align-items: flex-start; }
.offer-item .card-icon { margin-bottom: 0; }
.offer-item h3 { font-size: var(--step-1); margin-bottom: .25em; }
.offer-item p { font-size: .93rem; margin: 0; color: var(--ink-600); }

/* --------------------------------------------------------------------------
   Tables
   -------------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { width: 100%; border-collapse: collapse; font-size: .965rem; min-width: 420px; }
caption { text-align: left; font-weight: 600; color: var(--ink-500); padding-bottom: .75rem; font-size: .92rem; }
th, td { padding: .95rem 1.15rem; text-align: left; border-bottom: 1px solid var(--rule-soft); }
thead th {
  background: var(--navy-900); color: #fff;
  font-family: var(--font-sans);
  font-weight: 600; font-size: .74rem; letter-spacing: .11em; text-transform: uppercase;
}
thead th:last-child, td.amount { text-align: right; }
td.amount {
  font-family: var(--font-display);
  font-weight: 600; font-size: 1.08rem; color: var(--navy-900);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
tbody tr:last-child td, tbody tr:last-child th { border-bottom: 0; }
tbody tr { transition: background-color .14s ease; }
tbody tr:hover { background: var(--navy-50); }

.table-card {
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  /* The table below keeps a 380px floor so its columns stay readable, which is
     wider than a phone's content column. Hiding that overflow clipped the last
     column off the tariff and facilities tables with no way to reach it — and
     still pushed the page sideways. Scrolling the card is what the rest of the
     site already does with .table-wrap; the radius keeps clipping either way. */
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  background: var(--paper);
  box-shadow: var(--shadow-xs);
}
.table-card table { min-width: 380px; }
/* On a phone the 380px floor is wider than the content column, which pushed
   the amount off the card edge and made reading a price a swipe. These tables
   are two columns of short text; letting them use the width available fits
   them whole, and the scroll above stays as the safety net for anything that
   still cannot. */
@media (max-width: 620px) {
  .table-card table { min-width: 0; }
}

/* --------------------------------------------------------------------------
   Notices
   -------------------------------------------------------------------------- */
.notice {
  display: flex; gap: .9rem; align-items: flex-start;
  padding: 1.1rem 1.3rem;
  border-radius: var(--r);
  border: 1px solid var(--rule);
  border-left-width: 3px;
  background: var(--paper);
  font-size: .95rem; line-height: 1.6;
  margin-bottom: 1.5rem;
}
.notice svg { width: 20px; height: 20px; flex: none; margin-top: 2px; }
.notice p { margin: 0; }
.notice strong { display: block; color: var(--navy-900); margin-bottom: .15rem; font-weight: 650; }

.notice-emergency {
  background: var(--red-50); border-color: var(--red-100);
  border-left-color: var(--red-600); color: var(--red-800);
}
.notice-emergency svg { color: var(--red-600); }
.notice-emergency strong { color: var(--red-800); }
.notice-emergency a { color: var(--red-700); font-weight: 650; }

.notice-info {
  background: var(--navy-50); border-color: var(--navy-100);
  border-left-color: var(--navy-600);
}
.notice-info svg { color: var(--navy-600); }

.notice-success {
  background: var(--green-50); border-color: var(--green-100);
  border-left-color: var(--green-600); color: var(--green-800);
}
.notice-success svg { color: var(--green-600); }
.notice-success strong { color: var(--green-800); }

.notice-warn {
  background: var(--gold-50); border-color: var(--gold-100);
  border-left-color: var(--gold-500); color: var(--gold-700);
}
.notice-warn svg { color: var(--gold-600); }
.notice-warn strong { color: var(--gold-700); }

/* --------------------------------------------------------------------------
   Map and contact
   -------------------------------------------------------------------------- */
.map-embed {
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  overflow: hidden; background: var(--navy-50); line-height: 0;
  box-shadow: var(--shadow-sm);
}
.map-embed iframe { width: 100%; height: clamp(300px, 42vw, 440px); border: 0; display: block; }

.contact-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 1.15rem; }
.contact-list li { display: flex; gap: .95rem; align-items: flex-start; margin: 0; }
.contact-list .card-icon { width: 44px; height: 44px; border-radius: 12px; margin: 0; }
.contact-list .card-icon svg { width: 21px; height: 21px; }
.contact-list strong { display: block; color: var(--navy-900); font-size: .93rem; margin-bottom: .1rem; }
.contact-list a { text-decoration: none; font-weight: 600; color: var(--navy-700); }
.contact-list a:hover { text-decoration: underline; }
.contact-list span { font-size: .94rem; color: var(--ink-600); }

/* --------------------------------------------------------------------------
   Page hero (inner pages)
   -------------------------------------------------------------------------- */
.page-hero {
  position: relative; overflow: hidden; isolation: isolate;
  background: var(--navy-950);
  color: #a8bed5;
  padding: clamp(2.75rem, 6vw, 4.75rem) 0;
}
/* The tint. Without artwork it carries the banner on its own; with artwork
   behind it, it drops to a scrim so the drawing still reads through. */
.page-hero::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background-image:
    radial-gradient(40rem 24rem at 82% 0%, rgba(34,89,139,.34), transparent 70%),
    linear-gradient(165deg, var(--navy-950), var(--navy-800));
  background-size: cover; background-position: center;
}
.page-hero.has-art::before {
  background-image:
    linear-gradient(100deg,
      rgba(9,26,44,.94) 0%,
      rgba(9,26,44,.82) 32%,
      rgba(11,34,58,.52) 62%,
      rgba(13,42,70,.30) 100%),
    var(--hero-art);
}
.page-hero-red { background: var(--red-800); }
.page-hero-red::before {
  background-image:
    radial-gradient(40rem 24rem at 82% 0%, rgba(226,86,79,.30), transparent 70%),
    linear-gradient(160deg, #7d1114, #a4161a);
}
.page-hero-red.has-art::before {
  background-image:
    linear-gradient(100deg,
      rgba(107,14,18,.94) 0%,
      rgba(118,15,19,.83) 32%,
      rgba(138,18,24,.54) 62%,
      rgba(156,21,30,.32) 100%),
    var(--hero-art);
}
/* A photograph needs a heavier, more even wash than line art does: its
   midtones sit right where the headline does, and they move about from one
   photo to the next. */
.page-hero.has-photo::before {
  background-image:
    linear-gradient(100deg,
      rgba(6,22,38,.95) 0%,
      rgba(6,22,38,.84) 36%,
      rgba(6,22,38,.58) 70%,
      rgba(6,22,38,.42) 100%),
    var(--hero-art);
}
.page-hero-red.has-photo::before {
  background-image:
    linear-gradient(100deg,
      rgba(88,10,14,.95) 0%,
      rgba(103,13,17,.85) 36%,
      rgba(124,16,21,.60) 70%,
      rgba(140,18,24,.44) 100%),
    var(--hero-art);
}

.page-hero.page-hero-red p { color: #f7dcdd; }
.page-hero-red .breadcrumb { color: #edbcbe; }
.page-hero-red .breadcrumb a { color: #f7dcdd; }
.btn-on-red { background: #fff; color: var(--red-700); }
.btn-on-red:hover { background: #fff; color: var(--red-800); }

.page-hero::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: linear-gradient(90deg, transparent, rgba(201,151,31,.45) 30%, rgba(190,22,34,.45) 70%, transparent);
}
.page-hero h1 { color: #fff; margin-bottom: .3em; font-size: var(--step-4); font-weight: 400; }
.page-hero p { color: #9fb6cd; font-size: var(--step-1); max-width: 56ch; margin: 0; }

/* Narrow screens crop the artwork hard, so pull the scrim back to a plain
   top-to-bottom wash and let the motif sit behind the text as texture. */
@media (max-width: 760px) {
  .page-hero.has-art::before {
    background-image:
      linear-gradient(180deg, rgba(9,26,44,.95) 0%, rgba(9,26,44,.91) 55%, rgba(12,38,64,.87) 100%),
      var(--hero-art);
  }
  .page-hero-red.has-art::before {
    background-image:
      linear-gradient(180deg, rgba(107,14,18,.95) 0%, rgba(130,17,21,.91) 55%, rgba(150,20,28,.87) 100%),
      var(--hero-art);
  }
  /* Photographs keep more of themselves on small screens than the line art
     does — there is no fine detail to lose, and the crop is the whole point. */
  /* Phones fetch the 720px -sm rendition when one exists — a third of the
     bytes, indistinguishable at this size. */
  .page-hero.has-photo::before {
    background-image:
      linear-gradient(180deg, rgba(6,22,38,.90) 0%, rgba(6,22,38,.78) 55%, rgba(6,22,38,.70) 100%),
      var(--hero-art-sm, var(--hero-art));
  }
  .page-hero-red.has-photo::before {
    background-image:
      linear-gradient(180deg, rgba(88,10,14,.90) 0%, rgba(110,13,18,.79) 55%, rgba(128,16,22,.71) 100%),
      var(--hero-art-sm, var(--hero-art));
  }
}

.breadcrumb {
  font-size: .82rem; color: #7f95ad; margin-bottom: 1rem;
  display: flex; align-items: center; gap: .45rem; flex-wrap: wrap;
}
.breadcrumb a { color: #a8bed5; text-decoration: none; }
.breadcrumb a:hover { color: #fff; text-decoration: underline; }
.breadcrumb .sep { opacity: .45; }

/* --------------------------------------------------------------------------
   Photo credits
   -------------------------------------------------------------------------- */
.credit-list { list-style: none; margin: 0; padding: 0; }
.credit-list li {
  display: grid; gap: .15rem; margin: 0;
  padding: .85rem 0; border-top: 1px solid var(--rule-soft);
  font-size: .93rem; color: var(--ink-600);
}
.credit-list li:first-child { border-top: 0; }
.credit-list strong { color: var(--navy-900); font-size: .95rem; }

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--navy-950); color: #8ba2ba;
  padding: clamp(2.75rem, 6vw, 4.25rem) 0 0;
  font-size: .93rem;
}
.footer-grid { display: grid; gap: 2.4rem; padding-bottom: clamp(2rem, 4vw, 3rem); }
@media (min-width: 720px)  { .footer-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .footer-grid { grid-template-columns: 1.7fr 1fr 1fr 1.25fr; } }

.site-footer h4 {
  font-family: var(--font-sans);
  color: #fff; font-size: .74rem; font-weight: 700;
  letter-spacing: .15em; text-transform: uppercase; margin-bottom: 1.1rem;
}
.site-footer a { color: #8ba2ba; text-decoration: none; transition: color .16s ease; }
.site-footer a:hover { color: #fff; }
.footer-links { list-style: none; padding: 0; margin: 0; display: grid; gap: .6rem; }
.footer-links li { margin: 0; }

.footer-brand .brand-name { color: #fff; }
.footer-brand .brand-tag { color: var(--gold-500); }
.footer-brand p { margin-top: 1.1rem; max-width: 36ch; font-size: .92rem; line-height: 1.65; }

.footer-bottom {
  border-top: 1px solid rgba(255,255,255,.08);
  padding: 1.4rem 0 calc(1.4rem + env(safe-area-inset-bottom));
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem;
  justify-content: space-between; font-size: .84rem; color: #6d8299;
}

/* --------------------------------------------------------------------------
   Mobile action bar
   -------------------------------------------------------------------------- */
/* A compact floating cluster at the bottom right — round Call and WhatsApp
   buttons and a labelled Token pill — instead of a bar across the screen.
   Content shows through beside it, so the page keeps its full height. */
.mobile-bar {
  position: fixed; right: 12px; z-index: 95;
  bottom: calc(14px + env(safe-area-inset-bottom));
  display: none; align-items: center; gap: .55rem;
}
.fab {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .45rem;
  width: 48px; height: 48px; border-radius: 999px;
  color: #fff; text-decoration: none;
  font-size: .89rem; font-weight: 650;
  box-shadow: 0 3px 6px rgba(10, 37, 64, .18), 0 10px 26px -8px rgba(10, 37, 64, .38);
  transition: transform .16s ease, box-shadow .16s ease;
}
.fab svg { width: 20px; height: 20px; }
.fab:active { transform: scale(.94); }
.fab-call  { background: var(--red-600); }
.fab-wa    { background: #1da851; }
.fab-token { width: auto; padding: 0 1.05rem 0 .9rem; background: var(--navy-800); }

/* The cluster serves every width — with the masthead carrying only the
   brand and the sections, this is where Call, WhatsApp and Token live. */
.mobile-bar { display: flex; }
body { padding-bottom: 30px; }

/* --------------------------------------------------------------------------
   Pills and utilities
   -------------------------------------------------------------------------- */
.pill {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .26rem .7rem; border-radius: 999px;
  font-size: .765rem; font-weight: 700; letter-spacing: .02em;
  border: 1px solid transparent;
}
.pill-green { background: var(--green-50); color: var(--green-700); border-color: var(--green-100); }
.pill-red   { background: var(--red-50);   color: var(--red-700);   border-color: var(--red-100); }
.pill-gold  { background: var(--gold-50);  color: var(--gold-700);  border-color: var(--gold-100); }
.pill-navy  { background: var(--navy-50);  color: var(--navy-800);  border-color: var(--navy-100); }
.pill-grey  { background: var(--ground-deep); color: var(--ink-500); border-color: var(--rule); }

.text-center { text-align: center; }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.mt-1 { margin-top: .75rem; } .mb-1 { margin-bottom: .75rem; }
.mt-2 { margin-top: 1.5rem; } .mb-2 { margin-bottom: 1.5rem; }
.mt-3 { margin-top: 2.25rem; } .mb-3 { margin-bottom: 2.25rem; }
.mt-4 { margin-top: 3rem; } .mb-4 { margin-bottom: 3rem; }
.muted { color: var(--ink-500); }
.small { font-size: .88rem; }
.nowrap { white-space: nowrap; }

/* --------------------------------------------------------------------------
   Home hero — the words on paper, the photograph beside them

   Two halves rather than one picture with writing across it. Words over a
   photograph only ever end one of two ways: the picture is darkened until it
   is wallpaper, or the words sit at a contrast nobody can read. This hero
   carries an emergency number, so the second was never available, and the
   first stopped being worth it once the pictures were worth showing. Each
   half now does one job — and the photograph carries nothing at all: no tint,
   no gradient, no text.

   The left column's padding is the page gutter, computed rather than guessed,
   so the headline starts on the same vertical line as every heading further
   down the page while the photograph runs clean off the right edge.

   Everything that moves is opacity or a transform on the frame, so no slide
   change can touch layout. The drift lives on the frame, not on the layers:
   one movement shared by all five means two pictures mid-crossfade are always
   at exactly the same size, which is what stops the change from lurching.
   -------------------------------------------------------------------------- */
.hero-show {
  --hs-gutter: max(clamp(18px, 4vw, 40px), calc((100vw - var(--wrap)) / 2));

  /* How far the photograph reaches back under the words, and how wide the
     dissolve is that covers that reach. The dissolve is the wider of the two,
     so the picture is already indistinguishable from paper well before it
     gets anywhere near a letter — and the words reserve the reach again in
     their own right padding below, so the two never actually meet. */
  --hs-reach: clamp(46px, 5.5vw, 120px);
  --hs-fade-x: calc(var(--hs-reach) + clamp(80px, 9vw, 180px));
  --hs-fade-y: clamp(34px, 5vw, 76px);

  position: relative; isolation: isolate;
  display: grid;
  /* The words take the slightly larger share now that they also carry the
     reach in their padding: without that they would be setting a headline in
     what is left after the photograph has had its share twice. */
  grid-template-columns: minmax(0, 1.24fr) minmax(0, 1fr);
  align-items: center;
  background: var(--ground);
  overflow: clip;
  /* The shared .hero rule pads itself and paints a tinted gradient, both of
     which belong to the older banner. Here the words carry their own spacing
     and the photograph runs to the edges, so both are cleared rather than
     leaving a band of ground above and below the picture. */
  padding: 0;
}

/* The words. Ordinary dark type on the site's own ground — the same reading
   conditions as the rest of the page, which is the whole point. */
.hs-words {
  position: relative; z-index: 1;
  /* Both halves are pinned to the same row. Without the explicit row the
     photograph comes first in the markup, takes row 1 column 2, and grid's
     forward-only auto-placement then has nowhere to put the words but a
     second row — which silently doubles the hero's height. */
  grid-column: 1; grid-row: 1;
  /* The right padding carries the reach as well as its own gap, so widening
     the dissolve can never walk the photograph into a line of type: whatever
     the picture takes back, the words give up first. */
  padding: clamp(2.6rem, 5vw, 4.6rem)
           calc(var(--hs-reach) + clamp(1.4rem, 2.6vw, 2.4rem))
           clamp(2.6rem, 5vw, 4.6rem) var(--hs-gutter);
}

/* There was a hairline here, on the theory that a ruled join reads as
   deliberate. On a screen this wide it did the opposite: a razor edge down the
   middle of the hero, with a photograph stopping dead against it, so the two
   halves read as two unrelated panels rather than one hero. The join is now
   a dissolve painted on the photograph itself (see .hs-frame::after), which
   is the same idea done properly — the picture ends in paper instead of
   ending at a line. */

.hs-place {
  display: inline-flex; align-items: center; gap: .45rem;
  /* ink-500 was right when this line sat on a dark photograph; on the ivory
     ground it measures 4.06:1, under the 4.5:1 small text needs. */
  color: var(--ink-600); margin: 0 0 1.15rem;
  font-size: .875rem; font-weight: 600; letter-spacing: .01em;
}
.hs-place svg { width: 17px; height: 17px; color: var(--red-600); }

/* Every slide's text occupies the same grid cell, so the tallest one sets the
   height once and the rest fade in and out inside it — the hero is as tall as
   its longest slide from the first paint and never jumps as the copy changes. */
.hs-copy { display: grid; }
.hs-text { grid-area: 1 / 1; }
.hs-text[hidden] { display: none; }

.hs-mark {
  display: inline-grid; place-items: center;
  width: 46px; height: 46px; margin-bottom: 1.05rem;
  border-radius: 14px;
  background: var(--gold-50);
  border: 1px solid var(--gold-100);
}
.hs-mark svg { width: 24px; height: 24px; color: var(--gold-600); }

.hero-show .hs-title {
  color: var(--navy-900); margin: 0 0 .42em;
  font-size: clamp(2rem, 1.1rem + 2.6vw, 3.15rem); line-height: 1.07;
  letter-spacing: -.026em; text-wrap: balance;
}
.hero-show .hs-lede {
  color: var(--ink-700); margin: 0;
  font-size: clamp(1rem, .95rem + .28vw, 1.13rem); line-height: 1.62;
  max-width: 34rem;
}

/* Entrance: each line arrives from slightly behind and slightly small, one
   after another. Only opacity, scale and translate, so it composites on the
   GPU and cannot disturb the layout. */
.hs-text.is-on .hs-mark,
.hs-text.is-on .hs-title,
.hs-text.is-on .hs-lede {
  animation: hs-rise .7s cubic-bezier(.16, .84, .28, 1) both;
  transform-origin: 0% 60%;
}
.hs-text.is-on .hs-title { animation-delay: .07s; }
.hs-text.is-on .hs-lede  { animation-delay: .14s; }
@keyframes hs-rise {
  from { opacity: 0; scale: .94; translate: 0 10px; filter: blur(3px); }
  60%  { opacity: 1; }
  to   { opacity: 1; scale: 1; translate: 0 0; filter: blur(0); }
}

/* --------------------------------------------------------------------------
   The photograph
   -------------------------------------------------------------------------- */
.hs-frame {
  grid-column: 2; grid-row: 1;
  position: relative;
  align-self: stretch;
  min-height: clamp(26rem, 21rem + 20vw, 37rem);
  overflow: hidden;
  background: var(--ground-deep);
  /* Reaching back into the words' column rather than starting where the
     column does. Nothing of the picture is legible there — the dissolve below
     is wider than the reach — but the light coming off it is, and that is what
     makes the two halves read as one photograph lit from the right rather than
     as an image pasted beside a paragraph. */
  margin-left: calc(var(--hs-reach) * -1);
  touch-action: pan-y;
}

/* The dissolve. Paper laid over the photograph — full strength at the left
   edge, gone by the end of the ramp — plus a shallower version along the top
   and bottom so the two corners nearest the words soften as well, which is
   where a hard edge is most obvious. Painted on top of the pictures rather
   than masked out of them, so it costs no compositing layer and there is no
   version of it that can fail and leave a bare rectangle.

   The stops are not evenly spaced: an even ramp reads as a visible band of
   haze because the eye tracks the middle of a fade, not its ends. This one
   holds near-opaque for the first fifth and then lets go quickly. */
.hs-frame::after {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(to right,
      rgb(var(--ground-rgb) / 1)    0%,
      rgb(var(--ground-rgb) / .985) 20%,
      rgb(var(--ground-rgb) / .82)  40%,
      rgb(var(--ground-rgb) / .46)  62%,
      rgb(var(--ground-rgb) / .15)  82%,
      rgb(var(--ground-rgb) / 0)    100%),
    linear-gradient(to bottom,
      rgb(var(--ground-rgb) / .92) 0%,
      rgb(var(--ground-rgb) / .38) 46%,
      rgb(var(--ground-rgb) / 0)   100%),
    linear-gradient(to top,
      rgb(var(--ground-rgb) / .92) 0%,
      rgb(var(--ground-rgb) / .38) 46%,
      rgb(var(--ground-rgb) / 0)   100%);
  background-size:
    var(--hs-fade-x) 100%,
    100% var(--hs-fade-y),
    100% var(--hs-fade-y);
  background-position: left top, left top, left bottom;
}

.hs-stage { position: absolute; inset: 0; }

/* The one source picked here in a custom property, so the layer and both of
   its pseudo-elements below always agree on which file they are showing. */
.hs-layer {
  --hs-src: var(--hs-img);
  position: absolute; inset: 0;
  background-image: var(--hs-src);
  background-size: cover; background-position: center;
  opacity: 0;
  transition: opacity .9s cubic-bezier(.4, 0, .3, 1);
  will-change: opacity, transform;
}
@media (max-width: 700px) {
  .hs-layer { --hs-src: var(--hs-img-sm, var(--hs-img)); }
}

/* The picture settles while it is being shown: it arrives fractionally large
   and slightly off-centre and eases down to where it belongs. Two reasons it
   is a settle rather than a loop. A loop has to turn around, and the turn is
   always visible; this one only ever slows, so the slide reads as coming to
   rest. And it is timed to run far longer than a slide lasts, so it is always
   caught in its early, fastest part and never reaches the flat tail — the
   picture is still arriving when the next one takes over, which is what makes
   a two-second hero feel unhurried instead of clipped.

   A previous version of this hero had no movement at all, on the reasoning
   that a still picture is a calm one. On a phone that was true. Across half a
   desktop screen it was not: a photograph that large simply looked frozen, and
   the crossfade read as the page redrawing rather than as a hero.

   Alternate slides drift the other way, so five slides in a row never build
   up into one direction of travel. */
.hs-layer.is-on {
  opacity: 1;
  animation: hs-drift calc(var(--hs-turn, 2000ms) * 3.2)
             cubic-bezier(.17, .62, .3, 1) both;
}
.hs-layer:nth-child(even).is-on { animation-name: hs-drift-alt; }

/* Ending fractionally over 1 rather than at 1: the translate would otherwise
   pull a hairline of empty frame in at one edge on the last frame. */
@keyframes hs-drift {
  from { transform: scale(1.062) translate(1.15%, .55%); }
  to   { transform: scale(1.006) translate(0, 0); }
}
@keyframes hs-drift-alt {
  from { transform: scale(1.062) translate(-1.15%, -.55%); }
  to   { transform: scale(1.006) translate(0, 0); }
}

/* A photograph fills the frame; losing the edges of a scene costs nothing.
   A diagram cannot afford that — its outer panels are its content — and
   padding it out with bars is not fitting either. So a soft layer shows the
   whole picture over a blurred copy of itself: the sharp image sits in front
   at 'contain', and behind it the same file, blown past the frame's edges and
   blurred, fills whatever the frame's shape leaves over. The browser builds
   that surround for the frame it actually has, which is why one file fits a
   1.18 laptop frame, a 1.6 tablet frame and a square phone frame with no bar
   and no crop — and why there is never a seam, since the surround is the
   picture itself continuing outward. */
.hs-layer.hs-soft { background: none; }
.hs-layer.hs-soft::before,
.hs-layer.hs-soft::after {
  content: ''; position: absolute;
  background-image: var(--hs-src);
  background-position: center; background-repeat: no-repeat;
}
.hs-layer.hs-soft::before {
  /* Past the frame's edges, so the blur never thins out into a vignette at
     the border; the frame's own overflow clipping trims the excess. */
  inset: -64px;
  background-size: cover;
  filter: blur(26px) saturate(1.05);
}
.hs-layer.hs-soft::after { inset: 0; background-size: contain; }

/* A diagram settles the other way round — up from slightly small rather than
   down from slightly large. Its sharp copy is sized to fit the frame exactly,
   so anything over 1.0 would push the outer panels, which are the content,
   past the edge. Growing into place costs nothing: the blurred surround
   reaches 64px beyond the frame, far more than the few pixels this pulls in,
   so no gap can open at the border. */
.hs-layer.hs-soft.is-on,
.hs-layer.hs-soft:nth-child(even).is-on { animation-name: hs-drift-soft; }
@keyframes hs-drift-soft {
  from { transform: scale(.972); }
  to   { transform: scale(1); }
}

/* --------------------------------------------------------------------------
   Actions
   -------------------------------------------------------------------------- */
.hs-actions {
  display: flex; flex-wrap: wrap; gap: .75rem;
  margin: 1.9rem 0 0;
}

/* The buttons are drawn rather than filled: a pair of corner brackets that
   draw themselves in on hover, a sheen that crosses once, an arrow that
   slides. The brackets are fixed-size SVGs pinned to each corner rather than
   one frame stretched around the button — a stretched rounded rect turns its
   corners into ellipses at every width but the one it was drawn for. */
.hbtn {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; gap: .55rem;
  padding: 1.02rem 1.5rem;
  border-radius: 15px;
  font-weight: 650; font-size: 1rem; letter-spacing: .002em;
  text-decoration: none; white-space: nowrap;
  transition: transform .22s cubic-bezier(.2, .7, .3, 1),
              box-shadow .22s ease, background-color .22s ease, border-color .22s ease;
}
.hbtn:hover { transform: translateY(-2px); }
.hbtn:active { transform: translateY(0); transition-duration: .08s; }
.hbtn:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 3px; }

.hbtn-label { display: inline-flex; align-items: center; gap: .6rem; }
.hbtn svg { width: 20px; height: 20px; flex: none; }

.hbtn-go {
  display: inline-flex; opacity: 0; translate: -6px 0;
  transition: opacity .24s ease, translate .24s cubic-bezier(.2, .7, .3, 1);
}
.hbtn:hover .hbtn-go { opacity: 1; translate: 0 0; }

.hbtn-corner {
  position: absolute; width: 40px; height: 40px;
  fill: none; pointer-events: none;
}
.hbtn-corner path {
  stroke-width: 2; stroke-linecap: round;
  stroke-dasharray: 1; stroke-dashoffset: 1;
  transition: stroke-dashoffset .5s cubic-bezier(.25, .8, .3, 1);
}
.hbtn:hover .hbtn-corner path { stroke-dashoffset: 0; }
.hbtn-corner-tl { top: 3px; left: 3px; }
.hbtn-corner-br { bottom: 3px; right: 3px; }

/* One pass, on hover only — a sheen that loops is a casino, not a hospital. */
.hbtn-sheen {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 38%,
              rgba(255, 255, 255, .3) 50%, transparent 62%);
  translate: -130% 0;
}
.hbtn:hover .hbtn-sheen { animation: hbtn-sheen .85s cubic-bezier(.3, 0, .2, 1); }
@keyframes hbtn-sheen { from { translate: -130% 0; } to { translate: 130% 0; } }

.hbtn-primary {
  background: linear-gradient(135deg, var(--red-600), var(--red-700));
  color: #fff;
  box-shadow: 0 2px 4px rgba(124, 15, 20, .18), 0 12px 26px -8px rgba(124, 15, 20, .42);
}
.hbtn-primary:hover {
  background: linear-gradient(135deg, var(--red-500), var(--red-600));
  box-shadow: 0 4px 8px rgba(124, 15, 20, .2), 0 18px 34px -10px rgba(124, 15, 20, .5);
}
.hbtn-primary .hbtn-corner { stroke: rgba(255, 226, 160, .95); }

/* On paper the second button is an outline, not glass: the same shape, told
   apart by weight rather than by colour, so the pair reads as one family. */
.hbtn-ghost {
  background: var(--paper);
  color: var(--navy-900);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-xs);
}
.hbtn-ghost:hover { border-color: var(--navy-200); box-shadow: var(--shadow-sm); }
.hbtn-ghost .hbtn-label svg { color: var(--red-600); }
.hbtn-ghost .hbtn-corner { stroke: var(--navy-700); }

.hero-show .hero-live { color: var(--ink-600); margin-top: 1.5rem; }
.hero-show .hero-live strong { color: var(--navy-900); }

/* --------------------------------------------------------------------------
   Slide controls

   The active one fills across its turn, so the wait is visible and a picture
   never changes out of nowhere. The fill is a child element rather than a
   background animation, so pausing it is one property on an ancestor.
   -------------------------------------------------------------------------- */
/* The gap is 12px because the hit areas below reach 6px past each bar: any
   tighter and neighbouring targets would overlap, so a tap near a boundary
   would select the wrong slide. */
.hs-dots { display: flex; gap: .875rem; margin-top: 1.9rem; }
.hs-dot {
  position: relative;
  padding: .5rem .18rem; background: none; border: 0; cursor: pointer;
  line-height: 0;
}
/* A 3px bar is the right thing to look at and the wrong thing to hit: the
   button measured 32x19, well under the 44px a fingertip needs. The hit area
   is extended with a pseudo-element rather than padding, so the target grows
   without the row growing with it — which matters on a phone, where every
   pixel here pushes the booking button further down the screen. */
.hs-dot::after {
  content: ''; position: absolute; inset: -13px -7px;
}
.hs-dot > span {
  display: block; position: relative; overflow: hidden;
  width: 26px; height: 3px; border-radius: 2px;
  background: var(--rule);
  transition: width .3s ease, background-color .25s ease;
}
.hs-dot:hover > span { background: var(--ink-300); }
.hs-dot.is-on > span { width: 52px; background: var(--gold-100); }
.hs-dot > span > i {
  position: absolute; inset: 0 auto 0 0;
  display: block; width: 0; border-radius: 2px;
  background: var(--gold-500);
}
.hs-dot.is-on > span > i { animation: hs-fill var(--hs-turn, 3500ms) linear both; }
@keyframes hs-fill { from { width: 0; } to { width: 100%; } }
/* Paused while the reader is reading it; frozen once they take control. */
.hero-show.is-held .hs-dot.is-on > span > i { animation-play-state: paused; }
.hero-show.is-stopped .hs-dot.is-on > span > i { animation: none; width: 100%; }
.hs-dot:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 3px; border-radius: 4px; }

/* --------------------------------------------------------------------------
   Narrow screens: the photograph on top, the words beneath it

   Side by side stops working long before a phone — the words get a column too
   narrow to set a headline in. Stacking keeps both at full width, and the
   picture stays the first thing seen.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
  .hero-show { grid-template-columns: 1fr; }
  .hs-frame {
    grid-column: 1; grid-row: 1;
    min-height: 0; aspect-ratio: 16 / 10;
    /* Nothing to reach back under once the words are below rather than
       beside: the reach would only pull the picture off the left edge. */
    margin-left: 0;
  }
  /* Stacked, the join that matters is the bottom one. The picture keeps its
     own left and right edges, which are the screen's edges, and dissolves
     into the paper the words sit on. */
  .hs-frame::after {
    background-image:
      linear-gradient(to top,
        rgb(var(--ground-rgb) / 1)   0%,
        rgb(var(--ground-rgb) / .78) 26%,
        rgb(var(--ground-rgb) / .34) 58%,
        rgb(var(--ground-rgb) / 0)   100%);
    background-size: 100% clamp(52px, 13vw, 108px);
    background-position: left bottom;
  }
  .hs-words {
    grid-column: 1; grid-row: 2;
    padding: clamp(1.8rem, 5vw, 2.6rem) var(--hs-gutter) clamp(2.2rem, 6vw, 3rem);
  }
}

/* --------------------------------------------------------------------------
   The phone hero

   Measured rather than guessed: at 390px the hero stood 969px tall — 115% of
   the screen — which put "Book an OP Token" 35px below the fold, and 258px
   below it on a 360px phone. A hero whose whole purpose is that button must
   not hide it, so every part of this block is buying vertical space back.

   The frame is 5:4 rather than square. It was square so the diagrams could be
   read, but that reasoning expired when they gained their blurred surround:
   the sharp picture is sized to fit inside the frame, so the wider of the two
   renders at exactly the same size in a 5:4 frame as in a square one, and only
   the square picture gives up anything. 78px for that is a good trade.
   -------------------------------------------------------------------------- */
@media (max-width: 620px) {
  .hs-frame { aspect-ratio: 5 / 4; }

  .hs-words { padding-top: 1.35rem; padding-bottom: 1.5rem; }
  .hs-place { margin-bottom: .8rem; }

  /* The gold mark is decorative and already aria-hidden. On a phone it costs
     54px above the headline, which is a button's worth of screen. */
  .hs-mark { display: none; }

  .hs-actions { flex-direction: column; align-items: stretch; gap: .6rem; margin-top: 1.3rem; }
  .hs-actions .hbtn { width: 100%; justify-content: center; }
  .hero-show .hero-live { margin-top: 1rem; }
  .hs-dots { margin-top: 1.15rem; }
}

/* A reader who has asked for less motion gets no rise, no sheen and no lift —
   nothing that travels or scales. The pictures still change, because a
   cross-dissolve moves nothing: it is a change of opacity, and opacity is not
   motion. It is slowed to a longer, gentler dissolve to match the request.

   This used to switch the slideshow off entirely, and that turned out to be
   the wrong reading of the preference twice over — it is a request to reduce
   motion, not to freeze content, and Android's battery saver turns it on by
   itself, so a phone in power-saving mode showed a hero that never changed
   and looked broken. The dots remain the way to stop it for good, which is
   what WCAG 2.2.2 actually asks for. */
@media (prefers-reduced-motion: reduce) {
  .hs-layer { transition: opacity 1.1s linear; }
  /* The settle is the one thing here that genuinely travels, so it goes — and
     it has to be turned off in the same three shapes it was turned on in.
     `.hs-layer.is-on` alone does not do it: the two rules that pick a
     different keyframe set are each more specific than it, so the alternating
     slides and both diagram slides went on naming a moving animation. The
     shorthand happened to zero their duration, which is why nothing actually
     moved, but a preference honoured by accident is one line away from not
     being honoured at all. */
  .hs-layer.is-on,
  .hs-layer:nth-child(even).is-on,
  .hs-layer.hs-soft.is-on,
  .hs-layer.hs-soft:nth-child(even).is-on { animation: none; transform: none; }
  .hs-text.is-on .hs-mark,
  .hs-text.is-on .hs-title,
  .hs-text.is-on .hs-lede { animation: none; }
  .hs-dot.is-on > span > i { animation: none; width: 100%; }
  .hbtn, .hbtn-go, .hbtn-corner path { transition: none; }
  .hbtn:hover { transform: none; }
  .hbtn:hover .hbtn-sheen { animation: none; }
  .hbtn-go { opacity: 1; translate: 0 0; }
}

/* --------------------------------------------------------------------------
   Live queue (queue.php)
   -------------------------------------------------------------------------- */
.queue-mine {
  background: linear-gradient(160deg, var(--navy-900), var(--navy-800));
  color: var(--navy-50);
  border-radius: 16px; padding: 1.6rem 1.8rem;
  box-shadow: var(--shadow-lg);
}
.queue-mine.is-muted { opacity: .82; }
.queue-mine-head { display: flex; flex-wrap: wrap; gap: .35rem 1rem; align-items: baseline; }
.queue-mine .q-doctor {
  font-family: var(--font-display); font-weight: 650; font-size: 1.25rem;
}
.queue-mine .q-session { color: var(--navy-200); font-size: .88rem; }

.queue-mine-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .8rem;
  margin: 1.2rem 0 1rem; text-align: center;
}
.queue-mine .q-stat {
  background: rgba(238, 244, 250, .07);
  border: 1px solid rgba(185, 205, 226, .22);
  border-radius: 12px; padding: .85rem .5rem;
}
.queue-mine .q-stat-you { background: rgba(224, 182, 78, .14); border-color: rgba(224, 182, 78, .4); }
.queue-mine .q-stat-you .q-num { color: var(--gold-400); }
.queue-mine .q-label {
  display: block; font-size: .68rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--navy-200);
}
.queue-mine .q-num {
  display: block; font-size: clamp(2.1rem, 1.4rem + 3vw, 3rem);
  font-weight: 800; line-height: 1.15; font-variant-numeric: tabular-nums;
}
.queue-mine-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
  margin: 0; font-size: .9rem; color: var(--navy-100);
}
.queue-mine-foot .pill-navy { background: rgba(238, 244, 250, .12); color: var(--navy-50); border-color: rgba(185, 205, 226, .3); }

.queue-board { display: grid; gap: 1rem; }
.queue-card {
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: 14px; padding: 1.1rem 1.3rem; box-shadow: var(--shadow-sm);
}
.queue-card.is-ended { opacity: .72; }
.queue-card-head { display: flex; flex-wrap: wrap; gap: .2rem 1rem; align-items: baseline; }
.queue-card .q-doctor { font-family: var(--font-display); font-weight: 650; font-size: 1.1rem; color: var(--navy-900); }
.queue-card .q-session { color: var(--ink-500); font-size: .85rem; }
.queue-card-body {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-top: .7rem;
}
.queue-card .q-label {
  display: block; font-size: .66rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-500);
}
.queue-card .q-num {
  font-size: 2.3rem; font-weight: 800; line-height: 1.1;
  color: var(--navy-900); font-variant-numeric: tabular-nums;
}
.queue-card .q-side { display: flex; flex-direction: column; align-items: flex-end; gap: .35rem; }
.queue-card .q-waiting { font-size: .88rem; color: var(--ink-600); font-weight: 600; }

@media (max-width: 480px) {
  .queue-mine { padding: 1.2rem 1rem; }
  .queue-mine-grid { gap: .5rem; }
}

/* Booking summary on the cancel page. */
.cancel-summary {
  display: grid; grid-template-columns: auto 1fr; gap: .45rem 1.2rem;
  margin: 0 0 1.3rem; padding-bottom: 1.1rem;
  border-bottom: 1px solid var(--rule);
}
.cancel-summary dt {
  font-size: .72rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-500); align-self: center;
}
.cancel-summary dd { margin: 0; color: var(--ink-800); }

/* --------------------------------------------------------------------------
   Print
   -------------------------------------------------------------------------- */
@media print {
  .site-header, .site-footer, .emergency-bar, .mobile-bar, .no-print { display: none !important; }
  body { padding: 0; font-size: 11.5pt; color: #000; background: #fff; }
  a { text-decoration: none; color: #000; }
  .card, .table-card { box-shadow: none; }
}

/* ==========================================================================
   Forms
   ========================================================================== */

.form-card {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: clamp(1.5rem, 3.5vw, 2.5rem);
  box-shadow: var(--shadow-sm);
}

.field { margin-bottom: 1.35rem; }
.field:last-child { margin-bottom: 0; }

.field label, .fieldset-legend {
  display: block;
  font-family: var(--font-sans);
  font-weight: 650; font-size: .9rem;
  color: var(--navy-900); margin-bottom: .45rem;
  letter-spacing: -.005em;
}
.field .hint {
  display: block; font-weight: 400; font-size: .845rem;
  color: var(--ink-500); margin-top: -.25rem; margin-bottom: .5rem; line-height: 1.5;
}
.req { color: var(--red-600); margin-left: .12rem; }

.field input[type="text"], .field input[type="tel"], .field input[type="number"],
.field input[type="date"], .field input[type="password"], .field input[type="time"],
.field input[type="email"], .field select, .field textarea {
  width: 100%;
  padding: .78rem .95rem;
  font: inherit; font-size: 1rem; color: var(--ink-900);
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--r-sm);
  transition: border-color .16s ease, box-shadow .16s ease, background-color .16s ease;
  min-height: 50px;
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-400); }
.field textarea { min-height: 104px; resize: vertical; line-height: 1.6; }

.field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236f7b8a' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .85rem center;
  background-size: 18px; padding-right: 2.6rem; cursor: pointer;
}

.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--ink-300); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--navy-600);
  box-shadow: 0 0 0 3.5px rgba(34, 89, 139, .14);
}
.field input[aria-invalid="true"], .field select[aria-invalid="true"] {
  border-color: var(--red-600); box-shadow: 0 0 0 3.5px rgba(190, 22, 34, .11);
}
.field .error {
  display: flex; align-items: center; gap: .35rem;
  color: var(--red-700); font-size: .865rem; font-weight: 600; margin-top: .4rem;
}

.field-row { display: grid; gap: 1.35rem; }
@media (min-width: 580px) {
  .field-row.cols-2 { grid-template-columns: 1fr 1fr; }
  .field-row.cols-3 { grid-template-columns: repeat(3, 1fr); }
}

.hp-field {
  position: absolute !important; left: -9999px !important;
  width: 1px; height: 1px; overflow: hidden;
}

fieldset {
  border: 0; padding: 0; margin: 0 0 1.75rem;
  /* A fieldset defaults to min-inline-size:min-content, so a horizontally
     scrolling child (the date strip) stretches it instead of scrolling inside
     it, pushing the whole page sideways on a phone. */
  min-inline-size: 0;
}
fieldset:last-of-type { margin-bottom: 1.25rem; }

/* Numbered steps in the booking form */
.fieldset-legend.step {
  display: flex; align-items: center; gap: .65rem;
  font-family: var(--font-display); font-size: var(--step-1);
  font-weight: 600; color: var(--navy-900);
  margin-bottom: .9rem;
}
.fieldset-legend.step .num {
  display: grid; place-items: center; flex: none;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--navy-900); color: #fff;
  font-family: var(--font-sans); font-size: .8rem; font-weight: 700;
}

/* --------------------------------------------------------------------------
   Choice tiles
   -------------------------------------------------------------------------- */
.choice-grid { display: grid; gap: .7rem; }
@media (min-width: 580px) { .choice-grid.cols-2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 460px) { .choice-grid.cols-3 { grid-template-columns: repeat(3, 1fr); } }

.choice { position: relative; margin: 0; }
.choice input { position: absolute; opacity: 0; width: 0; height: 0; }

.choice-label {
  display: flex; gap: .8rem; align-items: flex-start;
  padding: 1rem 1.05rem; height: 100%;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--r);
  cursor: pointer;
  transition: border-color .16s ease, background-color .16s ease, box-shadow .16s ease;
}
.choice-label:hover { border-color: var(--navy-500); background: var(--navy-50); }

.choice input:checked + .choice-label {
  border-color: var(--navy-800);
  background: var(--navy-50);
  box-shadow: 0 0 0 2px rgba(16, 51, 86, .16);
}
.choice input:focus-visible + .choice-label { outline: 2.5px solid var(--navy-600); outline-offset: 3px; }
.choice input:disabled + .choice-label {
  opacity: .5; cursor: not-allowed; background: var(--ground-deep); border-color: var(--rule);
}
.choice input:disabled + .choice-label:hover { border-color: var(--rule); background: var(--ground-deep); }

/* A tick appears on the selected tile */
.choice input:checked + .choice-label::after {
  content: ''; position: absolute; top: .6rem; right: .6rem;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--navy-800) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 11px no-repeat;
}

.choice-label .avatar { width: 42px; height: 42px; flex: none; }
.choice-title { display: block; font-weight: 650; color: var(--navy-900); font-size: .96rem; line-height: 1.35; }
.choice-sub { display: block; font-size: .845rem; color: var(--ink-500); margin-top: .15rem; line-height: 1.45; }
.choice-meta { display: block; margin-top: .55rem; }
.choice-center { justify-content: center; text-align: center; padding-block: .85rem; }
.choice-center .choice-title { font-size: .98rem; }

/* --------------------------------------------------------------------------
   Date strip
   -------------------------------------------------------------------------- */
.date-strip {
  display: flex; gap: .55rem; overflow-x: auto; min-width: 0;
  padding: .2rem .2rem .7rem;
  margin: -.2rem -.2rem 0;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.date-strip::-webkit-scrollbar { height: 5px; }
.date-strip::-webkit-scrollbar-track { background: var(--ground-deep); border-radius: 3px; }
.date-strip::-webkit-scrollbar-thumb { background: var(--ink-300); border-radius: 3px; }

.date-choice { flex: 0 0 auto; scroll-snap-align: start; margin: 0; position: relative; }
/* The tile itself is the control; the native radio must not show through. */
.date-choice input { position: absolute; opacity: 0; width: 0; height: 0; }
.date-choice input:focus-visible + .choice-label { outline: 2.5px solid var(--navy-600); outline-offset: 3px; }
.date-choice .choice-label {
  flex-direction: column; align-items: center; gap: .05rem;
  min-width: 82px; padding: .75rem .6rem; text-align: center;
}
.date-choice input:checked + .choice-label::after { display: none; }

.date-dow {
  font-size: .7rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-400);
}
.date-day {
  font-family: var(--font-display); font-size: 1.6rem; font-weight: 600;
  color: var(--navy-900); line-height: 1.15; font-variant-numeric: tabular-nums;
}
.date-mon { font-size: .76rem; color: var(--ink-500); font-weight: 500; }
.date-choice input:checked + .choice-label .date-dow { color: var(--navy-700); }
.date-choice input:checked + .choice-label .date-mon { color: var(--navy-700); }
.date-free {
  display: block; margin-top: .3rem;
  font-size: .6rem; font-weight: 800; letter-spacing: .06em;
  color: var(--green-700); background: var(--green-50);
  border: 1px solid var(--green-100);
  padding: .1rem .3rem; border-radius: 4px;
}

/* --------------------------------------------------------------------------
   Session availability
   -------------------------------------------------------------------------- */
.session-loading {
  display: flex; align-items: center; justify-content: center; gap: .6rem;
  padding: 2rem 1.5rem; color: var(--ink-500); font-size: .95rem;
  background: var(--paper); border: 1.5px dashed var(--rule); border-radius: var(--r);
}
.spinner {
  display: inline-block; width: 17px; height: 17px; flex: none;
  border: 2.5px solid var(--navy-100);
  border-top-color: var(--navy-700); border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.tokens-left { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   Token slip
   -------------------------------------------------------------------------- */
.token-slip {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  overflow: hidden; max-width: 540px; margin-inline: auto;
  box-shadow: var(--shadow-lg);
}
.token-slip-head {
  background: var(--navy-900); color: #fff;
  padding: 1.5rem 1.5rem 1.35rem; text-align: center;
  position: relative;
}
.token-slip-head::after {
  content: ''; position: absolute; inset-inline: 0; bottom: 0; height: 3px;
  background: linear-gradient(90deg, var(--red-600), var(--gold-500) 60%, var(--green-600));
}
.token-slip-head .brand-mark { width: 38px; height: 38px; margin: 0 auto .6rem; }
.token-slip-head .brand-name { color: #fff; font-size: 1.2rem; display: block; }
.token-slip-head .brand-tag { color: var(--gold-500); font-size: .66rem; display: block; }

.token-number {
  text-align: center; padding: 2rem 1.5rem 1.6rem;
  position: relative;
}
/* Perforated tear line */
.token-number::after {
  content: ''; position: absolute; inset-inline: 1.25rem; bottom: 0;
  border-bottom: 2px dashed var(--rule);
}
.token-number .label {
  display: block; margin-bottom: .4rem;
  font-size: .72rem; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-400);
}
.token-number .value {
  font-family: var(--font-display);
  font-size: clamp(3.6rem, 15vw, 5rem); font-weight: 600;
  color: var(--navy-900); line-height: .95;
  letter-spacing: -.04em; font-variant-numeric: tabular-nums;
  display: block;
}
.token-number .ref { display: block; margin-top: .85rem; font-size: .86rem; color: var(--ink-500); }
.token-number .ref strong {
  color: var(--navy-900); letter-spacing: .12em;
  font-family: ui-monospace, 'SF Mono', Menlo, monospace; font-size: .95em;
}

.token-details { padding: 1.5rem; }
.token-details dl {
  display: grid; grid-template-columns: auto 1fr;
  gap: .7rem 1.2rem; margin: 0; font-size: .95rem;
}
.token-details dt { color: var(--ink-500); }
.token-details dd { margin: 0; font-weight: 650; color: var(--navy-900); text-align: right; }

.token-foot {
  padding: 1.15rem 1.5rem; background: var(--ground);
  border-top: 1px solid var(--rule-soft);
  font-size: .855rem; color: var(--ink-500); text-align: center; line-height: 1.6;
}
.token-foot strong { color: var(--navy-900); font-variant-numeric: tabular-nums; }

@media print {
  .token-slip { border-width: 1.5px; box-shadow: none; max-width: 100%; }
  .token-slip-head { background: #fff !important; border-bottom: 1.5px solid #000; }
  .token-slip-head .brand-name, .token-slip-head .brand-tag { color: #000 !important; }
  .token-slip-head::after { display: none; }
}

/* ==========================================================================
   Icons

   Two tiers, matching includes/icons.php. Path data is Lucide, vendored by
   tools/build-icons.py; everything below is how it behaves here.

   Each feature icon names one moving part and declares its animation as
   --ico-anim. The animation only runs while an ancestor is hovered or focused,
   so the page is still until someone reaches for something — a hospital site
   with permanently wiggling icons reads as a toy.
   ========================================================================== */

.ico { flex: none; }
.ico-l { fill: none; stroke: currentColor; }

/* The moving part rotates and scales about its own centre, not the viewBox's. */
.ico-anim { transform-box: fill-box; transform-origin: center; }
/* The ultrasound waves radiate from the probe at the bottom, so they scale
   about that point rather than their own middle. */
.ico-feature[style*="ico-scan"] .ico-anim { transform-origin: 50% 50%; }

/*
 * Hover and focus triggers. Kept as one list so a new component only has to be
 * added here rather than repeated against every icon.
 */
:is(.quick, .card-link, .btn, .hero-doc, .offer-item, .doctor-card,
    .contact-list li, .service-list li, .stat, .token-slip):is(:hover, :focus-within) .ico-feature .ico-anim,
.findbar-field:focus-within .ico-feature .ico-anim {
  animation-name: var(--ico-anim);
  animation-duration: .75s;
  animation-timing-function: cubic-bezier(.34, 1.4, .64, 1);
  animation-fill-mode: both;
}


/*
 * The well turns over when its card is hovered, so the icon reads as an object
 * on the card rather than a picture printed on it. A full 360 lands back where
 * it started, which means it plays the same on the way out as on the way in.
 */
:is(.quick, .card-link, .doctor-card, .offer-item, .stat,
    .contact-list li, .service-card):is(:hover, :focus-within)
  :is(.quick-icon, .card-icon) {
  transform: perspective(620px) rotateY(360deg);
}

/* --------------------------------------------------------------------------
   One keyframe per icon. Each is tied to what the icon means: the token stub
   tears, the clock hand sweeps, the pin drops, the heart beats.
   -------------------------------------------------------------------------- */
@keyframes ico-ticket   { 0% { transform: translateX(0); opacity: 1; }
                          45% { transform: translateX(2.5px); opacity: .35; }
                          100% { transform: translateX(0); opacity: 1; } }

@keyframes ico-calendar { 0% { transform: scaleX(0); opacity: 0; }
                          100% { transform: scaleX(1); opacity: 1; } }

@keyframes ico-clock    { from { transform: rotate(-35deg); }
                          to   { transform: rotate(0deg); } }

@keyframes ico-location { 0% { transform: translateY(-3px); }
                          60% { transform: translateY(1px); }
                          100% { transform: translateY(0); } }

@keyframes ico-search   { 0% { transform: translate(-2px, -2px); }
                          100% { transform: translate(0, 0); } }

@keyframes ico-stetho   { 0%, 100% { transform: scale(1); }
                          40% { transform: scale(1.28); } }

@keyframes ico-heart    { 0%, 100% { transform: scale(1); }
                          25% { transform: scale(1.14); }
                          45% { transform: scale(.97); }
                          65% { transform: scale(1.08); } }

@keyframes ico-icu      { from { stroke-dasharray: 26; stroke-dashoffset: 26; }
                          to   { stroke-dasharray: 26; stroke-dashoffset: 0; } }

@keyframes ico-droplet  { 0% { transform: translateY(-3px); opacity: .3; }
                          65% { transform: translateY(1px); opacity: 1; }
                          100% { transform: translateY(0); opacity: 1; } }

@keyframes ico-lab      { 0% { transform: translateY(3px); opacity: 0; }
                          60% { opacity: 1; }
                          100% { transform: translateY(-4px); opacity: 0; } }

/* Waves pulse outward from the probe. */
@keyframes ico-scan     { 0% { transform: scale(.7); opacity: .25; }
                          55% { opacity: 1; }
                          100% { transform: scale(1.05); opacity: .55; } }

@keyframes ico-maternity{ 0%, 100% { transform: scale(1); }
                          50% { transform: scale(1.06); } }


@keyframes ico-emergency{ 0% { transform: scale(.5); opacity: 0; }
                          100% { transform: scale(1); opacity: 1; } }

@keyframes ico-shield   { from { stroke-dasharray: 12; stroke-dashoffset: 12; }
                          to   { stroke-dasharray: 12; stroke-dashoffset: 0; } }

@keyframes ico-users    { 0% { transform: translateX(3px); opacity: 0; }
                          100% { transform: translateX(0); opacity: 1; } }

@keyframes ico-list     { from { stroke-dasharray: 30; stroke-dashoffset: 30; }
                          to   { stroke-dasharray: 30; stroke-dashoffset: 0; } }

@keyframes ico-discount { 0%, 100% { transform: scale(1); }
                          50% { transform: scale(1.45); } }

@keyframes ico-award    { 0% { transform: translateY(-2.5px) scaleY(.7); opacity: 0; }
                          100% { transform: translateY(0) scaleY(1); opacity: 1; } }

@keyframes ico-building { 0% { transform: scaleY(0); }
                          100% { transform: scaleY(1); } }

@keyframes ico-room     { 0% { transform: translateY(3px); opacity: 0; }
                          100% { transform: translateY(0); opacity: 1; } }

/* The handset rings rather than merely moving. */
@keyframes ico-phone    { 0%, 100% { transform: rotate(0deg); }
                          15% { transform: rotate(-12deg); }
                          30% { transform: rotate(10deg); }
                          45% { transform: rotate(-7deg); }
                          60% { transform: rotate(5deg); }
                          75% { transform: rotate(-2deg); } }

@media (prefers-reduced-motion: reduce) {
  .ico-anim { animation: none !important; }
  .quick-icon, .card-icon { transition-duration: .01ms; }
  :is(.quick, .card-link, .doctor-card, .offer-item, .stat,
      .contact-list li, .service-card):is(:hover, :focus-within)
    :is(.quick-icon, .card-icon) { transform: none; }
}

/* ==========================================================================
   Custom select

   The native control stays in the DOM and remains what the form submits. Only
   its dropdown is replaced, because that list is drawn by the operating system
   and cannot be styled to match anything around it.

   Default state shows the native element, so the field is usable with
   JavaScript off. assets/js/select.js sets data-cs-ready, which swaps in the
   button and the listbox.
   ========================================================================== */

.cs { position: relative; }

.cs-label {
  display: flex; align-items: center; gap: .3rem;
  font-size: .68rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-500);
  margin-bottom: .15rem; cursor: pointer;
}
.cs-label svg { width: 12px; height: 12px; color: var(--navy-500); flex: none; }

/* Enhanced: hide the native control, show ours. */
.cs[data-cs-ready] > select {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.cs:not([data-cs-ready]) .cs-btn,
.cs:not([data-cs-ready]) .cs-menu { display: none; }

.cs-btn {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  width: 100%; padding: 0; border: 0; background: none;
  font: inherit; font-size: .93rem; font-weight: 600;
  color: var(--navy-900); cursor: pointer; text-align: left;
  min-width: 0;
}
.cs-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cs-arrow { flex: none; color: var(--navy-700); transition: transform .18s ease; }
.cs.is-open .cs-arrow { transform: rotate(180deg); }
.cs-btn:focus-visible { outline: 2.5px solid var(--navy-600); outline-offset: 4px; border-radius: 4px; }

/* --------------------------------------------------------------------------
   The list
   -------------------------------------------------------------------------- */
.cs-menu {
  position: absolute; z-index: 60;
  top: calc(100% + .7rem); left: -.6rem; min-width: calc(100% + 1.2rem);
  max-height: 17rem; overflow-y: auto;
  margin: 0; padding: .35rem;
  list-style: none;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  animation: cs-in .16s ease-out;
}
@keyframes cs-in {
  from { opacity: 0; transform: translateY(-5px); }
  to   { opacity: 1; transform: translateY(0); }
}

.cs-opt {
  display: flex; align-items: center; gap: .5rem;
  margin: 0; padding: .6rem .7rem;
  border-radius: var(--r-sm);
  font-size: .93rem; font-weight: 500; color: var(--ink-700);
  white-space: nowrap; cursor: pointer;
  transition: background-color .12s ease, color .12s ease;
}
.cs-opt:hover { background: var(--navy-50); color: var(--navy-900); }
.cs-opt:focus-visible,
.cs-opt:focus { outline: none; background: var(--navy-50); color: var(--navy-900);
                box-shadow: inset 0 0 0 2px var(--navy-600); }

.cs-opt[aria-selected="true"] {
  background: var(--navy-800); color: #fff; font-weight: 650;
}
.cs-opt[aria-selected="true"]:hover { background: var(--navy-900); color: #fff; }
/* A tick on the chosen row, so selection survives a colour-blind reading. */
.cs-opt[aria-selected="true"]::after {
  content: ''; margin-left: auto; width: 15px; height: 15px; flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* On a phone the bar is a stacked card, so the list spans the field. */
@media (max-width: 760px) {
  .cs-menu { left: 0; right: 0; min-width: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .cs-menu { animation: none; }
  .cs-arrow { transition: none; }
}

/* ==========================================================================
   Scroll reveals and scroll-linked parallax

   assets/js/reveal.js tags elements with data-reveal and toggles .is-in as
   they enter and leave the viewport — both ways, so scrolling back replays
   the entrance in either direction. Reveals are keyframe animations on the
   `translate`/`scale` properties, deliberately not `transform` and not
   `transition`: the cards' hover lifts own `transform` and their own
   transition shorthand, and this way the two systems cannot collide.

   The parallax is scroll-driven CSS where the browser supports it — the
   scrubbing follows the scroll position exactly, so it reverses for free.
   Browsers without it just get the reveals.
   ========================================================================== */

.js-reveal [data-reveal] { opacity: 0; }
.js-reveal [data-reveal].is-in {
  opacity: 1;
  animation: rv-up .65s cubic-bezier(.22, .85, .3, 1) both;
  animation-delay: var(--rv-d, 0ms);
}
.js-reveal [data-reveal="fade"].is-in { animation-name: rv-fade; }
.js-reveal [data-reveal="zoom"].is-in { animation-name: rv-zoom; }
.js-reveal [data-reveal="left"].is-in { animation-name: rv-left; }
.js-reveal [data-reveal="right"].is-in { animation-name: rv-right; }

/* Cards enter from alternate sides (reveal.js assigns the side by position).
   The travel is a shared token so phones take a shorter slide, and the body
   is clipped sideways so the rightward start can never widen the page —
   clip, not hidden, because hidden would turn the body into a scroll
   container and silently break the named view-timelines below. */
:root { --rv-dx: 44px; }
@media (max-width: 640px) { :root { --rv-dx: 30px; } }
html.js-reveal body { overflow-x: clip; }

.js-reveal [data-reveal="slide-left"].is-in,
.js-reveal [data-reveal="slide-right"].is-in { animation-duration: .7s; }
.js-reveal [data-reveal="slide-left"].is-in  { animation-name: rv-slide-l; }
.js-reveal [data-reveal="slide-right"].is-in { animation-name: rv-slide-r; }

@keyframes rv-slide-l {
  from { opacity: 0; translate: calc(-1 * var(--rv-dx, 44px)) 0; }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes rv-slide-r {
  from { opacity: 0; translate: var(--rv-dx, 44px) 0; }
  to   { opacity: 1; translate: 0 0; }
}

/* --------------------------------------------------------------------------
   The facilities wave

   Every other card grid on the site enters from alternating sides. The
   facilities grids instead rise one after another, and — where the browser can
   do it — keep rising and sinking with the scroll rather than playing once.

   Two layers, and the order matters. The first is a plain staggered rise on a
   clock, which every browser gets and which is a complete answer on its own.
   The second replaces it with the same movement scrubbed by scroll position,
   so the cards come up as the section arrives and go back down as it leaves,
   at exactly the pace the reader is scrolling. Nothing is lost without it.
   -------------------------------------------------------------------------- */
.js-reveal [data-reveal="wave"].is-in {
  animation-name: rv-wave;
  animation-duration: .82s;
  /* Lands a hair past its resting place and settles back — the difference
     between a card that arrives and a card that is placed. */
  animation-timing-function: cubic-bezier(.2, .8, .25, 1.06);
}
@keyframes rv-wave {
  from { opacity: 0; translate: 0 52px; scale: .965; }
  55%  { opacity: 1; }
  to   { opacity: 1; translate: 0 0; scale: 1; }
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* The phase is a repeating 0-1-2 rather than the card's position in the
       whole grid, and that is deliberate: an ever-growing offset would push
       the ninth card's range past the end of its own entry, and a card whose
       range never completes is a card left half-faded on the page. Cycling
       keeps every range inside `entry`, so every card always finishes.

       It also survives the grid reflowing. At three columns the phases line up
       with the columns and the crest sweeps left to right; at two or one they
       fall out of step with the rows, which reads as a looser, less mechanical
       ripple rather than as a bug. */
    .grid-wave > [data-reveal="wave"] { --rv-p: 0; }
    .grid-wave > [data-reveal="wave"]:nth-child(3n + 2) { --rv-p: 1; }
    .grid-wave > [data-reveal="wave"]:nth-child(3n + 3) { --rv-p: 2; }

    .js-reveal .grid-wave > [data-reveal="wave"] {
      /* The observer's class no longer decides anything here: the timeline
         holds the card at the start of the movement until it is genuinely on
         screen, which is a better answer than a class toggling at a threshold. */
      opacity: 1;
      animation: rv-wave-scrub linear both;
      animation-timeline: view();
      animation-delay: 0s;
      animation-range: entry calc(4% + 9% * var(--rv-p, 0))
                       entry calc(64% + 9% * var(--rv-p, 0));
    }
  }
}
@keyframes rv-wave-scrub {
  from { opacity: 0; translate: 0 58px; scale: .955; }
  to   { opacity: 1; translate: 0 0; scale: 1; }
}

@keyframes rv-up   { from { opacity: 0; translate: 0 26px; }  to { opacity: 1; translate: 0 0; } }
@keyframes rv-fade { from { opacity: 0; }                     to { opacity: 1; } }
@keyframes rv-zoom { from { opacity: 0; scale: .93; }         to { opacity: 1; scale: 1; } }
@keyframes rv-left { from { opacity: 0; translate: -30px 0; } to { opacity: 1; translate: 0 0; } }
@keyframes rv-right{ from { opacity: 0; translate: 30px 0; }  to { opacity: 1; translate: 0 0; } }

/* Whatever the script believes, paper gets a still page. */
@media print {
  [data-reveal] { opacity: 1 !important; animation: none !important; }
}

/* Reduced motion keeps the reveals and takes the movement out of them.
   Every variant becomes the same plain dissolve: no rise, no slide, no scale,
   nothing that travels — a change of opacity, which is not motion and is the
   substitution the guidance recommends rather than a page frozen solid.

   This has to be stated at the variant rules' own specificity, not below it.
   Each of those is `.js-reveal [data-reveal="x"].is-in` — three selectors —
   so a rule written only as `.js-reveal [data-reveal]` loses to every one of
   them and the slides would keep sliding. Matching the count and sitting later
   in the file is what actually settles it, and it is worth writing down
   because the same trap has already been walked into once here. */
@media (prefers-reduced-motion: reduce) {
  .js-reveal [data-reveal],
  .js-reveal [data-reveal].is-in {
    animation: none;
    transition: opacity .55s linear;
    translate: none;
    scale: none;
  }
  .js-reveal [data-reveal] { opacity: 0; }
  .js-reveal [data-reveal].is-in { opacity: 1; }
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* Card photographs drift against their crop as the card crosses the
       viewport. The scale provides the headroom the travel spends.

       The timelines are named and declared on the clipping ancestors: view()
       on the child would resolve against the nearest scroll container, and an
       overflow: hidden box *is* one, so the child would be tracked against its
       own clip box and never move. The named timeline tracks the ancestor
       against the real viewport, and descendants can consume it. */
    .card-photo { view-timeline: --rv-card block; }
    .card-photo img {
      scale: 1.12;
      animation: rv-drift linear both;
      animation-timeline: --rv-card;
    }
    @keyframes rv-drift {
      from { translate: 0 3.2%; }
      to   { translate: 0 -3.2%; }
    }

    /* Banner photographs slide slower than the page. With background-size
       cover, position percentages can never expose an edge. */
    .page-hero { view-timeline: --rv-hero block; }
    .page-hero.has-photo::before {
      animation: rv-hero-drift linear both;
      animation-timeline: --rv-hero;
    }
    @keyframes rv-hero-drift {
      from { background-position: center, 50% 30%; }
      to   { background-position: center, 50% 70%; }
    }
  }
}
