/* ---- tokens.css ---- */
/* grace-os · design tokens
 OD-7 resolved: palette sampled from the clinic logo (blue gradient molar + navy wordmark).
 This file is the only place a raw colour value may appear. */

@font-face{font-family:Fraunces;src:url("../fonts/fraunces-400.woff2")format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:Fraunces;src:url("../fonts/fraunces-400-italic.woff2")format("woff2");font-weight:400;font-style:italic;font-display:swap}
@font-face{font-family:Fraunces;src:url("../fonts/fraunces-600.woff2")format("woff2");font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:Inter;src:url("../fonts/inter-400.woff2")format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:Inter;src:url("../fonts/inter-500.woff2")format("woff2");font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:Inter;src:url("../fonts/inter-600.woff2")format("woff2");font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:"JetBrains Mono";src:url("../fonts/jbmono-500.woff2")format("woff2");font-weight:500;font-style:normal;font-display:swap}

:root{
  color-scheme: light;

  /* ---- brand, sampled from logo-grace-dental.png ----
 --g-navy does TWO jobs and they diverge in dark mode:
 as TEXT it is the heading colour, and in dark it must become light
 as a GROUND it is the strong brand fill, and in dark it must stay dark
 Splitting them is why the dark dashboard has readable headings. Use
 --g-ground-strong for any background or button fill, and --g-navy only for
 text. The --g-on-* tokens carry the correct foreground for each fill,
 because in dark mode --g-blue, --g-warn and --g-ok all become LIGHT, and
 white text on a light fill is unreadable. */
  --g-navy:      #0A2B5C;
  --g-navy-deep: #062043;
  --g-ground-strong: #0A2B5C;
  --g-on-ground: #FFFFFF;
  --g-on-blue:   #FFFFFF;
  --g-on-warn:   #FFFFFF;
  --g-on-ok:     #FFFFFF;
  --g-on-hold:   #3A2C05;
  --g-blue:      #0B6FC4;
  --g-blue-lift: #0086E4;
  --g-aqua:      #17C4E8;
  --g-aqua-soft: #B9E9F5;
  --g-mist:      #EAF4FB;
  --g-cloud:     #F7FAFC;
  --g-white:     #FFFFFF;

  /* ---- text ---- */
  --g-ink:    #12202F;
  --g-slate:  #43586C;
  /* --g-quiet carries the small print: hints, breadcrumbs, field help, card
 subtitles. It was #6B7F92, which measures 3.71:1 on --g-mist and fails
 WCAG 1.4.3 at the sizes it is actually used at. "Quiet" is a visual weight,
 not a licence to go under the floor, and seniors are a primary audience
 here. This value measures 5.42:1 on mist and 6.04:1 on white. */
  --g-quiet:  #4F657A;
  --g-onDark: #EAF2F8;

  /* ---- lines and states ---- */
  --g-line:      #D6E3EE;
  --g-line-soft: #E8F0F6;
  --g-ok:        #14684D;
  --g-ok-bg:     #E4F4EE;
  --g-ok-line:   #B6DFCD;
  --g-ok-ink:    #0C4A37;
  --g-warn:      #A8451F;
  --g-warn-bg:   #FBEDE7;
  --g-warn-line: #EBC4B2;
  --g-warn-ink:  #6E2C10;
  --g-warn-deep: #8E3817;
  --g-hold:      #7A5B10;
  --g-hold-bg:   #FBF3DC;
  --g-hold-line: #E8D9A8;

  /* live status indicators. These sit on the navy band, so they are tuned for
 that ground rather than for the page, and they are never the only signal. */
  --g-live-on:   #4ADE9E;
  --g-live-soon: #F5C451;
  --g-live-off:  #8FA5B8;
  --g-onNavy-dim:#40607F;

  /* ---- surfaces ---- */
  --g-surface:   var(--g-white);
  --g-surface-2: var(--g-cloud);
  --g-surface-3: var(--g-mist);
  --g-page:      var(--g-white);

  /* ---- type ---- */
  --f-display: Fraunces, Georgia, "Times New Roman", serif;
  --f-ui: Inter, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --f-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Consolas, monospace;

  /* seniors are a primary audience: the base is 17px, not 16px */
  --t-base: 1.0625rem;
  --t-sm:   0.9375rem;
  --t-xs:   0.8125rem;
  --t-lg:   1.1875rem;
  --t-xl:   1.375rem;
  --t-h4:   clamp(1.125rem, 1rem + 0.5vw, 1.3125rem);
  --t-h3:   clamp(1.375rem, 1.2rem + 0.8vw, 1.75rem);
  --t-h2:   clamp(1.75rem, 1.45rem + 1.4vw, 2.5rem);
  --t-h1:   clamp(2.125rem, 1.6rem + 2.4vw, 3.5rem);
  --t-hero: clamp(2.375rem, 1.7rem + 3.1vw, 4.25rem);

  --lh-tight: 1.14;
  --lh-head:  1.24;
  --lh-body:  1.65;

  /* ---- space ---- */
  --s1: 0.25rem;  --s2: 0.5rem;   --s3: 0.75rem;  --s4: 1rem;
  --s5: 1.5rem;   --s6: 2rem;     --s7: 3rem;     --s8: 4rem;
  --s9: 5.5rem;   --s10: 7.5rem;
  --pad-section: clamp(3.5rem, 2rem + 6vw, 7rem);
  --gutter: clamp(1.125rem, 0.6rem + 2.4vw, 2.5rem);
  --measure: 66ch;
  --wrap: 1200px;
  --wrap-wide: 1400px;
  --wrap-narrow: 760px;

  /* ---- shape ---- */
  --r1: 6px; --r2: 10px; --r3: 16px; --r4: 24px; --r-pill: 999px;
  --tap: 44px;

  /* ---- elevation, kept shallow: this is a clinic, not a casino ---- */
  --sh1: 0 1px 2px rgba(10,43,92,.06), 0 1px 1px rgba(10,43,92,.04);
  --sh2: 0 2px 6px rgba(10,43,92,.07), 0 6px 18px rgba(10,43,92,.06);
  --sh3: 0 10px 34px rgba(10,43,92,.12), 0 2px 8px rgba(10,43,92,.06);
  --ring: 0 0 0 3px var(--g-aqua-soft);

  /* ---- motion ---- */
  --ease: cubic-bezier(.22,.61,.36,1);
  --dur1: 140ms; --dur2: 240ms; --dur3: 420ms;

  --z-header: 100;
  --z-buddy: 900;
  --z-modal: 1000;
  --z-toast: 1100;
}

/* The dashboard is the one surface that offers the visitor a dark mode.
 ONE build. The pre-paint theme-init in shared/js/theme-init.js stamps data-theme
 on <html> before first paint, so there is no flash. */
[data-theme="dark"]{
  color-scheme: dark;
  --g-ink:    #E7F0F7;
  --g-slate:  #A7BCCE;
  --g-quiet:  #93AABC;
  /* Headings, labels and table heads all read --g-navy. On a near black ground
 the light value is the only readable one; the dark brand fill lives on in
 --g-ground-strong, which does NOT flip. */
  --g-navy:   #DEEAF6;
  --g-ground-strong: #123255;
  --g-on-ground: #FFFFFF;
  /* --g-blue, --g-warn and --g-ok are LIGHT in this theme, so anything filled
 with them needs dark text, not white. */
  --g-on-blue:  #041525;
  --g-on-warn:  #2A0E05;
  --g-on-ok:    #05231A;
  --g-on-hold:  #2C2205;
  --g-line:      #1E3550;
  --g-line-soft: #16273B;
  --g-surface:   #0E2138;
  --g-surface-2: #0A1A2C;
  --g-surface-3: #132B45;
  --g-page:      #071322;
  --g-mist:      #132B45;
  --g-cloud:     #0A1A2C;
  --g-blue:      #4FA6EE;
  --g-blue-lift: #6FBBF7;
  --g-aqua-soft: #16405A;
  --g-ok:        #6FD3AE;
  --g-ok-bg:     #10352A;
  --g-warn:      #F0A184;
  --g-warn-bg:   #3A1C11;
  --g-hold:      #E4C46A;
  --g-hold-bg:   #362C10;
  --sh1: 0 1px 2px rgba(0,0,0,.35);
  --sh2: 0 2px 8px rgba(0,0,0,.4);
  --sh3: 0 12px 36px rgba(0,0,0,.5);
}


/* ---- base.css ---- */
/* grace-os · base layer
 native document scroll only. No smooth-scroll library, no hijack.
 overflow-x is never hidden on html or body. */

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-top:calc(var(--header-h,68px) + 1rem)}
@media (prefers-reduced-motion: reduce){html{scroll-behavior:auto}}

body{
  margin:0;
  background:var(--g-page);
  color:var(--g-ink);
  font:400 var(--t-base)/var(--lh-body) var(--f-ui);
  font-feature-settings:"cv05" 1,"ss01" 1;
  -webkit-font-smoothing:antialiased;
  overflow-x:clip;              /* clip, never hidden: hidden creates a scroll container */
  min-height:100dvh;
}

h1,h2,h3,h4{margin:0 0 var(--s3);font-family:var(--f-display);font-weight:600;line-height:var(--lh-head);color:var(--g-navy);letter-spacing:-.012em;text-wrap:balance}
h1{font-size:var(--t-h1);line-height:var(--lh-tight)}
h2{font-size:var(--t-h2)}
h3{font-size:var(--t-h3)}
h4{font-size:var(--t-h4);font-family:var(--f-ui);font-weight:600;letter-spacing:0}
p{margin:0 0 var(--s4);max-width:var(--measure);text-wrap:pretty}
ul,ol{margin:0 0 var(--s4);padding-left:1.25em}
li{margin:0 0 var(--s2);max-width:var(--measure)}
strong,b{font-weight:600}
small{font-size:var(--t-sm)}
img,svg,video{max-width:100%;height:auto;display:block}
hr{border:0;border-top:1px solid var(--g-line);margin:var(--s6) 0}

a{color:var(--g-blue);text-decoration-thickness:1px;text-underline-offset:.18em}
a:hover{color:var(--g-blue-lift)}

:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--g-aqua);
  outline-offset:2px;
  border-radius:var(--r1);
}

::selection{background:var(--g-aqua-soft);color:var(--g-navy)}

/* ---------- layout primitives ---------- */
.wrap{width:min(var(--wrap),100% - var(--gutter)*2);margin-inline:auto}
.wrap-wide{width:min(var(--wrap-wide),100% - var(--gutter)*2);margin-inline:auto}
.wrap-narrow{width:min(var(--wrap-narrow),100% - var(--gutter)*2);margin-inline:auto}
.section{padding-block:var(--pad-section)}
.section-tight{padding-block:calc(var(--pad-section) * .6)}
.tint{background:var(--g-mist)}
.tint-soft{background:var(--g-cloud)}
.ink-panel{background:var(--g-ground-strong);color:var(--g-onDark)}
.ink-panel h1,.ink-panel h2,.ink-panel h3{color:var(--g-white)}
.ink-panel a{color:var(--g-aqua-soft)}

.grid{display:grid;gap:var(--s5)}
.g-2{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}
.g-3{grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr))}
.g-4{grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr))}
.row{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center}
.stack>*+*{margin-top:var(--s4)}
.center{text-align:center}
.center p{margin-inline:auto}

/* ---------- utility ---------- */
/* The section label above a heading.
 It used to be uppercase mono with wide tracking and a small aqua dash drawn
 before it. That combination is the single most recognisable signature of a
 generated landing page, and it appeared above twenty headings across the site.
 The label still earns its place, because it tells you which part of the page
 you are in, so it stays. The costume goes: no leading rule, no uppercase, the
 ordinary UI face, and a weight that sits under the heading instead of
 competing with it. The copy is already written in sentence case, so it now
 reads the way it was written. */
.eyebrow{
  font:600 var(--t-sm)/1.3 var(--f-ui);
  letter-spacing:0;color:var(--g-blue);
  display:block;margin-bottom:.4rem;
}
.lede{font-size:var(--t-lg);color:var(--g-slate);line-height:1.6}
.muted{color:var(--g-slate)}
.quiet{color:var(--g-quiet);font-size:var(--t-sm)}
.mono{font-family:var(--f-mono);font-size:var(--t-sm);letter-spacing:.02em}
.nowrap{white-space:nowrap}
.visually-hidden{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.skip{position:absolute;left:var(--s4);top:-100px;z-index:calc(var(--z-modal) + 1);background:var(--g-ground-strong);color:var(--g-on-ground);padding:.75rem 1.15rem;border-radius:var(--r2);transition:top var(--dur2) var(--ease)}
.skip:focus{top:var(--s4)}

/* ---------- motion is additive and opt-in ----------
 Content is visible by default. html.reveal-ready is set by JS only when
 motion is allowed, and only then does anything animate. */
.reveal{opacity:1;transform:none}
html.reveal-ready .reveal{opacity:0;transform:translateY(14px);transition:opacity var(--dur3) var(--ease),transform var(--dur3) var(--ease)}
html.reveal-ready .reveal.in{opacity:1;transform:none}
html.reveal-ready .reveal-d1{transition-delay:70ms}
html.reveal-ready .reveal-d2{transition-delay:140ms}
html.reveal-ready .reveal-d3{transition-delay:210ms}
@media (prefers-reduced-motion: reduce){
  html.reveal-ready .reveal{opacity:1!important;transform:none!important;transition:none!important}
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}

/* ---------- print ---------- */
@media print{
  .site-header,.site-footer,.buddy-launch,.buddy-panel,.no-print{display:none!important}
  body{background:var(--g-white);color:var(--g-navy-deep);font-size:11pt}
  a[href^="http"]::after{content:" (" attr(href) ")";font-size:9pt;color:var(--g-slate)}
}


/* ---- components.css ---- */
/* grace-os · components
 Every interactive target is at least 44px. Every state is legible in greyscale. */

/* ============ buttons ============ */
.btn{
  --btn-bg:var(--g-blue); --btn-fg:var(--g-on-blue); --btn-bd:var(--g-blue);
  display:inline-flex;align-items:center;justify-content:center;gap:.55em;
  min-height:var(--tap);padding:.7rem 1.4rem;
  font:500 var(--t-base)/1.2 var(--f-ui);
  background:var(--btn-bg);color:var(--btn-fg);border:1px solid var(--btn-bd);
  border-radius:var(--r-pill);cursor:pointer;text-decoration:none;text-align:center;
  transition:background var(--dur1) var(--ease),border-color var(--dur1) var(--ease),color var(--dur1) var(--ease),box-shadow var(--dur1) var(--ease),transform var(--dur1) var(--ease);
}
.btn:hover{--btn-bg:var(--g-blue-lift);--btn-bd:var(--g-blue-lift);color:var(--g-on-blue);box-shadow:var(--sh2)}
.btn:active{transform:translateY(1px)}
.btn[disabled],.btn[aria-disabled="true"]{opacity:.5;cursor:not-allowed;box-shadow:none;transform:none}
.btn-lg{min-height:52px;padding:.9rem 1.9rem;font-size:var(--t-lg)}
.btn-sm{min-height:38px;padding:.45rem 1rem;font-size:var(--t-sm)}
.btn-ghost{--btn-bg:transparent;--btn-fg:var(--g-blue);--btn-bd:var(--g-line)}
.btn-ghost:hover{--btn-bg:var(--g-mist);--btn-bd:var(--g-blue);color:var(--g-blue)}
.btn-quiet{--btn-bg:transparent;--btn-fg:var(--g-slate);--btn-bd:transparent}
.btn-quiet:hover{--btn-bg:var(--g-mist);--btn-fg:var(--g-navy);box-shadow:none}
.btn-ink{--btn-bg:var(--g-ground-strong);--btn-fg:var(--g-on-ground);--btn-bd:var(--g-ground-strong)}
.btn-ink:hover{--btn-bg:var(--g-navy-deep);--btn-bd:var(--g-navy-deep)}
.btn-onDark{--btn-bg:var(--g-white);--btn-fg:var(--g-ground-strong);--btn-bd:var(--g-white)}
.btn-onDark:hover{--btn-bg:var(--g-aqua-soft);--btn-fg:var(--g-ground-strong);--btn-bd:var(--g-aqua-soft)}
.btn-urgent{--btn-bg:var(--g-warn);--btn-fg:var(--g-on-warn);--btn-bd:var(--g-warn)}
.btn-urgent:hover{--btn-bg:var(--g-warn-deep);--btn-bd:var(--g-warn-deep)}
.btn-block{width:100%}
.btn .ic{width:1.15em;height:1.15em;flex:none}

/* ============ the status band ============
 The clinic's genuine differentiator is that it is open seven days, to 21:00 on
 weekdays. This band computes that against the schedule tables in America/Toronto
 and states it plainly. It is not decoration: if the engine cannot resolve a state
 it renders the neutral variant and says so. */
.status-band{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s5);
  padding:.6rem var(--gutter);
  background:var(--g-navy-deep);color:var(--g-onDark);
  font:500 var(--t-sm)/1.4 var(--f-ui);
}
.status-band a{color:var(--g-aqua-soft);text-decoration:none;min-height:var(--tap);display:inline-flex;align-items:center}
.status-band a:hover{text-decoration:underline}
.status-now{display:inline-flex;align-items:center;gap:.55em;font-weight:600}
.status-dot{width:.6rem;height:.6rem;border-radius:50%;background:var(--g-quiet);flex:none;position:relative}
.status-dot[data-state="open"]{background:var(--g-live-on)}
.status-dot[data-state="closing"]{background:var(--g-live-soon)}
.status-dot[data-state="closed"]{background:var(--g-live-off)}
html.reveal-ready .status-dot[data-state="open"]::after{
  content:"";position:absolute;inset:-4px;border-radius:50%;border:1px solid var(--g-live-on);opacity:.55;
  animation:pulse 2.6s var(--ease) infinite;
}
@keyframes pulse{0%{transform:scale(.7);opacity:.7}70%{transform:scale(1.35);opacity:0}100%{opacity:0}}
.status-sep{color:var(--g-onNavy-dim)}
.status-band .mono{color:var(--g-onDark);opacity:.85}

/* ============ header ============ */
.site-header{position:sticky;top:0;z-index:var(--z-header);background:var(--g-white);border-bottom:1px solid var(--g-line-soft);transition:box-shadow var(--dur2) var(--ease)}
.site-header[data-stuck="true"]{box-shadow:var(--sh2)}
.hdr{display:flex;align-items:center;gap:var(--s4);min-height:68px;padding-block:.5rem}
.brand{display:flex;align-items:center;gap:.7rem;text-decoration:none;color:var(--g-navy);flex:none}
.brand img{height:42px;width:auto}
.brand-name{font:600 1.0625rem/1.05 var(--f-display);letter-spacing:-.01em}
.brand-sub{display:block;font:500 .625rem/1.4 var(--f-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--g-quiet)}
.nav{margin-left:auto;display:flex;align-items:center;gap:.15rem}
.nav a{
  display:inline-flex;align-items:center;min-height:var(--tap);padding:.4rem .8rem;
  color:var(--g-ink);text-decoration:none;font-size:var(--t-sm);font-weight:500;border-radius:var(--r2);
}
.nav a:hover{background:var(--g-mist);color:var(--g-navy)}
.nav a[aria-current="page"]{color:var(--g-blue);box-shadow:inset 0 -2px 0 var(--g-aqua)}
.nav-cta{margin-left:var(--s3);display:flex;gap:.5rem;align-items:center}
.hdr-toggle{display:none;align-items:center;justify-content:center;width:var(--tap);height:var(--tap);margin-left:auto;background:none;border:1px solid var(--g-line);border-radius:var(--r2);cursor:pointer;color:var(--g-navy)}

/* submenu */
.has-sub{position:relative}
.has-sub>button{display:inline-flex;align-items:center;gap:.35em;min-height:var(--tap);padding:.4rem .8rem;background:none;border:0;font:500 var(--t-sm) var(--f-ui);color:var(--g-ink);cursor:pointer;border-radius:var(--r2)}
.has-sub>button:hover{background:var(--g-mist);color:var(--g-navy)}
.has-sub>button .chev{width:.7em;height:.7em;transition:transform var(--dur1) var(--ease)}
.has-sub[data-open="true"]>button .chev{transform:rotate(180deg)}
/* Closed by default in CSS, not by JS. Without this the submenu hangs open on a
 page whose script has not run yet, which is exactly what a slow connection sees. */
.submenu{display:none;position:absolute;top:calc(100% + .4rem);left:0;min-width:280px;background:var(--g-white);border:1px solid var(--g-line);border-radius:var(--r3);box-shadow:var(--sh3);padding:.4rem;margin:0;list-style:none}
.has-sub:hover>.submenu,.has-sub:focus-within>.submenu,.has-sub[data-open="true"]>.submenu{display:block}
.submenu a{display:block;padding:.6rem .8rem;border-radius:var(--r2);font-size:var(--t-sm);min-height:var(--tap)}
.submenu a:hover{background:var(--g-mist)}
.submenu .sub-note{display:block;font-size:var(--t-xs);color:var(--g-quiet);font-weight:400;margin-top:.1rem}

@media (max-width:1040px){
  .hdr-toggle{display:inline-flex}
  .nav{
    position:fixed;inset:auto 0 0 0;top:var(--header-h,68px);
    flex-direction:column;align-items:stretch;gap:0;
    background:var(--g-white);border-top:1px solid var(--g-line);
    padding:var(--s4) var(--gutter) calc(var(--s8) + env(safe-area-inset-bottom));
    overflow-y:auto;margin:0;
    transform:translateY(-8px);opacity:0;pointer-events:none;
    transition:opacity var(--dur2) var(--ease),transform var(--dur2) var(--ease);
  }
  .nav[data-open="true"]{transform:none;opacity:1;pointer-events:auto}
  .nav a,.has-sub>button{width:100%;justify-content:flex-start;padding:.85rem .5rem;font-size:var(--t-base);border-bottom:1px solid var(--g-line-soft);border-radius:0}
  .submenu{position:static;border:0;box-shadow:none;padding:0 0 .5rem 1rem;min-width:0;display:none}
  .has-sub[data-open="true"] .submenu{display:block}
  .nav-cta{margin:var(--s5) 0 0;flex-direction:column;align-items:stretch}
  .nav-cta .btn{width:100%}
}

/* ============ cards ============ */
.card{
  background:var(--g-surface);border:1px solid var(--g-line);border-radius:var(--r3);
  padding:var(--s5);box-shadow:var(--sh1);
  transition:box-shadow var(--dur2) var(--ease),border-color var(--dur2) var(--ease),transform var(--dur2) var(--ease);
  display:flex;flex-direction:column;
}
a.card,.card-link{text-decoration:none;color:inherit}
a.card:hover,.card-link:hover{border-color:var(--g-aqua);box-shadow:var(--sh2);transform:translateY(-2px)}
.card h3,.card h4{margin-bottom:var(--s2)}
.card p{margin-bottom:var(--s3)}
.card>:last-child{margin-bottom:0}
.card-media{margin:calc(var(--s5)*-1) calc(var(--s5)*-1) var(--s4);border-radius:var(--r3) var(--r3) 0 0;overflow:hidden;background:var(--g-mist)}
.card-media img{width:100%;aspect-ratio:4/3;object-fit:cover}
.card-flat{box-shadow:none;background:var(--g-cloud);border-color:var(--g-line-soft)}
.card-foot{margin-top:auto;padding-top:var(--s4);display:flex;align-items:center;gap:.5em;font-weight:500;font-size:var(--t-sm);color:var(--g-blue)}
.card-foot .ic{width:1em;height:1em;transition:transform var(--dur1) var(--ease)}
a.card:hover .card-foot .ic{transform:translateX(3px)}

/* the orbit mark, lifted from the logo. one ornament, used sparingly. */
.orbit{position:relative}
.orbit::before{
  content:"";position:absolute;inset:-14% -8% auto auto;width:clamp(120px,18vw,220px);aspect-ratio:1;
  border:1px solid var(--g-aqua);border-radius:50%;opacity:.28;
  transform:rotate(-18deg) scaleY(.42);pointer-events:none;
}

/* ============ feature list ============ */
.feature{display:flex;gap:var(--s4);align-items:flex-start}
.feature-ic{
  flex:none;width:46px;height:46px;border-radius:var(--r2);
  background:var(--g-mist);display:grid;place-items:center;color:var(--g-blue);
}
.feature-ic img{width:26px;height:26px;object-fit:contain}
.feature-ic svg{width:22px;height:22px}
.feature h4{margin-bottom:.2rem}
.feature p{margin:0;font-size:var(--t-sm);color:var(--g-slate)}

/* ============ chips ============ */
.chips{display:flex;flex-wrap:wrap;gap:.5rem}
/* 44px, not 38px. A chip is a primary control on the FAQ and inside Buddy, and
 the house floor for an interactive target is 44px regardless of what WCAG 2.5.8
 would tolerate. Older hands and phone thumbs are the actual users here. */
.chip{
  display:inline-flex;align-items:center;gap:.4em;min-height:var(--tap);padding:.5rem 1rem;
  background:var(--g-white);border:1px solid var(--g-line);border-radius:var(--r-pill);
  font:500 var(--t-sm)/1.2 var(--f-ui);color:var(--g-navy);cursor:pointer;text-decoration:none;
  transition:background var(--dur1) var(--ease),border-color var(--dur1) var(--ease),color var(--dur1) var(--ease);
}
.chip:hover{background:var(--g-mist);border-color:var(--g-blue);color:var(--g-blue)}
.chip[aria-pressed="true"],.chip.is-on{background:var(--g-ground-strong);border-color:var(--g-ground-strong);color:var(--g-on-ground)}

/* ============ badges ============ */
.badge{display:inline-flex;align-items:center;gap:.4em;padding:.22rem .6rem;border-radius:var(--r-pill);font:500 var(--t-xs)/1.5 var(--f-ui);white-space:nowrap}
.badge-ok{background:var(--g-ok-bg);color:var(--g-ok)}
.badge-warn{background:var(--g-warn-bg);color:var(--g-warn)}
.badge-hold{background:var(--g-hold-bg);color:var(--g-hold)}
.badge-info{background:var(--g-mist);color:var(--g-blue)}
.badge-neutral{background:var(--g-cloud);color:var(--g-slate);border:1px solid var(--g-line)}
/* No leading dot. The badge already carries its state as words, and a coloured
 pip in front of every label is chrome, not information. The states stay legible
 in greyscale because the text says what they are, which was always the point. */

/* ============ forms ============ */
.field{margin-bottom:var(--s4);display:block}
.field>label,.label{display:block;font-weight:500;font-size:var(--t-sm);color:var(--g-navy);margin-bottom:.35rem}
.req{color:var(--g-warn);font-weight:600}
.hint{display:block;font-size:var(--t-xs);color:var(--g-quiet);margin-top:.3rem;max-width:56ch}
.input,.select,.textarea{
  width:100%;min-height:var(--tap);padding:.65rem .85rem;
  font:400 var(--t-base)/1.4 var(--f-ui);color:var(--g-ink);
  background:var(--g-white);border:1px solid var(--g-line);border-radius:var(--r2);
  transition:border-color var(--dur1) var(--ease),box-shadow var(--dur1) var(--ease);
}
.textarea{min-height:118px;resize:vertical}
.select{appearance:none;padding-right:2.4rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%2343586C' stroke-width='1.6' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right .9rem center;background-size:12px 8px}
.input:focus,.select:focus,.textarea:focus{border-color:var(--g-blue);box-shadow:var(--ring);outline:none}
.input[aria-invalid="true"],.select[aria-invalid="true"],.textarea[aria-invalid="true"]{border-color:var(--g-warn);box-shadow:0 0 0 3px var(--g-warn-bg)}
.err{display:none;margin-top:.35rem;font-size:var(--t-sm);color:var(--g-warn);font-weight:500}
.err[data-show="true"]{display:block}
.check{display:flex;gap:.65rem;align-items:flex-start;min-height:var(--tap);padding:.35rem 0;cursor:pointer}
.check input{width:1.25rem;height:1.25rem;margin-top:.2rem;flex:none;accent-color:var(--g-blue)}
.check span{font-size:var(--t-sm);line-height:1.5}
fieldset{border:1px solid var(--g-line);border-radius:var(--r3);padding:var(--s4);margin:0 0 var(--s5)}
legend{padding:0 .5rem;font-weight:600;font-size:var(--t-sm);color:var(--g-navy)}
.form-note{background:var(--g-mist);border-left:3px solid var(--g-aqua);border-radius:0 var(--r2) var(--r2) 0;padding:var(--s3) var(--s4);font-size:var(--t-sm);color:var(--g-slate)}
.form-note p:last-child{margin-bottom:0}

/* ============ notice ============ */
.notice{display:flex;gap:var(--s3);padding:var(--s4);border-radius:var(--r3);border:1px solid var(--g-line);background:var(--g-cloud);font-size:var(--t-sm)}
.notice .ic{width:1.3em;height:1.3em;flex:none;margin-top:.15em}
.notice p:last-child{margin-bottom:0}
.notice-warn{background:var(--g-warn-bg);border-color:var(--g-warn-line);color:var(--g-warn-ink)}
.notice-warn a{color:var(--g-warn-ink)}
.notice-info{background:var(--g-mist);border-color:var(--g-aqua-soft)}
.notice-ok{background:var(--g-ok-bg);border-color:var(--g-ok-line);color:var(--g-ok-ink)}

/* the estimate honesty string is a component, not a paragraph someone might edit away */
.estimate-note{font-size:var(--t-xs);color:var(--g-slate);background:var(--g-cloud);border:1px dashed var(--g-line);border-radius:var(--r2);padding:.6rem .8rem;margin-top:var(--s3)}

/* ============ tables ============ */
.table-scroll{overflow-x:auto;border:1px solid var(--g-line);border-radius:var(--r3);background:var(--g-surface)}
table.data{width:100%;border-collapse:collapse;font-size:var(--t-sm);min-width:520px}
table.data th,table.data td{text-align:left;padding:.7rem .85rem;border-bottom:1px solid var(--g-line-soft);vertical-align:top}
table.data thead th{background:var(--g-cloud);font-weight:600;color:var(--g-navy);position:sticky;top:0;z-index:1;white-space:nowrap}
table.data tbody tr:last-child td{border-bottom:0}
table.data tbody tr:hover{background:var(--g-cloud)}
table.data td.num,table.data th.num{text-align:right;font-family:var(--f-mono)}

/* ============ accordion ============ */
.acc{border:1px solid var(--g-line);border-radius:var(--r3);overflow:hidden;background:var(--g-surface)}
.acc+.acc{margin-top:.6rem}
.acc summary{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s4);
  min-height:var(--tap);padding:var(--s4);cursor:pointer;list-style:none;
  font-weight:500;color:var(--g-navy);
}
.acc summary::-webkit-details-marker{display:none}
.acc summary:hover{background:var(--g-cloud)}
.acc summary .chev{width:1em;height:1em;flex:none;color:var(--g-blue);transition:transform var(--dur2) var(--ease)}
.acc[open] summary .chev{transform:rotate(180deg)}
.acc[open] summary{border-bottom:1px solid var(--g-line-soft)}
.acc-body{padding:var(--s4)}
.acc-body>:last-child{margin-bottom:0}

/* ============ dialog ============ */
dialog{
  border:0;padding:0;border-radius:var(--r4);box-shadow:var(--sh3);
  max-width:min(560px,calc(100vw - 2rem));width:100%;background:var(--g-surface);color:var(--g-ink);
}
dialog::backdrop{background:rgba(6,32,67,.55);backdrop-filter:blur(2px)}
.dlg-head{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s4);padding:var(--s5) var(--s5) var(--s3)}
.dlg-head h2,.dlg-head h3{margin:0}
.dlg-body{padding:0 var(--s5) var(--s5)}
.dlg-foot{display:flex;gap:.6rem;justify-content:flex-end;flex-wrap:wrap;padding:var(--s4) var(--s5);border-top:1px solid var(--g-line-soft);background:var(--g-cloud);border-radius:0 0 var(--r4) var(--r4)}
.dlg-x{width:var(--tap);height:var(--tap);flex:none;display:grid;place-items:center;background:none;border:0;border-radius:var(--r2);cursor:pointer;color:var(--g-slate)}
.dlg-x:hover{background:var(--g-mist);color:var(--g-navy)}

/* ============ toast ============ */
.toasts{position:fixed;left:50%;bottom:calc(1rem + env(safe-area-inset-bottom));transform:translateX(-50%);z-index:var(--z-toast);display:flex;flex-direction:column;gap:.5rem;width:min(440px,calc(100vw - 2rem));pointer-events:none}
.toast{pointer-events:auto;background:var(--g-ground-strong);color:var(--g-on-ground);border-radius:var(--r3);padding:.8rem 1rem;box-shadow:var(--sh3);font-size:var(--t-sm);display:flex;gap:.6rem;align-items:flex-start}
.toast-ok{background:var(--g-ok);color:var(--g-on-ok)}
.toast-warn{background:var(--g-warn);color:var(--g-on-warn)}

/* ============ footer ============ */
.site-footer{background:var(--g-navy-deep);color:var(--g-onDark);padding-block:var(--s8) var(--s5);margin-top:auto}
.site-footer h4{color:var(--g-white);font-size:var(--t-sm);font-family:var(--f-mono);font-weight:500;letter-spacing:.12em;text-transform:uppercase;margin-bottom:var(--s3);color:var(--g-aqua-soft)}
.site-footer a{color:var(--g-onDark);text-decoration:none}
.site-footer a:hover{color:var(--g-white);text-decoration:underline}
.foot-grid{display:grid;gap:var(--s6);grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr))}
.foot-grid ul{list-style:none;padding:0;margin:0}
.foot-grid li{margin-bottom:.55rem}
/* Footer links are navigation, not prose, so they take the full 44px target.
 The exemption for a link inline in a sentence does not apply to a list of
 links, and this footer is how a lot of people on a phone reach a service page.
 Breadcrumbs, the phone number inside the address block and links inside body
 copy stay inline, because forcing a target size on those breaks the line. */
.foot-grid li{margin-bottom:.15rem}
.foot-grid li a{display:inline-flex;align-items:center;min-height:var(--tap);font-size:var(--t-sm)}
.foot-brand img{height:46px;width:auto;margin-bottom:var(--s3);filter:brightness(0) invert(1);opacity:.95}
.foot-hours{font-family:var(--f-mono);font-size:var(--t-xs);line-height:1.9;color:var(--g-onDark);opacity:.9}
.foot-hours b{color:var(--g-white);font-weight:500}
.foot-base{margin-top:var(--s7);padding-top:var(--s4);border-top:1px solid rgba(255,255,255,.13);display:flex;flex-wrap:wrap;gap:var(--s3) var(--s5);align-items:center;justify-content:space-between;font-size:var(--t-xs);opacity:.82}
.foot-base a{text-decoration:underline;text-underline-offset:.2em}

/* ============ mobile action bar ============ */
.action-bar{
  position:fixed;left:0;right:0;bottom:0;z-index:calc(var(--z-header) - 1);
  display:none;gap:.5rem;padding:.55rem var(--gutter) calc(.55rem + env(safe-area-inset-bottom));
  background:var(--g-white);border-top:1px solid var(--g-line);box-shadow:0 -2px 14px rgba(10,43,92,.09);
}
.action-bar .btn{flex:1}
@media (max-width:760px){
  .action-bar{display:flex}
  body{padding-bottom:76px}
  .buddy-launch{bottom:calc(84px + env(safe-area-inset-bottom))!important}
}

/* ============ skeleton ============ */
.skel{background:linear-gradient(90deg,var(--g-line-soft) 25%,var(--g-mist) 37%,var(--g-line-soft) 63%);background-size:400% 100%;border-radius:var(--r2);min-height:1em}
html.reveal-ready .skel{animation:shimmer 1.5s linear infinite}
@keyframes shimmer{0%{background-position:100% 0}100%{background-position:0 0}}

/* ============ demo seam banner ============ */
.demo-bar{
  display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;
  padding:.5rem var(--gutter);background:var(--g-hold-bg);color:var(--g-hold);
  font:500 var(--t-xs)/1.5 var(--f-ui);border-bottom:1px solid var(--g-hold-line);
}
.demo-bar strong{font-weight:600}
.demo-bar a{color:var(--g-hold)}


/* ---- buddy.css ---- */
/* grace-os · Grace Buddy
 Tokens only. Not one raw colour value lives in this file, so a palette change
 in tokens.css reaches the concierge without anybody editing it here.

 BUILD NOTE for whoever owns tools/build.py: copy_assets() concatenates
 tokens.css, base.css and components.css into assets/css/app.css. Add
 "buddy.css" to that tuple so this file ships. Until it does, buddy.js injects
 a layout only fallback and warns in the console, so the widget still works,
 it just looks plain. */

.buddy {
  /* the sentinel buddy.js reads to know this stylesheet arrived */
  --buddy-ready: 1;
  --buddy-w: 400px;
  --buddy-gap: var(--s3);
  display: contents;
}

/* Both of these are toggled through the hidden property in JS. Some of them are
 flex or grid containers, and display would quietly beat hidden. */
.buddy [hidden],
.buddy[hidden] { display: none !important; }

/* ============ launcher ============ */
.buddy-launch {
  position: fixed;
  right: var(--gutter);
  bottom: calc(var(--s4) + env(safe-area-inset-bottom));
  z-index: var(--z-buddy);
  display: inline-flex;
  align-items: center;
  gap: .55em;
  min-height: var(--tap);
  padding: .7rem 1.25rem;
  font: 500 var(--t-sm)/1.2 var(--f-ui);
  color: var(--g-on-ground);
  background: var(--g-ground-strong);
  border: 1px solid var(--g-ground-strong);
  border-radius: var(--r-pill);
  box-shadow: var(--sh3);
  cursor: pointer;
  transition: background var(--dur1) var(--ease), transform var(--dur1) var(--ease);
}
.buddy-launch:hover { background: var(--g-blue); border-color: var(--g-blue); }
.buddy-launch:active { transform: translateY(1px); }
.buddy-launch .ic { width: 1.15em; height: 1.15em; flex: none; }

/* the panel is the way back out on a phone, so the launcher steps aside */
.buddy[data-open="true"][data-modal="true"] .buddy-launch { display: none; }

/* ============ panel ============ */
.buddy-panel {
  position: fixed;
  right: var(--gutter);
  bottom: calc(var(--s4) + var(--tap) + var(--buddy-gap) + env(safe-area-inset-bottom));
  z-index: var(--z-buddy);
  display: flex;
  flex-direction: column;
  width: min(var(--buddy-w), calc(100vw - var(--gutter) * 2));
  max-height: 640px;
  max-height: min(640px, calc(100dvh - 9rem));
  overflow: hidden;
  background: var(--g-surface);
  color: var(--g-ink);
  border: 1px solid var(--g-line);
  border-radius: var(--r4);
  box-shadow: var(--sh3);
}
.buddy-panel:focus { outline: none; }
.buddy-panel:focus-visible { outline: 2px solid var(--g-aqua); outline-offset: 2px; }

@media (prefers-reduced-motion: no-preference) {
  .buddy-panel { animation: buddy-in var(--dur2) var(--ease) both; }
  @keyframes buddy-in {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: none; }
  }
}

/* ---- head ---- */
.buddy-head {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  padding: var(--s4) var(--s4) var(--s3);
  background: var(--g-navy-deep);
  color: var(--g-onDark);
}
.buddy-head-text { flex: 1 1 auto; min-width: 0; }
.buddy-title {
  margin: 0;
  font: 600 var(--t-lg)/1.2 var(--f-display);
  color: var(--g-white);
  letter-spacing: -.01em;
}
.buddy-sub {
  margin: .15rem 0 0;
  max-width: none;
  font: 400 var(--t-xs)/1.45 var(--f-ui);
  color: var(--g-aqua-soft);
}
.buddy-lang {
  flex: none;
  min-height: 36px;
  padding: .2rem .5rem;
  font: 500 var(--t-xs) var(--f-ui);
  color: var(--g-onDark);
  background: transparent;
  border: 1px solid var(--g-slate);
  border-radius: var(--r1);
}
.buddy-x {
  flex: none;
  width: var(--tap);
  height: var(--tap);
  margin: calc(var(--s2) * -1) calc(var(--s2) * -1) 0 0;
  display: grid;
  place-items: center;
  color: var(--g-onDark);
  background: none;
  border: 0;
  border-radius: var(--r2);
  cursor: pointer;
}
.buddy-x:hover { background: var(--g-ground-strong); color: var(--g-on-ground); }
.buddy-x .ic { width: 1.1em; height: 1.1em; }

/* ---- the two controls that are always there ---- */
.buddy-chrome {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  padding: var(--s3) var(--s4);
  background: var(--g-cloud);
  border-bottom: 1px solid var(--g-line);
}
.buddy-chrome .btn { flex: 1 1 auto; }

/* ---- transcript ---- */
.buddy-log {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--s4);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  background: var(--g-surface);
}
.buddy-divider {
  margin: 0;
  max-width: none;
  font: 500 var(--t-xs)/1 var(--f-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--g-quiet);
  text-align: center;
}

.buddy-msg { display: flex; flex-direction: column; gap: .5rem; align-items: flex-start; }
.buddy-msg[data-who="you"] { align-items: flex-end; }

.buddy-bubble {
  max-width: 92%;
  padding: .7rem .9rem;
  font-size: var(--t-base);
  line-height: var(--lh-body);
  background: var(--g-mist);
  color: var(--g-ink);
  border: 1px solid var(--g-line-soft);
  border-radius: var(--r3);
  border-top-left-radius: var(--r1);
}
.buddy-bubble p { margin: 0 0 .6rem; max-width: none; }
.buddy-bubble p:last-child { margin-bottom: 0; }

.buddy-msg[data-who="you"] .buddy-bubble {
  background: var(--g-ground-strong);
  color: var(--g-onDark);
  border-color: var(--g-ground-strong);
  border-radius: var(--r3);
  border-top-right-radius: var(--r1);
}

/* an emergency answer is meant to be unmissable, not decorative */
.buddy-msg[data-kind="emergency"] .buddy-bubble {
  background: var(--g-warn-bg);
  border-color: var(--g-warn);
  border-left-width: 4px;
  color: var(--g-warn);
  font-weight: 500;
}
/* the dentist has not signed this one off yet, and that should look deliberate */
.buddy-msg[data-kind="unsigned"] .buddy-bubble,
.buddy-msg[data-kind="blocked"] .buddy-bubble {
  background: var(--g-hold-bg);
  border-color: var(--g-hold);
  color: var(--g-hold);
}
.buddy-msg[data-kind="human"] .buddy-bubble {
  background: var(--g-ok-bg);
  border-color: var(--g-ok);
  color: var(--g-ok);
}

/* ---- links and chips ---- */
.buddy-links,
.buddy-chips {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  max-width: 100%;
}
.buddy-chip,
.buddy-link {
  min-height: var(--tap);
  font-size: var(--t-sm);
  text-align: left;
  white-space: normal;
}
.buddy-link { text-decoration: none; }
.buddy-chip-group {
  flex: 1 0 100%;
  margin: .3rem 0 0;
  font: 500 var(--t-xs)/1 var(--f-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--g-quiet);
}
.buddy-chip-group:first-child { margin-top: 0; }

/* ---- typing, decorative only ---- */
.buddy-typing { display: flex; gap: .3rem; padding: .5rem .2rem; }
.buddy-dot {
  width: .45rem;
  height: .45rem;
  border-radius: 50%;
  background: var(--g-quiet);
  opacity: .5;
}
@media (prefers-reduced-motion: no-preference) {
  .buddy-dot { animation: buddy-blink 1.1s var(--ease) infinite; }
  .buddy-dot:nth-child(2) { animation-delay: .15s; }
  .buddy-dot:nth-child(3) { animation-delay: .3s; }
  @keyframes buddy-blink {
    0%, 100% { opacity: .28; transform: translateY(0); }
    50% { opacity: .9; transform: translateY(-2px); }
  }
}

/* ---- ask box ---- */
.buddy-ask {
  display: flex;
  gap: .5rem;
  align-items: center;
  padding: var(--s3) var(--s4);
  border-top: 1px solid var(--g-line);
  background: var(--g-surface-2);
}
.buddy-ask .input { flex: 1 1 auto; font-size: var(--t-sm); }
.buddy-ask .btn { flex: none; }

.buddy-foot {
  margin: 0;
  max-width: none;
  padding: 0 var(--s4) var(--s3);
  font-size: var(--t-xs);
  line-height: 1.45;
  color: var(--g-quiet);
  background: var(--g-surface-2);
}

/* ---- the after hours call back form ---- */
.buddy-callback {
  width: 100%;
  padding: var(--s3);
  background: var(--g-cloud);
  border: 1px solid var(--g-line);
  border-radius: var(--r3);
}
.buddy-callback .field { margin-bottom: var(--s3); }
.buddy-callback .field:last-of-type { margin-bottom: var(--s3); }
.buddy-callback label { display: block; font-size: var(--t-sm); font-weight: 500; color: var(--g-navy); margin-bottom: .25rem; }
.buddy-callback .textarea { min-height: 64px; }
.buddy-callback .btn { width: 100%; }

/* ============ phone: the panel takes the screen ============
 Matches the 760px breakpoint components.css already uses for the action bar,
 so the launcher and the panel never argue about who owns the bottom edge. */
@media (max-width: 760px) {
  .buddy-panel {
    inset: 0;
    width: 100%;
    max-width: none;
    max-height: none;
    height: 100vh;
    height: 100dvh;
    border: 0;
    border-radius: 0;
    z-index: var(--z-modal);
  }
  .buddy-head { padding-top: calc(var(--s4) + env(safe-area-inset-top)); }
  .buddy-ask { padding-bottom: calc(var(--s3) + env(safe-area-inset-bottom)); }
  .buddy-bubble { max-width: 100%; }
}

/* a short viewport, which is also what 200 percent zoom looks like on a laptop */
@media (max-height: 620px) and (min-width: 761px) {
  .buddy-panel { max-height: calc(100dvh - 5rem); }
  .buddy-foot { display: none; }
}

@media print {
  .buddy-launch, .buddy-panel { display: none !important; }
}


/* ---- surface: web ---- */
/* grace-os · public website surface
 *
 * Design brief, so a later reader knows what the rules are protecting:
 *
 * The clinic's real, checkable differences are that it opens seven days a week
 * until 9pm on weekdays, and that it accepts every public program plus direct
 * billing. The old site buried both under stock photography and keyword filler.
 * Here they are the structure: a computed status band at the very top of every
 * page, and a programs rail that names each program as a plain fact.
 *
 * The one ornament is the orbit ring lifted from the logo mark. It appears as a
 * thin arc behind the hero and nowhere else. No carousels, no counters, no
 * numeral tiles, no badge soup.
 */

/* ================= hero ================= */
.hero{position:relative;overflow:hidden;background:var(--g-cloud);isolation:isolate}
.hero-inner{
  display:grid;gap:clamp(2rem,4vw,4rem);align-items:center;
  grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);
  padding-block:clamp(3rem,6vw,6rem);
}
.hero-copy{max-width:34rem;position:relative;z-index:2}
.hero h1{font-size:var(--t-hero);margin-bottom:var(--s4)}
.hero .lede{margin-bottom:var(--s5);font-size:clamp(1.0625rem,1rem + .4vw,1.25rem)}
.hero-actions{display:flex;flex-wrap:wrap;gap:.7rem;margin-bottom:var(--s5)}
.hero-assure{display:flex;flex-wrap:wrap;gap:.5rem 1.4rem;font-size:var(--t-sm);color:var(--g-slate)}
.hero-assure span{display:inline-flex;align-items:center;gap:.45em}
.hero-assure svg{width:1.05em;height:1.05em;color:var(--g-blue);flex:none}

.hero-media{position:relative;z-index:1}
.hero-media img{width:100%;border-radius:var(--r4);object-fit:cover;aspect-ratio:5/4;box-shadow:var(--sh3)}
/* the orbit, once */
.hero::after{
  content:"";position:absolute;right:-6%;top:8%;width:min(58vw,620px);aspect-ratio:1;
  border:1px solid var(--g-aqua);border-radius:50%;opacity:.3;
  transform:rotate(-14deg) scaleY(.36);pointer-events:none;z-index:0;
}
/* Hangs off the bottom left corner of the photograph rather than sitting on top
 of it. The hero image is a group of people; a card over their faces reads as
 an accident. Overlap the corner, not the subject. */
.hero-card{
  position:absolute;left:-3rem;bottom:-1rem;z-index:3;
  background:var(--g-white);border:1px solid var(--g-line);border-radius:var(--r3);
  box-shadow:var(--sh3);padding:var(--s4);max-width:17.5rem;
}
.hero-card p{margin:0;font-size:var(--t-sm);color:var(--g-slate)}
.hero-card b{display:block;font-family:var(--f-display);font-size:1.15rem;color:var(--g-navy);margin-bottom:.2rem}

@media (max-width:900px){
  .hero-inner{grid-template-columns:1fr;padding-block:2.25rem 2.75rem}
  .hero-media{order:-1}
  .hero-media img{aspect-ratio:16/10;border-radius:var(--r3)}
  .hero-card{position:static;margin-top:var(--s4);max-width:none;box-shadow:var(--sh1)}
  .hero::after{width:88vw;right:-30%;top:-4%}
}

/* page header for interior pages */
.page-head{background:var(--g-mist);padding-block:clamp(2.25rem,4vw,4rem);border-bottom:1px solid var(--g-line-soft)}
.page-head h1{margin-bottom:var(--s3)}
.page-head .lede{max-width:58ch}
.crumbs{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;padding:0;margin:0 0 var(--s4);font-size:var(--t-xs);color:var(--g-quiet)}
.crumbs li{margin:0;display:flex;align-items:center;gap:.4rem}
.crumbs li+li::before{content:"/";color:var(--g-line)}
.crumbs a{color:var(--g-slate);text-decoration:none}
.crumbs a:hover{color:var(--g-blue);text-decoration:underline}

/* ================= split section ================= */
.split{display:grid;gap:clamp(2rem,4vw,4.5rem);align-items:center;grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr))}
.split.flip>*:first-child{order:2}
.split-media img{width:100%;border-radius:var(--r3);object-fit:cover;aspect-ratio:4/3}
.split-media.tall img{aspect-ratio:3/4}
@media (max-width:820px){.split.flip>*:first-child{order:0}}

/* ================= service grid ================= */
.svc-grid{display:grid;gap:var(--s4);grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr))}
.svc{
  display:flex;flex-direction:column;text-decoration:none;color:inherit;
  background:var(--g-white);border:1px solid var(--g-line);border-radius:var(--r3);overflow:hidden;
  transition:border-color var(--dur2) var(--ease),box-shadow var(--dur2) var(--ease),transform var(--dur2) var(--ease);
}
.svc:hover{border-color:var(--g-aqua);box-shadow:var(--sh2);transform:translateY(-2px)}
.svc img{width:100%;aspect-ratio:16/10;object-fit:cover;background:var(--g-mist)}
.svc-body{padding:var(--s4) var(--s5) var(--s5);display:flex;flex-direction:column;flex:1}
.svc-body h3{font-size:var(--t-h4);font-family:var(--f-ui);margin-bottom:.35rem}
.svc-body p{font-size:var(--t-sm);color:var(--g-slate);margin-bottom:var(--s4)}
.svc-body .card-foot{margin-top:auto;padding-top:0}

/* ================= programs rail ================= */
.prog-rail{display:grid;gap:var(--s3);grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr))}
.prog{
  background:var(--g-white);border:1px solid var(--g-line);border-radius:var(--r3);
  padding:var(--s4);display:flex;flex-direction:column;gap:.4rem;
}
.prog-code{font:500 var(--t-xs)/1 var(--f-mono);letter-spacing:.1em;text-transform:uppercase;color:var(--g-blue)}
.prog b{font-size:var(--t-sm);color:var(--g-navy);font-weight:600;line-height:1.35}
.prog p{margin:0;font-size:var(--t-xs);color:var(--g-slate);line-height:1.55}

/* ================= steps ================= */
.steps{display:grid;gap:var(--s5);grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));counter-reset:none}
.step{position:relative;padding-left:var(--s6)}
.step::before{
  content:"";position:absolute;left:0;top:.35rem;width:14px;height:14px;border-radius:50%;
  background:var(--g-white);border:2px solid var(--g-aqua);
}
.step::after{content:"";position:absolute;left:6px;top:1.4rem;bottom:-.5rem;width:2px;background:var(--g-line-soft)}
.step:last-child::after{display:none}
.step h4{margin-bottom:.25rem}
.step p{font-size:var(--t-sm);color:var(--g-slate);margin:0}
@media (min-width:760px){.steps .step::after{display:none}}

/* ================= facts strip ================= */
.facts{display:grid;gap:var(--s5);grid-template-columns:repeat(auto-fit,minmax(min(100%,190px),1fr))}
.fact{border-left:2px solid var(--g-aqua);padding-left:var(--s4)}
.fact b{display:block;font-family:var(--f-display);font-size:clamp(1.25rem,1rem + 1vw,1.6rem);color:var(--g-navy);line-height:1.2;margin-bottom:.25rem}
.fact span{font-size:var(--t-sm);color:var(--g-slate)}

/* ================= emergency band ================= */
.emg{background:var(--g-warn-bg);border-block:1px solid var(--g-warn-line)}
.emg-inner{display:grid;gap:var(--s5);grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));align-items:center;padding-block:var(--s6)}
.emg h2{color:var(--g-warn-ink);font-size:var(--t-h3)}
.emg p{color:var(--g-warn-ink);margin-bottom:var(--s4)}
.emg .btn-urgent{align-self:start}

/* ================= booking flow ================= */
.book-layout{display:grid;gap:clamp(1.5rem,3vw,3rem);grid-template-columns:minmax(0,1.35fr) minmax(0,.65fr);align-items:start}
@media (max-width:940px){.book-layout{grid-template-columns:1fr}}
.book-steps{display:flex;gap:.35rem;flex-wrap:wrap;margin-bottom:var(--s5);padding:0;list-style:none}
.book-steps li{
  display:flex;align-items:center;gap:.45rem;padding:.35rem .8rem;border-radius:var(--r-pill);
  background:var(--g-cloud);border:1px solid var(--g-line);font-size:var(--t-xs);color:var(--g-slate);
}
.book-steps li[aria-current="step"]{background:var(--g-ground-strong);border-color:var(--g-ground-strong);color:var(--g-on-ground);font-weight:500}
.book-steps li[data-done="true"]{background:var(--g-ok-bg);border-color:var(--g-ok-line);color:var(--g-ok)}

.type-grid{display:grid;gap:.6rem;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr))}
.type-opt{
  display:flex;gap:.8rem;align-items:flex-start;padding:var(--s4);cursor:pointer;
  background:var(--g-white);border:1px solid var(--g-line);border-radius:var(--r3);
  transition:border-color var(--dur1) var(--ease),box-shadow var(--dur1) var(--ease);
}
.type-opt:hover{border-color:var(--g-blue)}
.type-opt input{margin-top:.25rem;width:1.15rem;height:1.15rem;flex:none;accent-color:var(--g-blue)}
.type-opt:has(input:checked){border-color:var(--g-blue);box-shadow:var(--ring)}
.type-opt b{display:block;font-size:var(--t-base);color:var(--g-navy);font-weight:600;margin-bottom:.15rem}
.type-opt span{font-size:var(--t-sm);color:var(--g-slate);display:block}
.type-opt .mono{color:var(--g-quiet);margin-top:.3rem;display:block}

.day-strip{display:flex;gap:.4rem;overflow-x:auto;padding-bottom:.5rem;scroll-snap-type:x mandatory}
.day-btn{
  flex:none;scroll-snap-align:start;min-width:74px;min-height:var(--tap);padding:.5rem .6rem;
  background:var(--g-white);border:1px solid var(--g-line);border-radius:var(--r2);cursor:pointer;
  display:flex;flex-direction:column;align-items:center;gap:.1rem;font-family:var(--f-ui);
}
.day-btn small{font-size:var(--t-xs);color:var(--g-quiet);text-transform:uppercase;letter-spacing:.06em}
.day-btn b{font-size:1.05rem;color:var(--g-navy)}
.day-btn[aria-pressed="true"]{background:var(--g-ground-strong);border-color:var(--g-ground-strong)}
.day-btn[aria-pressed="true"] b,.day-btn[aria-pressed="true"] small{color:var(--g-white)}
.day-btn[disabled]{opacity:.4;cursor:not-allowed}

.slot-grid{display:grid;gap:.5rem;grid-template-columns:repeat(auto-fill,minmax(104px,1fr))}
.slot{
  min-height:var(--tap);padding:.55rem .4rem;border-radius:var(--r2);cursor:pointer;
  background:var(--g-white);border:1px solid var(--g-line);
  font:500 var(--t-sm)/1.2 var(--f-mono);color:var(--g-navy);text-align:center;
}
.slot:hover{border-color:var(--g-blue);background:var(--g-mist)}
.slot[aria-pressed="true"]{background:var(--g-blue);border-color:var(--g-blue);color:var(--g-white)}
.slot[data-reserve="true"]{border-color:var(--g-warn);color:var(--g-warn)}

.summary-card{position:sticky;top:calc(var(--header-h,68px) + 1rem)}
.summary-row{display:flex;justify-content:space-between;gap:var(--s4);padding:.55rem 0;border-bottom:1px solid var(--g-line-soft);font-size:var(--t-sm)}
.summary-row:last-of-type{border-bottom:0}
.summary-row dt{color:var(--g-slate);margin:0}
.summary-row dd{margin:0;font-weight:500;color:var(--g-navy);text-align:right}

/* ================= faq ================= */
.faq-filters{margin-bottom:var(--s5)}
.faq-list .acc[hidden]{display:none}

/* ================= prose ================= */
.prose{max-width:72ch}
.prose h2{margin-top:var(--s7)}
.prose h2:first-child{margin-top:0}
.prose h3{margin-top:var(--s6)}
/* Default markers, in the text colour. A recoloured bullet is decoration that
 carries no information, and a page of aqua dots reads as a template. */
.prose ul li::marker{color:var(--g-slate)}
.prose>ul,.prose>ol{max-width:66ch}

/* ================= map ================= */
.map-shell{position:relative;border:1px solid var(--g-line);border-radius:var(--r3);overflow:hidden;background:var(--g-mist);aspect-ratio:16/10}
.map-shell iframe{width:100%;height:100%;border:0;display:block}
.map-consent{position:absolute;inset:0;display:grid;place-items:center;text-align:center;padding:var(--s5);background:var(--g-mist)}
.map-consent p{max-width:42ch;font-size:var(--t-sm);color:var(--g-slate)}

/* ================= misc ================= */
.pill-row{display:flex;flex-wrap:wrap;gap:.4rem}
.pill{display:inline-flex;align-items:center;padding:.3rem .75rem;border-radius:var(--r-pill);background:var(--g-mist);color:var(--g-blue);font-size:var(--t-xs);font-weight:500}
.rule{height:1px;background:var(--g-line);margin-block:var(--s6)}
.two-col{columns:2;column-gap:var(--s6)}
@media (max-width:700px){.two-col{columns:1}}
