@import url('/assets/fonts/fonts.css');

/* ============================================================================
   Dental Art Clinic — "quiet craft"

   Direction: an editorial clinic monograph. Warm paper ground rather than
   stark white, deep teal for authority, gold used sparingly as a scalpel —
   hairlines, the arch motif, one accent per view. The recurring shape is the
   tooth ARCH taken from the practice's own logo mark: rounded crown, squared
   base. It frames the hero photo, caps the section rules and rounds the cards.

   Colour decisions worth recording:
   - Gold #d0b163 is the brand mark but only ~1.9:1 on paper, so it is never
     used for text. Gold TEXT is #8A6A2F (5.2:1). Gold as a FILL only carries
     deep-teal text.
   - The primary button is teal-on-white (9:1) rather than the source site's
     white-on-gold (2.0:1, fails AA).
   ========================================================================= */

/* ----------------------------------------------------------------- tokens */
:root {
  --teal:        #1E5169;
  --teal-deep:   #143B4E;
  --teal-soft:   #7EBEC5;
  --teal-tint:   #EAF3F5;
  --gold:        #D0B163;
  --gold-text:   #8A6A2F;   /* accessible gold for type on paper */
  --gold-deep:   #B8974C;

  --paper:       #FBF9F5;
  --paper-warm:  #F4F0E8;
  --card:        #FFFFFF;
  --ink:         #22333C;
  --ink-soft:    #55707C;
  --rule:        #E4DED2;

  --measure: 68ch;
  --radius: 14px;
  --arch: 46% 46% var(--radius) var(--radius) / 34% 34% var(--radius) var(--radius);

  --shadow-sm: 0 1px 2px rgba(30,81,105,.05), 0 2px 8px rgba(30,81,105,.04);
  --shadow-md: 0 2px 4px rgba(30,81,105,.05), 0 12px 28px -8px rgba(30,81,105,.14);
  --shadow-lg: 0 30px 60px -22px rgba(30,81,105,.30);

  --step: clamp(3.5rem, 2.2rem + 5vw, 6.5rem);   /* section rhythm */
  --gutter: clamp(1.25rem, 4vw, 2.5rem);

  --ease: cubic-bezier(.22,.61,.36,1);
}

/* ------------------------------------------------------------------ reset */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Karla', ui-sans-serif, system-ui, sans-serif;
  font-size: 1.0625rem;
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Paper grain — atmosphere without an image request. */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  opacity: .5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 .42 0 0 0 0 .36 0 0 0 0 .24 0 0 0 .055 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
body > * { position: relative; z-index: 1; }

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

h1, h2, h3, h4 {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  color: var(--teal);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -.015em;
  margin: 0 0 .6em;
  font-variation-settings: 'opsz' 90, 'SOFT' 20;
}
h1 { font-size: clamp(2.35rem, 1.55rem + 3.4vw, 4.1rem); line-height: 1.04; letter-spacing: -.028em; }
h2 { font-size: clamp(1.7rem, 1.28rem + 1.7vw, 2.55rem); }
h3 { font-size: clamp(1.15rem, 1.05rem + .45vw, 1.4rem); font-weight: 600; letter-spacing: -.008em; }
p  { margin: 0 0 1.15em; max-width: var(--measure); }
ul, ol { max-width: var(--measure); padding-left: 1.15em; margin: 0 0 1.3em; }
li { margin-bottom: .5em; }

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

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

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--teal); color: #fff; padding: .8rem 1.2rem;
  border-radius: 0 0 var(--radius) 0; font-weight: 600;
}
.skip-link:focus { left: 0; }

.container {
  width: min(1200px, 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---------------------------------------------------------------- topbar */
.topbar {
  background: var(--teal-deep);
  color: #E7F0F2;
  font-size: .855rem;
  letter-spacing: .01em;
}
.topbar-inner { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 42px; }
.topbar-info { display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap; }
.tb-item { display: inline-flex; align-items: center; gap: .45rem; color: #E7F0F2; text-decoration: none; }
.tb-item:hover { color: var(--gold); }
/* linkify_contacts() wraps visible phones/emails in a nested <a>, which would
   otherwise pick up the global teal link colour and go near-invisible on the
   dark topbar. Same in the footer. */
.topbar a, .topbar a:hover { color: inherit; text-decoration: none; }
.tb-item svg { opacity: .72; }
.topbar-social { display: flex; align-items: center; gap: .5rem; }
.tb-social { color: #E7F0F2; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; transition: background .2s var(--ease), color .2s var(--ease); }
.tb-social:hover { background: rgba(208,177,99,.18); color: var(--gold); }
@media (max-width: 760px) { .tb-hide-sm { display: none; } }

/* ---------------------------------------------------------------- header */
.site-header {
  position: sticky; top: 0; z-index: 200;
  background: rgba(251,249,245,.94);
  backdrop-filter: saturate(150%) blur(10px);
  border-bottom: 1px solid var(--rule);
}
.header-inner { display: flex; align-items: center; gap: 1.5rem; min-height: 78px; }
.brand { flex: 0 0 auto; display: flex; align-items: center; }
.brand-logo { height: 46px; width: auto; }

.main-nav { margin-left: auto; display: flex; align-items: center; gap: .35rem; }
.main-nav > a,
.main-nav > .has-dropdown > a,
.services-toggle {
  position: relative;
  font-size: .93rem; font-weight: 600; letter-spacing: .005em;
  color: var(--ink); text-decoration: none;
  padding: .55rem .7rem; border-radius: 8px;
  background: none; border: 0; cursor: pointer;
  font-family: inherit;
  display: inline-flex; align-items: center; gap: .3rem;
}
/* Gold underline draws in from the left — the one nav flourish. */
.main-nav > a::after,
.services-toggle::after {
  content: ""; position: absolute; left: .7rem; right: .7rem; bottom: .3rem;
  height: 1.5px; background: var(--gold);
  transform: scaleX(0); transform-origin: left;
  transition: transform .28s var(--ease);
}
.main-nav > a:hover::after,
.main-nav > a.active::after,
.has-dropdown:hover .services-toggle::after { transform: scaleX(1); }
.main-nav > a.active { color: var(--teal); }

/* The phone lives in the topbar (all breakpoints) and the mobile call bar; it was
   a third contact repeat in the header and crowded the Book Now button. */
.chev { transition: transform .25s var(--ease); }
/* Scoped to the TOGGLE's own chevron with `>`. Unscoped, this also caught the `›`
   on every .dropdown-item--parent inside the open panel and spun those 180° — so
   the submenu arrows pointed LEFT, away from the panel they open. */
.has-dropdown:hover > .services-toggle .chev { transform: rotate(180deg); }
.dropdown-item--parent .chev { color: var(--ink-soft); font-size: 1.15em; line-height: 1; }
.dropdown-item--parent:hover .chev { color: var(--teal); transform: translateX(2px); }

/* -------------------------------------------------- cascading services menu */
.has-dropdown { position: relative; }
.dropdown {
  position: absolute; top: calc(100% + 12px); left: 50%; translate: -50% 0;
  min-width: 292px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: .5rem;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .22s var(--ease), transform .22s var(--ease), visibility .22s;
}
/* MANDATORY hover bridge (audit sub-check 21). The panel sits 12px below its
   toggle; without a transparent bridge across that dead gap the menu closes the
   instant the cursor leaves the button, forcing a click. */
.dropdown::before {
  content: ""; position: absolute; top: -14px; left: 0; right: 0; height: 14px;
}
.has-dropdown:hover .dropdown,
.has-dropdown:focus-within .dropdown {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.dropdown-item {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  padding: .62rem .8rem; border-radius: 9px;
  color: var(--ink); text-decoration: none; font-weight: 600; font-size: .92rem;
}
.dropdown-item:hover, .dropdown-item:focus-visible { background: var(--teal-tint); color: var(--teal); }
.dropdown-item--parent { position: relative; }

.has-submenu { position: relative; }
.submenu {
  position: absolute; top: -.5rem; left: calc(100% - 4px);
  min-width: 268px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: .5rem;
  opacity: 0; visibility: hidden; transform: translateX(-6px);
  transition: opacity .2s var(--ease), transform .2s var(--ease), visibility .2s;
}
.has-submenu:hover > .submenu,
.has-submenu:focus-within > .submenu { opacity: 1; visibility: visible; transform: translateX(0); }
/* Submenu children are bare anchors, not .dropdown-item */
.submenu a {
  display: block; padding: .55rem .8rem; border-radius: 9px;
  color: var(--ink); text-decoration: none; font-weight: 600; font-size: .9rem;
}
.submenu a:hover, .submenu a:focus-visible { background: var(--teal-tint); color: var(--teal); }
.submenu-overview {
  display: block; padding: .55rem .8rem; margin-bottom: .25rem;
  font-size: .74rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--gold-text); text-decoration: none;
  border-bottom: 1px solid var(--rule); border-radius: 0;
}
.submenu a.submenu-overview:hover { color: var(--teal); background: transparent; }

.menu-toggle { display: none; }

/* ------------------------------------------------------------------ buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: inherit; font-weight: 700; font-size: .95rem; letter-spacing: .01em;
  padding: .82rem 1.5rem; border-radius: 10px;
  text-decoration: none; cursor: pointer; border: 1.5px solid transparent;
  min-height: 46px;
  transition: transform .2s var(--ease), box-shadow .2s var(--ease),
              background-color .2s var(--ease), color .2s var(--ease);
}
.btn--primary { background: var(--teal); color: #fff; box-shadow: var(--shadow-sm); }
.btn--primary:hover { background: var(--teal-deep); color: #fff; transform: translateY(-1px); box-shadow: var(--shadow-md); }
.btn--ghost { background: transparent; color: var(--teal); border-color: var(--gold); }
.btn--ghost:hover { background: var(--gold); color: var(--teal-deep); }
.btn--lg { padding: .95rem 1.9rem; font-size: 1rem; min-height: 52px; }
.btn--block { width: 100%; }
/* The header's only filled element. Every other nav item is unfilled ink text on
   paper, so a solid teal pill reads unmistakably as THE action.
   Was gold #D0B163 with #143B4E letters: 5.75:1 — technically AA, but a mid-gold
   fill under small bold type reads muddy, and its value sits close enough to the
   paper ground that the button didn't separate from the menu. Teal on white is
   8.5:1 and the fill/ground value gap is large. The gold hairline keeps the brand
   accent on the element without carrying any text. */
.btn--nav {
  background: var(--teal); color: #fff;
  border: 1.5px solid var(--gold);
  padding: .68rem 1.35rem; min-height: 42px;
  font-size: .92rem; letter-spacing: .02em;
  box-shadow: 0 1px 2px rgba(20,59,78,.16);
}
.btn--nav:hover { background: var(--teal-deep); color: #fff; border-color: var(--gold); transform: translateY(-1px); }

/* --------------------------------------------------------------------- hero */
.hero {
  position: relative;
  padding: clamp(3rem, 2rem + 4vw, 5.5rem) 0 clamp(3.5rem, 2rem + 5vw, 6rem);
  background:
    radial-gradient(1100px 520px at 78% -8%, var(--teal-tint) 0%, transparent 62%),
    linear-gradient(180deg, var(--paper) 0%, var(--paper) 60%, var(--paper-warm) 100%);
  overflow: hidden;
}
/* Single column by default; the two-column split only applies when there is
   actually a photo to put in the second column. Otherwise an imageless hero
   (blog posts, team, contact) reserved half the row for nothing. */
.hero__grid {
  display: grid; grid-template-columns: 1fr;
  gap: clamp(2rem, 1rem + 4vw, 5rem); align-items: center;
}
.hero__grid:has(.hero__visual) { grid-template-columns: 1.08fr .92fr; }
.hero__content { max-width: 40rem; }
.eyebrow {
  display: block;
  font-size: .76rem; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--gold-text); margin-bottom: 1rem;
  text-align: inherit;                 /* explicit: never inherit-by-accident (sub-check 27a) */
}
.eyebrow::after {
  content: ""; display: block; width: 34px; height: 2px;
  background: var(--gold); margin-top: .6rem;
}
.hero__h1--brand { display: block; }
.hero__brand {
  display: block;
  font-size: clamp(2.6rem, 1.6rem + 4.2vw, 4.6rem);
  font-variation-settings: 'opsz' 144, 'SOFT' 40, 'WONK' 1;
  letter-spacing: -.035em;
}
.hero__h1-rest {
  display: block;
  font-size: clamp(1.28rem, 1.05rem + 1vw, 1.85rem);
  font-weight: 400; color: var(--ink-soft); letter-spacing: -.01em;
  margin-top: .35rem; line-height: 1.3;
}
.hero__sub { font-size: 1.115rem; color: var(--ink-soft); max-width: 34rem; margin-bottom: 1.9rem; }
.hero__actions { display: flex; flex-wrap: wrap; gap: .85rem; align-items: center; }
.hero__phone { font-weight: 700; color: var(--teal); text-decoration: none; padding: .5rem .2rem; }
.hero__phone:hover { color: var(--gold-text); }

.hero__visual { position: relative; justify-self: end; width: 100%; max-width: 460px; }
/* The arch — crown rounded, base squared. Lifted from the logo's tooth mark. */
.hero__photo {
  position: relative; overflow: hidden;
  border-radius: var(--arch);
  box-shadow: var(--shadow-lg);
  aspect-ratio: 4 / 5;
  background: var(--teal-tint);
}
.hero__photo img { width: 100%; height: 100%; object-fit: cover; }
.hero__photo::after {          /* thin gold inner keyline */
  content: ""; position: absolute; inset: 0;
  border: 1px solid rgba(208,177,99,.55);
  border-radius: inherit; pointer-events: none;
}
.hero__blob { position: absolute; border-radius: 50%; pointer-events: none; z-index: -1; }
.hero__blob--1 { width: 300px; height: 300px; right: -70px; top: -60px; background: radial-gradient(circle, rgba(208,177,99,.20), transparent 68%); }
.hero__blob--2 { width: 340px; height: 340px; left: -110px; bottom: -90px; background: radial-gradient(circle, rgba(126,190,197,.26), transparent 68%); }

/* Staggered page-load reveal — the one orchestrated motion moment. */
@media (prefers-reduced-motion: no-preference) {
  .hero__content > *, .hero__visual { animation: rise .78s var(--ease) both; }
  .hero__content > *:nth-child(1) { animation-delay: .04s; }
  .hero__content > *:nth-child(2) { animation-delay: .12s; }
  .hero__content > *:nth-child(3) { animation-delay: .20s; }
  .hero__content > *:nth-child(4) { animation-delay: .28s; }
  .hero__visual { animation-delay: .16s; }
}
@keyframes rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

/* ------------------------------------------------------------- page banner */
/* Landscape article image, in the shape it was actually composed for. Sits
   between the hero and the body, full container width. */
.page-banner { padding-block: 0 0; margin-top: calc(var(--step) * -.45); }
.page-banner__frame {
  margin: 0; border-radius: var(--radius); overflow: hidden;
  aspect-ratio: 2.4 / 1; background: var(--teal-tint);
  border: 1px solid var(--rule); box-shadow: var(--shadow-md);
  position: relative;
}
.page-banner__frame img { width: 100%; height: 100%; object-fit: cover; }
.page-banner__frame::after {          /* same gold keyline as the hero arch */
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  border: 1px solid rgba(208,177,99,.42); pointer-events: none;
}
@media (max-width: 720px) { .page-banner__frame { aspect-ratio: 16 / 9; } }

/* ----------------------------------------------------------------- sections */
.section { padding-block: var(--step); }
.section--alt { background: var(--paper-warm); border-block: 1px solid var(--rule); }
.section--tight { padding-block: calc(var(--step) * .58); }
.sec-head { max-width: var(--measure); margin-bottom: 2.6rem; }
.section > .container > h2 { max-width: 22ch; }

/* Prose rhythm inside re-emitted verbatim content */
.page-main > h2 { margin-top: 2.4rem; }
.page-main > h2:first-child { margin-top: 0; }
.page-main > h3 { margin-top: 1.9rem; color: var(--ink); }
.page-main > h2::before {
  content: ""; display: block; width: 30px; height: 2px;
  background: var(--gold); margin-bottom: .85rem;
}
.lede { font-size: 1.16rem; color: var(--ink-soft); }

/* A heading with no body of its own, sitting directly above other headings, is a
   GROUP LABEL in the source ("Overnight Care" over the care sub-steps). Rendered
   at full H2 weight it reads as a broken, empty section. Styled as a label it
   reads as what it is. Unfilled headings with nothing under them at all are
   dropped upstream in digest.py; these are the ones that legitimately head a set. */
.page-main > h2:has(+ h2),
.page-main > h2:has(+ h3),
.page-main > h3:has(+ h3) {
  font-family: 'Karla', sans-serif;
  font-size: .78rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--gold-text); margin-bottom: 1.2rem;
}
.page-main > h2:has(+ h2)::before,
.page-main > h2:has(+ h3)::before { display: none; }

.two-col-media {
  margin: 0 0 2rem; border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--shadow-md); aspect-ratio: 4 / 3; background: var(--teal-tint);
}
.two-col-media img { width: 100%; height: 100%; object-fit: cover; }
/* Authored after .two-col-media so the modifier wins on source order at equal
   specificity (Hardening Rule 7). */
.two-col-media--wide { aspect-ratio: 2.4 / 1; }

/* -------------------------------------------------- main + sidebar template */
/* ONE layout for every repeated page type (sub-check 27b) — instances cannot
   drift in width or alignment by how much copy each happens to have. */
.page-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: clamp(2rem, 1rem + 3.5vw, 4.5rem);
  align-items: start;
}
.page-main { min-width: 0; }
.page-aside { position: sticky; top: 104px; display: grid; gap: 1.1rem; }
.aside-card {
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.4rem 1.5rem;
  box-shadow: var(--shadow-sm);
}
.aside-card--cta { background: var(--teal); border-color: var(--teal); color: #DCEAEE; }
.aside-card--cta .aside-h, .aside-card--cta .aside-phone a { color: #fff; }
.aside-card--cta p { color: #C6DCE3; }
.aside-card--cta .btn--primary { background: var(--gold); color: var(--teal-deep); }
.aside-card--cta .btn--primary:hover { background: #E0C57F; color: var(--teal-deep); }
.aside-h {
  font-size: .78rem; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  font-family: 'Karla', sans-serif; color: var(--gold-text); margin-bottom: .9rem;
}
.aside-phone { font-family: 'Fraunces', serif; font-size: 1.5rem; margin: .2rem 0 1rem; }
.aside-phone a { text-decoration: none; font-weight: 600; }
.aside-links { list-style: none; padding: 0; margin: 0; }
.aside-links li + li { border-top: 1px solid var(--rule); }
.aside-links a { display: block; padding: .55rem 0; font-size: .93rem; font-weight: 600; text-decoration: none; }
.aside-links a:hover { color: var(--gold-text); padding-left: .3rem; transition: padding .2s var(--ease); }
.aside-links a[aria-current="page"] { color: var(--gold-text); }

.hours { font-size: .92rem; }
.hours-row { display: flex; justify-content: space-between; gap: 1rem; padding: .4rem 0; }
.hours-row + .hours-row { border-top: 1px dashed var(--rule); }
.hours-row span:first-child { color: var(--ink-soft); }
.hours-row span:last-child { font-weight: 600; text-align: right; }
.hours--wide { max-width: 30rem; margin-bottom: 2rem; }

/* -------------------------------------------------------------------- cards */
.svc-grid, .subsvc-grid {
  display: grid; gap: 1.1rem;
  grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
  align-items: start;                  /* never stretch uneven cards (Rule 8) */
}
/* Nine services divide evenly into three columns; auto-fit would leave a lone
   orphan card on a 4-up row at desktop width. */
@media (min-width: 1080px) { .svc-grid { grid-template-columns: repeat(3, 1fr); } }
.svc-card, .subsvc-card, .post-card {
  position: relative; display: block;
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.6rem 1.5rem 1.4rem;
  text-decoration: none; color: var(--ink);
  box-shadow: var(--shadow-sm);
  transition: transform .24s var(--ease), box-shadow .24s var(--ease), border-color .24s var(--ease);
  overflow: hidden;
}
.svc-card::before, .subsvc-card::before, .post-card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: var(--gold); transform: scaleX(0); transform-origin: left;
  transition: transform .32s var(--ease);
}
.svc-card:hover, .subsvc-card:hover, .post-card:hover {
  transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: #D8CFBC;
}
.svc-card:hover::before, .subsvc-card:hover::before, .post-card:hover::before { transform: scaleX(1); }
.svc-card h3, .subsvc-card h3, .post-card h2 {
  font-size: 1.16rem; margin-bottom: .5rem; color: var(--teal);
}
.svc-card p, .subsvc-card p, .post-card p {
  font-size: .935rem; color: var(--ink-soft); margin-bottom: 1rem; line-height: 1.62;
}
.svc-cta { font-size: .84rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--gold-text); }
.svc-card:hover .svc-cta span, .subsvc-card:hover .svc-cta span, .post-card:hover .svc-cta span {
  display: inline-block; transform: translateX(4px); transition: transform .24s var(--ease);
}
.post-grid { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); align-items: start; }
.post-card--text h2 { font-size: 1.1rem; line-height: 1.32; }

/* --------------------------------------------------------------------- team */
.team-grid {
  display: grid; gap: 1.6rem;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
  align-items: start;
}
.team-card {
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.5rem; box-shadow: var(--shadow-sm);
}
.team-card__photo {
  width: 100%; aspect-ratio: 4/5; object-fit: cover;
  border-radius: var(--arch); margin-bottom: 1.2rem;
}
.team-card__monogram {
  width: 100%; aspect-ratio: 4/5; border-radius: var(--arch); margin-bottom: 1.2rem;
  display: grid; place-items: center;
  background: linear-gradient(155deg, var(--teal-tint), var(--paper-warm));
  border: 1px solid var(--rule);
  font-family: 'Fraunces', serif; font-size: 3rem; font-weight: 600;
  color: var(--teal); letter-spacing: .04em;
}
/* Roster rows (/meet-the-team/). Photo left, bio right, one per row — the bio
   text wraps to the full measure instead of a ~270px column, so a three-paragraph
   bio reads as three short paragraphs rather than a tall stack. */
.team-roster { display: grid; gap: 1.4rem; }
.team-card--row {
  display: grid; grid-template-columns: 210px minmax(0, 1fr);
  gap: clamp(1.5rem, 1rem + 2vw, 2.6rem);
  align-items: start; padding: 1.7rem 1.9rem;
}
.team-card--row .team-card__photo,
.team-card--row .team-card__monogram { margin-bottom: 0; }
.team-card--row .team-card__body > :last-child { margin-bottom: 0; }
.team-card--row .team-card p { max-width: 74ch; }
@media (max-width: 720px) {
  .team-card--row { grid-template-columns: 1fr; gap: 1.2rem; padding: 1.4rem; }
  .team-card--row .team-card__media { max-width: 200px; }
}

.team-card__name { font-size: 1.3rem; margin-bottom: .15rem; }
.team-card__role {
  font-size: .78rem; font-weight: 700; letter-spacing: .11em; text-transform: uppercase;
  color: var(--gold-text); margin-bottom: 1rem;
}
.team-card p { font-size: .94rem; color: var(--ink-soft); line-height: 1.66; }
.team-grid--teaser { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); max-width: 640px; }
.team-card--teaser { text-align: center; }
.team-card--teaser .team-card__role { color: var(--gold-text); }
.center-cta { text-align: center; margin-top: 2rem; max-width: none; }

/* ------------------------------------------------------------- associations */
.assoc-strip { padding-block: calc(var(--step) * .52); border-top: 1px solid var(--rule); }
.assoc-strip__grid {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: clamp(2rem, 1rem + 4vw, 5rem);
}
.assoc-card__logo { display: block; line-height: 0; }
.assoc-strip .container > h2.assoc-strip__h {
  font-size: .78rem; font-weight: 700; letter-spacing: .15em; text-transform: uppercase;
  font-family: 'Karla', sans-serif; color: var(--gold-text);
  text-align: center; margin-bottom: 2.2rem;
  /* `.section > .container > h2 { max-width: 22ch }` is (0,2,1); a bare
     `.assoc-strip__h` at (0,1,0) lost to it, so the narrow box kept the centred
     label reading left-aligned. This selector outranks it (Rule 7). */
  max-width: none;
}
.assoc-card {
  display: grid; place-items: center;
  opacity: .78; transition: opacity .3s var(--ease), transform .3s var(--ease);
}
a.assoc-card:hover { opacity: 1; transform: translateY(-2px); }
/* Per-logo tuning (sub-check 16d). These four logos run 0.98 -> 3.09 in aspect
   ratio; a single object-fit rule renders the ultrawide RCDSO mark at half the
   visual weight of the square implant badge. Each modifier is tuned so all four
   read as roughly equal AREA, not equal height. */
/* width:auto is load-bearing. The <img> tags carry explicit width attributes for
   CLS reservation, so max-height alone clamps the height while the width stays at
   its natural value — squashing the mark. With width:auto the intrinsic ratio
   drives the width and max-height does the sizing. */
.assoc-card img { width: auto; height: auto; max-width: 100%; }
.assoc-card--oda     img { max-height: 54px; }
.assoc-card--cda     img { max-height: 60px; }
.assoc-card--rcdso   img { max-height: 46px; }
.assoc-card--implant img { max-height: 72px; }
.assoc-card__logo { width: auto; height: auto; }

/* ----------------------------------------------------------------- CTA band */
.cta-section { padding-block: 0 var(--step); }     /* breathing room before the footer */
.cta-band {
  background: linear-gradient(135deg, var(--teal) 0%, var(--teal-deep) 100%);
  color: #fff;
  border-radius: calc(var(--radius) + 6px);
  padding: clamp(2.2rem, 1.4rem + 3vw, 3.6rem) clamp(1.6rem, 1rem + 3vw, 3.4rem);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.cta-band-inner {
  display: grid; grid-template-columns: 1.35fr .9fr;
  gap: clamp(1.8rem, 1rem + 3vw, 3.5rem); align-items: center;
}
.cta-band h2 { color: #fff; margin-bottom: .5rem; max-width: 16ch; }
.cta-band p { color: #C6DCE3; max-width: 44ch; }
.cta-band__main p { margin-bottom: 1.6rem; }
/* linkify_contacts() nests an <a> in the body copy; without this it inherits the
   global teal link colour and disappears against the teal band. */
.cta-band a { color: var(--gold); text-decoration-color: rgba(208,177,99,.55); }
.cta-band a:hover { color: #E7D19A; }
.cta-band .btn--primary { background: var(--gold); color: var(--teal-deep); text-decoration: none; }
.cta-band .btn--primary:hover { background: #E0C57F; color: var(--teal-deep); }

.cta-band__urgent {
  border: 1px solid rgba(208,177,99,.42);
  background: rgba(208,177,99,.10);
  border-radius: var(--radius);
  padding: 1.3rem 1.4rem;
}
.cta-band__urgent-label {
  display: block; font-size: .74rem; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: var(--gold); margin-bottom: .45rem;
}
.cta-band__urgent-call {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: 'Fraunces', serif; font-size: 1.6rem; font-weight: 600;
  color: #fff !important; text-decoration: none; line-height: 1.15;
}
.cta-band__urgent-call:hover { color: var(--gold) !important; }
.cta-band__urgent-note { font-size: .88rem; color: #A8C4CD; margin: .5rem 0 0; max-width: none; }

@media (max-width: 900px) {
  .cta-band-inner { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Digestible-content treatments
   Applied only where a block's content genuinely has that shape. Styling reuses
   the site's own tokens and card geometry so treated blocks read as part of the
   design rather than a bolted-on component set.
   ========================================================================== */

/* --- feature / benefit cards ------------------------------------------- */
.dc-card-grid {
  display: grid; gap: 1.1rem; margin: 1.6rem 0 2.2rem;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  align-items: start;                    /* never stretch uneven cards (Rule 8) */
}
.dc-card {
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.3rem 1.4rem;
  box-shadow: var(--shadow-sm);
}
.dc-card > h3 { margin: 0 0 .5rem; font-size: 1.05rem; color: var(--teal); }
.dc-card__body > * { margin: 0; color: var(--ink-soft); font-size: .945rem; line-height: 1.66; max-width: none; }
.dc-card__body > * + * { margin-top: .7rem; }
.dc-card__body ul, .dc-card__body ol { padding-left: 1.1em; }
/* The article column is ~708px next to the 340px sidebar, which resolves this
   grid to exactly two tracks. An odd final card would then sit alone at half
   width with a hole beside it; letting it span reads as intentional. */
@media (min-width: 981px) {
  .page-main .dc-card-grid:not(.dc-card-grid--wide) > .dc-card:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }
}

/* Medium-length blurbs go to full-width rows: a 120-word body poured into a
   230px column becomes a tall stack, which is a vertical wall of text — the
   thing this whole treatment exists to avoid. */
.dc-card-grid--wide { grid-template-columns: 1fr; gap: 1rem; }
.dc-card-grid--wide .dc-card {
  display: grid; grid-template-columns: minmax(150px, 200px) minmax(0, 1fr);
  column-gap: 1.9rem; align-items: start;
}
.dc-card-grid--wide .dc-card > h3 { margin: 0; }
@media (max-width: 720px) {
  .dc-card-grid--wide .dc-card { grid-template-columns: 1fr; row-gap: .5rem; }
}

/* Where the source numbered its own items, the number becomes presentational so
   the heading text stays clean ("1. 1. Toothaches" was the alternative). */
.dc-card-grid--numbered { counter-reset: dc-n; }
.dc-card-grid--numbered .dc-card { counter-increment: dc-n; position: relative; padding-top: 1.35rem; }
.dc-card-grid--numbered .dc-card > h3 { padding-left: 2.35rem; min-height: 1.75rem; }
.dc-card-grid--numbered .dc-card > h3::before {
  content: counter(dc-n); position: absolute; left: 1.4rem; top: 1.3rem;
  display: grid; place-items: center; width: 1.75rem; height: 1.75rem;
  border-radius: 50%; background: var(--gold); color: var(--teal-deep);
  font-family: 'Karla', sans-serif; font-size: .82rem; font-weight: 700; line-height: 1;
}
.dc-card-grid--numbered.dc-card-grid--wide .dc-card > h3 { padding-left: 2.35rem; }

/* --- numbered process steps -------------------------------------------- */
.dc-steps {
  list-style: none; counter-reset: dc-step; padding: 0;
  margin: 1.6rem 0 2.2rem; display: grid; gap: 1.15rem; max-width: none;
}
.dc-steps > li { counter-increment: dc-step; position: relative; padding-left: 3.6rem; margin: 0; }
.dc-steps > li::before {
  content: counter(dc-step); position: absolute; left: 0; top: -.15rem;
  width: 2.4rem; height: 2.4rem; border-radius: 50%;
  background: var(--teal); color: #fff; display: grid; place-items: center;
  font-family: 'Fraunces', serif; font-weight: 600; font-size: 1.02rem;
}
/* The connecting rule that makes a stack read as a sequence rather than a list. */
.dc-steps > li:not(:last-child)::after {
  content: ""; position: absolute; left: 1.19rem; top: 2.55rem; bottom: -1.15rem;
  width: 2px; background: linear-gradient(var(--gold), rgba(208,177,99,.15));
}
.dc-steps h3 { margin: .25rem 0 .35rem; font-size: 1.06rem; }
.dc-step__body > * { margin: 0; color: var(--ink-soft); font-size: .945rem; max-width: none; }
.dc-step__body > * + * { margin-top: .6rem; }

/* --- FAQ accordion ------------------------------------------------------ */
.dc-faq {
  margin: 1.5rem 0 2.2rem;
  border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow-sm); overflow: hidden;
}
.dc-faq details + details { border-top: 1px solid var(--rule); }
.dc-faq summary {
  display: flex; align-items: flex-start; gap: .8rem;
  padding: 1.05rem 1.35rem; cursor: pointer; list-style: none;
}
.dc-faq summary::-webkit-details-marker { display: none; }
.dc-faq summary h3 { margin: 0; font-size: 1.02rem; flex: 1 1 auto; }
.dc-faq summary::after {
  content: ""; flex: 0 0 auto; width: .62rem; height: .62rem; margin-top: .38rem;
  border-right: 2px solid var(--gold-text); border-bottom: 2px solid var(--gold-text);
  transform: rotate(45deg); transition: transform .25s var(--ease);
}
.dc-faq details[open] summary::after { transform: rotate(-135deg); }
.dc-faq summary:hover { background: var(--teal-tint); }
.dc-faq__body { padding: 0 1.35rem 1.2rem; }
.dc-faq__body > * { margin: 0; color: var(--ink-soft); font-size: .95rem; max-width: none; }
.dc-faq__body > * + * { margin-top: .7rem; }

/* --- checklist ---------------------------------------------------------- */
/* Reserved for verified all-positive lists. A tick reads "yes, this is good",
   so it must never sit beside an exclusion, a symptom or a warning. */
.dc-checklist { list-style: none; padding: 0; margin: 1rem 0 1.6rem; display: grid; gap: .75rem; }
.dc-checklist li { position: relative; padding-left: 2.1rem; margin: 0; }
.dc-checklist li::before {
  content: ""; position: absolute; left: 0; top: .3rem;
  width: 1.3rem; height: 1.3rem; border-radius: 50%; background: var(--teal);
}
.dc-checklist li::after {
  content: ""; position: absolute; left: .43rem; top: .62rem;
  width: .42rem; height: .22rem;
  border-left: 2px solid #fff; border-bottom: 2px solid #fff; transform: rotate(-45deg);
}

/* --- pros / cons comparison --------------------------------------------- */
.dc-pc-wrap { display: contents; }
.dc-pc { margin: 1.4rem 0 2rem; }
.dc-pc__label {
  font-family: 'Karla', sans-serif;
  font-family: 'Karla', sans-serif; font-size: .76rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; margin-bottom: .9rem;
}
.dc-pc--pos .dc-pc__label { color: var(--success, #1f7a5a); }
.dc-pc--neg .dc-pc__label { color: #9a5b3f; }
.dc-pros, .dc-cons {
  list-style: none; padding: 0; margin: 0; max-width: none;
  display: grid; gap: .8rem; grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
  align-items: start;
}
.dc-pros > li, .dc-cons > li {
  position: relative; margin: 0; padding: 1rem 1.2rem 1rem 2.9rem;
  background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius);
}
.dc-pros > li { border-left: 3px solid #2f9070; }
.dc-cons > li { border-left: 3px solid #b8794f; }
.dc-pros > li::before, .dc-cons > li::before {
  content: ""; position: absolute; left: 1.05rem; top: 1.28rem;
  width: .72rem; height: .4rem;
}
.dc-pros > li::before { border-left: 2.2px solid #2f9070; border-bottom: 2.2px solid #2f9070; transform: rotate(-45deg); }
.dc-cons > li::before { border-bottom: 2.2px solid #b8794f; height: 0; top: 1.42rem; }
.dc-pros h3, .dc-cons h3 { font-size: 1rem; margin: 0 0 .3rem; }
.dc-pros li > div > *, .dc-cons li > div > * { margin: 0; font-size: .93rem; color: var(--ink-soft); max-width: none; }

/* ------------------------------------------------------------------ callout */
/* Kin to the pre-footer CTA band — same card geometry, same gold accent — but in
   a light key so a mid-page aside doesn't read as a second call to action. */
.callout-section { padding-block: calc(var(--step) * .42); }
.callout {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 1.4rem;
  align-items: start;
  background: linear-gradient(135deg, var(--teal-tint) 0%, var(--paper-warm) 100%);
  border: 1px solid rgba(208,177,99,.55);
  border-radius: calc(var(--radius) + 6px);
  padding: clamp(1.5rem, 1rem + 2vw, 2.4rem) clamp(1.4rem, 1rem + 2vw, 2.6rem);
  box-shadow: var(--shadow-sm);
}
.callout__icon {
  display: grid; place-items: center; width: 52px; height: 52px;
  border-radius: 50%; background: var(--card); color: var(--teal);
  border: 1px solid rgba(208,177,99,.55);
}
.callout h2 { font-size: clamp(1.25rem, 1.1rem + .7vw, 1.6rem); margin-bottom: .4rem; }
.callout p { color: var(--ink-soft); margin-bottom: 0; max-width: 66ch; }
@media (max-width: 620px) { .callout { grid-template-columns: 1fr; gap: 1rem; } }

/* ------------------------------------------------------------------ find us */
/* Map + NAP + hours + parking in one place, below the team. */
/* Directions prose folded in from the Step 11 "Visiting us in Cambridge" band,
   which used to stand on its own two screens above this map. */
.find-us__lede { max-width: 68ch; margin-bottom: clamp(1.4rem, 1rem + 1.5vw, 2.2rem); }
.find-us__lede p:last-child { margin-bottom: 0; }
.find-us {
  display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, .75fr);
  gap: clamp(1.5rem, 1rem + 2.5vw, 2.6rem); align-items: stretch;
}
.find-us__map {
  border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--rule); box-shadow: var(--shadow-md); min-height: 100%;
}
.find-us__map iframe { display: block; width: 100%; height: 100%; min-height: 460px; border: 0; }
.find-us__details { display: grid; gap: 1.1rem; align-content: start; }
.nap-card {
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.4rem 1.5rem; box-shadow: var(--shadow-sm);
}
.nap-card__h {
  font-size: .78rem; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  font-family: 'Karla', sans-serif; color: var(--gold-text); margin-bottom: .9rem;
}
.nap-list { list-style: none; padding: 0; margin: 0 0 1.1rem; font-size: .96rem; }
.nap-list li { display: flex; gap: .6rem; align-items: flex-start; padding: .45rem 0; }
.nap-list li + li { border-top: 1px dashed var(--rule); }
.nap-list svg { flex: 0 0 auto; margin-top: .38rem; color: var(--gold-text); }
.nap-list a { text-decoration: none; font-weight: 600; }
.find-us__parking { margin-top: clamp(1.8rem, 1rem + 2vw, 2.8rem); }
.find-us__parking h3 { color: var(--ink); margin-bottom: .7rem; }
/* .step-grid shares this geometry: a short ordered list where each item is one
   sentence, laid out as numbered cards across the full band instead of a bullet
   list hugging a 68ch measure. Used by the homepage "first visit" band. */
.parking-list, .step-grid { counter-reset: pk; list-style: none; padding: 0; max-width: none;
  display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(258px, 1fr)); }
.parking-list li, .step-grid li {
  counter-increment: pk; position: relative; margin: 0;
  background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 1.1rem 1.2rem 1.1rem 3.3rem; font-size: .94rem; color: var(--ink-soft);
}
/* Five items at the shared 258px minimum wrap 4+1, which reads as a mistake.
   A wider floor gives three columns and a 3+2 wrap. Parking has three items, so
   it lays out the same either way and is unaffected. */
.step-grid { grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }
.parking-list li::before, .step-grid li::before {
  content: counter(pk); position: absolute; left: 1.1rem; top: 1rem;
  display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  background: var(--gold); color: var(--teal-deep);
  font-family: 'Fraunces', serif; font-weight: 600; font-size: .88rem; line-height: 1;
}
@media (max-width: 900px) {
  .find-us { grid-template-columns: 1fr; }
  .find-us__map iframe { min-height: 340px; }
}

/* A text-only band. Prose runs to a 68ch measure, which left the homepage's
   generated narrative band hugging the left edge with an empty right half —
   every other band on that page is a two-col with a photo balancing it. Setting
   the paragraphs as two columns fills the width without inventing an image, and
   keeps the left alignment the rest of the page uses. Not CSS multi-column: that
   would break one paragraph across both columns, and these are two distinct
   thoughts that should each start at the top of a column. */
.band-narrative {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(310px, 1fr));
  gap: clamp(1.4rem, 1rem + 2vw, 2.8rem); align-items: start;
}
.band-narrative > p { max-width: 58ch; margin-bottom: 0; }
.band-narrative > p:first-child { font-size: 1.04rem; color: var(--ink); }

.two-col--solo { grid-template-columns: minmax(0, 1fr); }

/* -------------------------------------------------------------------- forms */
.ff-form { max-width: 40rem; }
/* Separate the form from the copy above it. Measured before this: 20px from the
   intro paragraph to the first field, against 17px between fields — so the
   intro read as one more field label and the form had no visible starting edge.
   :not(:first-child) so a form that opens its own container is unaffected. */
.ff-form:not(:first-child) { margin-top: clamp(1.7rem, 1.2rem + 1.4vw, 2.5rem); }
.ff-row { margin-bottom: 1.05rem; }
.ff-row--split { display: grid; grid-template-columns: 1fr 1fr; gap: 1.05rem; }
.ff-form label {
  display: block; font-size: .84rem; font-weight: 700; letter-spacing: .04em;
  color: var(--teal); margin-bottom: .35rem;
}
.ff-form input, .ff-form select, .ff-form textarea {
  width: 100%; font-family: inherit; font-size: 1rem; color: var(--ink);
  padding: .78rem .9rem; background: var(--card);
  border: 1.5px solid var(--rule); border-radius: 9px;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
  min-height: 46px;
}
.ff-form textarea { min-height: 140px; resize: vertical; }
.ff-form input:focus, .ff-form select:focus, .ff-form textarea:focus {
  /* A transparent outline rather than none: Windows High Contrast / forced-colors
     mode discards box-shadow, so `outline: none` left those users with no focus
     indicator at all on every form field. */
  outline: 2px solid transparent; outline-offset: 2px;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(208,177,99,.22);
}
.ff-actions { margin-top: 1.3rem; }
.ff-fineprint { font-size: .85rem; color: var(--ink-soft); margin-top: .9rem; }

/* Honeypot. Off-screen rather than display:none — some bots skip hidden inputs
   but fill positioned ones, and a real keyboard user can still never reach it
   because of tabindex="-1" and aria-hidden on the wrapper. */
.ff-hp {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden; white-space: nowrap;
}
/* Submission result. --error is a genuine alert, so it does not rely on colour
   alone: the left rule and the heavier weight carry it too. */
.ff-note { margin-top: .9rem; font-size: .93rem; padding-left: .8rem; }
.ff-note--error { color: #8A2B20; border-left: 3px solid #8A2B20; font-weight: 600; }
.ff-note a { color: inherit; }
.ff-sent {
  background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius);
  padding: clamp(1.4rem, 1rem + 2vw, 2.2rem); box-shadow: var(--shadow-sm); max-width: 40rem;
}
.ff-sent:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.ff-sent h3 { margin: 0 0 .5rem; color: var(--teal); }
.ff-sent p { margin: 0; color: var(--ink-soft); }

.map-embed { border-radius: var(--radius); overflow: hidden; border: 1px solid var(--rule); margin-bottom: 1rem; }
.map-embed iframe { display: block; width: 100%; border: 0; }
.contact-nap { font-size: 1.06rem; line-height: 2; }
.contact-line { display: inline-block; }
.aff-list { list-style: none; padding: 0; margin: 0; font-size: .92rem; }
.aff-list li { padding: .35rem 0; color: var(--ink-soft); }
.aff-list li + li { border-top: 1px dashed var(--rule); }

/* ------------------------------------------- review paths + 3D office tour */
/* Two equal routes, deliberately side by side. The source site put a
   "Would You Recommend Us?" fork in front of these and only showed the Google
   option to people who answered YES — review gating, which Google prohibits.
   Equal weight in the layout is the point, so neither reads as the default. */
.review-paths {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.1rem; margin: 1.4rem 0 1.8rem;
}
.review-path {
  background: var(--paper-warm); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: 1.3rem 1.4rem;
  display: flex; flex-direction: column;
}
.review-path h3 { margin: 0 0 .5rem; font-size: 1.12rem; }
.review-path p { color: var(--ink-soft); font-size: .96rem; margin: 0 0 1rem; }
.review-path .btn { margin-top: auto; align-self: start; }

.tour-embed {
  border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--rule); box-shadow: var(--shadow-sm);
  background: var(--paper-warm);
}
.tour-embed iframe { display: block; width: 100%; border: 0; }
/* Matterport needs real height to be usable; on a phone a 520px frame is most
   of the viewport, so trade some height for the rest of the page staying visible. */
@media (max-width: 640px) { .tour-embed iframe { height: 360px; } }
.tour-note { margin: .9rem 0 0; font-size: .93rem; color: var(--ink-soft); }

/* ----------------------------------------------------- reviews (GHL widget) */
/* Cross-origin iframe: nothing inside it can be styled from here. Previously
   this wrapper carried a white card (background + padding) to ease the seam
   between the widget's plain-white content and the page's warm paper ground —
   client asked twice (2026-08-03) to remove it, since the white card itself
   read as a border/frame around the widget. No wrapper styling now; the
   iframe sits flush against the section background. */
/* min-height, not height, as a CLS floor for the pre-load instant. In
   practice review-widget.js's postMessage resize never actually fires on
   this widget (measured live: iframe.height stays unset 8s+ after load), so
   this floor IS the rendered height, not a fallback — verified against the
   widget's real content via a headless render at production width: 412px
   desktop (1120px iframe), 518px mobile (350px iframe). Previous values
   (520 / 760) were the pre-postMessage-removal guess and left ~100-240px of
   dead space below the last review card, which read as excess space above
   the "Leave a review" button. +10-12px buffer, not the content height
   exactly, so a marginally longer review card doesn't get clipped
   (scrolling="no" on the iframe hides overflow rather than scrolling it). */
.reviews-embed iframe { display: block; width: 100%; min-height: 425px; border: 0; }
@media (max-width: 700px) { .reviews-embed iframe { min-height: 530px; } }
.reviews-embed__fallback { margin: 1.2rem; color: var(--ink-soft); }
/* Tighter than the shared .center-cta (2rem top). Client flagged both this
   gap and the section's standard bottom rhythm (--step, up to 6.5rem) as too
   much air under a two-line widget + one button — #reviews below scopes the
   bottom-padding cut to this section only, leaving --step everywhere else. */
.reviews-cta { margin-top: .35rem; margin-bottom: 0; }
#reviews { padding-bottom: 2rem; }

/* ------------------------------------------------------------------- footer */
.site-footer { background: var(--teal-deep); color: #BFD4DA; padding-top: var(--step); font-size: .94rem; }
.site-footer h2, .site-footer h3, .site-footer h4, .footer-hours-h { color: #fff; font-size: 1.02rem; font-family: 'Karla', sans-serif; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; margin-bottom: 1.1rem; }
.footer-grid { display: grid; gap: 2.2rem; grid-template-columns: 1.3fr 1fr 1fr .95fr 1.05fr; padding-bottom: var(--step); }
.footer-col ul { list-style: none; padding: 0; margin: 0; }
.footer-col li { margin-bottom: .55rem; }
.site-footer a { color: #BFD4DA; text-decoration: none; }
.site-footer a:hover { color: var(--gold); }
.site-footer a a { color: inherit; }           /* nested linkify anchors */
.aside-card--cta a { color: inherit; }
.brand-logo--footer { height: 42px; filter: brightness(0) invert(1); opacity: .92; margin-bottom: 1.1rem; }
.footer-tagline { color: #9FBAC3; max-width: 30ch; }
.footer-contact li, .footer-visit li { display: flex; gap: .55rem; align-items: flex-start; }
.footer-emergency {
  background: rgba(208,177,99,.12); border: 1px solid rgba(208,177,99,.35);
  border-radius: var(--radius); padding: 1.1rem 1.2rem; margin-top: 1.2rem;
}
.footer-emergency__label { font-size: .74rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--gold); display: block; margin-bottom: .3rem; }
.footer-emergency__call { font-family: 'Fraunces', serif; font-size: 1.3rem; color: #fff; text-decoration: none; font-weight: 600; }
.footer-bottom {
  border-top: 1px solid rgba(255,255,255,.12);
  padding-block: 1.5rem;
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  font-size: .86rem; color: #93AEB7;
}
.footer-bottom-links { display: flex; flex-wrap: wrap; gap: 1.3rem; }

/* --------------------------------------------------------------- responsive */
@media (max-width: 1080px) {
  .page-layout { grid-template-columns: minmax(0, 1fr) 300px; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 980px) {
  /* Mode isolation (Rule 10): the desktop hover cascade is fully switched off
     below this breakpoint — hover doesn't exist on touch. */
  .menu-toggle {
    display: inline-grid; place-items: center; margin-left: auto;
    width: 46px; height: 46px; border-radius: 9px;
    background: var(--teal); color: #fff; border: 0; cursor: pointer;
    position: relative; z-index: 1002;
  }
  .menu-toggle { gap: 5px; }
  .menu-toggle span {
    display: block; width: 20px; height: 2px; background: currentColor; border-radius: 2px;
    transition: transform .25s var(--ease), opacity .2s var(--ease);
  }
  .menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .main-nav {
    position: fixed; inset: 0; width: 100vw; min-height: 100vh; min-height: 100dvh;
    margin: 0; padding: calc(5.5rem + env(safe-area-inset-top)) 1.5rem calc(5rem + env(safe-area-inset-bottom));
    background: rgba(251,249,245,.98);
    backdrop-filter: saturate(145%) blur(12px);
    border-left: 0;
    box-shadow: none;
    flex-direction: column; align-items: stretch; gap: .1rem;
    overflow-y: auto; overscroll-behavior: contain;
    transform: translateX(100%);
    transition: transform .32s var(--ease);
    z-index: 1001;
  }
  .main-nav.active { transform: translateX(0); }
  .main-nav > a, .services-toggle { padding: .95rem .2rem; font-size: 1.08rem; border-bottom: 1px solid var(--rule); border-radius: 0; }
  .main-nav > a::after, .services-toggle::after { display: none; }
  .has-dropdown { width: 100%; }
  .services-toggle { width: 100%; justify-content: space-between; }
  .chev, .has-dropdown:hover .chev { transform: none; }

  /* Cascade flattens: every hub and child visible in a nested list. */
  .dropdown, .submenu {
    position: static; opacity: 1; visibility: visible; transform: none; translate: none;
    width: 100%; max-width: 100%;
    box-shadow: none; border: 0; border-radius: 0; min-width: 0;
    padding: 0 0 .45rem .65rem; background: transparent;
    display: none;
  }
  .has-dropdown.open > .dropdown { display: block; }
  .dropdown::before { display: none; }        /* no gap to bridge in flat mode */
  .submenu { display: block; padding-left: .7rem; border-left: 2px solid var(--rule); }
  .dropdown-item { padding: .42rem .2rem; font-size: .9rem; }
  /* Flat mode has no submenu to point into — the chevron is desktop-only chrome. */
  .dropdown-item--parent .chev { display: none; }
  .btn--nav { margin-top: 1.2rem; }

  .page-layout { grid-template-columns: 1fr; }
  .page-aside { position: static; max-width: 460px; }
  /* Must repeat the :has() selector. `.hero__grid:has(.hero__visual)` above is
     (0,2,0) and a bare `.hero__grid` here is (0,1,0) — specificity beats source
     order even from inside a media query, so the desktop two-column split
     survived onto phones and squeezed the hero photo into a thumbnail beside
     right-shunted text (Hardening Rule 7). */
  .hero__grid, .hero__grid:has(.hero__visual) { grid-template-columns: 1fr; }
  .hero__visual { justify-self: start; max-width: 380px; order: -1; }
}

@media (max-width: 620px) {
  body { font-size: 1.02rem; }
  .footer-grid { grid-template-columns: 1fr; gap: 2rem; }
  .ff-row--split { grid-template-columns: 1fr; }
  .cta-band-inner { flex-direction: column; align-items: flex-start; }
  .hero__actions { width: 100%; }
  .hero__actions .btn { flex: 1 1 auto; }
  .assoc-strip__grid { gap: 2rem 2.5rem; }
}

/* Primary action stays reachable at every breakpoint (Rule 11): once the sticky
   header scrolls out of practical reach on a phone, a persistent call bar takes
   over. */
.callbar { display: none; }
@media (max-width: 620px) {
  .callbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 180;
    background: var(--teal); border-top: 1px solid rgba(255,255,255,.14);
    box-shadow: 0 -10px 30px -12px rgba(20,59,78,.45);
  }
  .callbar a {
    flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
    padding: .95rem .5rem; min-height: 54px;
    color: #fff; text-decoration: none; font-weight: 700; font-size: .95rem;
  }
  .callbar a + a { border-left: 1px solid rgba(255,255,255,.16); background: var(--gold); color: var(--teal-deep); }
  body { padding-bottom: 54px; }
}

@media print {
  .topbar, .site-header, .cta-band, .callbar, .page-aside { display: none; }
  body { background: #fff; }
}

/* Landscape hero variant — the homepage leads with a wide family photo, so the
   4:5 arch would crop it to a sliver (sub-check 20). Authored AFTER .hero__photo
   so the modifier wins on source order at equal specificity (Rule 7). */
.hero__photo--wide { aspect-ratio: 3 / 2; border-radius: 34% 34% var(--radius) var(--radius) / 22% 22% var(--radius) var(--radius); }
@media (min-width: 981px) { .hero__visual:has(.hero__photo--wide) { max-width: 560px; } }

/* ---------------------------------------------- two-column narrative bands */
.two-col {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .82fr);
  gap: clamp(2rem, 1rem + 4vw, 4.5rem); align-items: start;
}
.two-col--flip .two-col__text { order: 2; }
.two-col--flip .two-col__media { order: 1; }
.two-col__text > :first-child { margin-top: 0; }
.two-col__text h3 { margin-top: 1.9rem; color: var(--ink); }
.two-col__media {
  margin: .4rem 0 0; border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--shadow-md); border: 1px solid var(--rule);
  position: sticky; top: 104px;
}
.two-col__media img { width: 100%; height: auto; display: block; }
@media (max-width: 900px) {
  .two-col { grid-template-columns: 1fr; }
  .two-col--flip .two-col__text, .two-col--flip .two-col__media { order: initial; }
  .two-col__media { position: static; max-width: 520px; }
}
.two-col__media--map iframe { display: block; width: 100%; border: 0; }


/* ---------------------------------------------- Step 16: interface guidelines */

/* Tells the browser which palette the page is built for, so native controls,
   scrollbars and form widgets match instead of rendering in the OS default. */
:root { color-scheme: light; }

/* Removes the ~300ms double-tap zoom delay on touch, and replaces the default
   grey flash on tap with something that matches the palette. */
a, button, summary, label, input[type="submit"], .btn {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(30, 81, 105, .12);
}

/* Headings set their own line breaks rather than leaving a one-word last line. */
h1, h2, h3, .hero__h1, .team-card__name { text-wrap: balance; }
/* Body copy gets the lighter version — balance is expensive over long text. */
p, li, .lede, .hero__sub { text-wrap: pretty; }

/* Opening hours and fee figures line up in columns instead of drifting, because
   proportional digits vary in width. */
.hours, .hours-row, .nap-list, .dc-table, table { font-variant-numeric: tabular-nums; }

/* Full-bleed bars sit under the notch and the home indicator on modern phones
   without the safe-area padding. */
.topbar, .site-header { padding-left: max(0px, env(safe-area-inset-left)); padding-right: max(0px, env(safe-area-inset-right)); }
.site-footer { padding-bottom: max(1.5rem, env(safe-area-inset-bottom)); }

/* Modal-ish scrollers should not chain their scroll to the page behind them. */
.dc-faq, .tour-embed, .map-embed { overscroll-behavior: contain; }
