/* ==========================================================================
   FRESH DENTAL SOLUTIONS — COMPONENTS
   ==========================================================================
   The reusable vocabulary: nav, footer, buttons, cards, badges, forms,
   tables, breadcrumbs, section headers, prose/long-form typography.
   Every class here is meant to be used on any page, including morphic and
   KB surfaces, which layer their own look on top in morphic.css / kb.css.

   Depends on: tokens.css, base.css. Load this file third.
   ========================================================================== */

/* ==========================================================================
   NAV — the ONLY position:fixed element on the site (plus its mobile drawer)
   ==========================================================================
   <header>
     <a class="skip-link" href="#main">Skip to content</a>
     <nav class="nav" aria-label="Primary">
       <div class="nav-inner container">
         <a class="nav-logo" href="/index.html" aria-label="Fresh Dental Solutions — home">
           <span class="nav-logo-mark">Fresh</span><span class="nav-logo-tail">Dental</span>
         </a>
         <button class="nav-toggle" type="button" aria-expanded="false" aria-controls="nav-drawer" aria-label="Open menu">
           <span class="nav-toggle-bar"></span><span class="nav-toggle-bar"></span><span class="nav-toggle-bar"></span>
         </button>
         <div class="nav-drawer" id="nav-drawer">
           <ul class="nav-links" role="list">
             <li><a class="nav-link is-active" href="/index.html" aria-current="page">Home</a></li>
             <li><a class="nav-link" href="/about.html">About</a></li>
           </ul>
           <a class="btn btn-primary btn-sm" href="/contact.html">Book a visit</a>
         </div>
       </div>
     </nav>
   </header>
   JS contract: toggling opens the drawer by adding `.is-open` to
   `.nav-drawer` and flipping the toggle button's `aria-expanded`. */

.nav {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--z-nav);
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}

.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-6);
  padding-block: var(--s-4);
}

.nav-logo {
  display: inline-flex;
  /* Never let the flex row shrink the lockup: base.css gives every img a
     max-width:100%, so a squeezed flex item silently distorts the mark. */
  flex: 0 0 auto;
  align-items: baseline;
  gap: 0.15em;
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: var(--tracking-tight);
  color: var(--text);
  text-decoration: none;
}
.nav-logo:hover { color: var(--text); }
.nav-logo-tail { color: var(--brand); }

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--s-7);
}

.nav-link {
  position: relative;
  padding-block: var(--s-1);
  color: var(--text-muted);
  font-weight: 500;
  font-size: var(--fs-sm);
  text-decoration: none;
}
.nav-link::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 2px;
  background: var(--grad-fresh);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t) var(--ease-out);
}
.nav-link:hover { color: var(--text); }
.nav-link:hover::after,
.nav-link.is-active::after { transform: scaleX(1); }
.nav-link.is-active { color: var(--text); font-weight: 600; }

/* Desktop: the drawer is not off-canvas, it's simply the rest of the nav
   row (links + book button) sitting inline next to the logo/mode-switch.
   The mobile media query below replaces this with the off-canvas column
   layout. Without an explicit row here the drawer's block children (the nav
   list, then the button) stack vertically and roughly double the nav's
   rendered height — which is also what --nav-h has to clear. */
.nav-drawer {
  display: flex;
  align-items: center;
  gap: var(--s-6);
}

.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  padding: var(--s-2);
  border-radius: var(--r-sm);
}
.nav-toggle-bar {
  width: 22px;
  height: 2px;
  background: var(--text);
  border-radius: var(--r-full);
  transition: transform var(--t) var(--ease-out), opacity var(--t) var(--ease-out);
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* The desktop nav row (logo + mode switch + five links + the book button)
   stops fitting well before the old 48rem breakpoint: between ~770px and
   ~1010px it wrapped onto a second line and the bar grew from ~76px to
   ~89px, while --nav-h stayed at 5rem — so the top of every page sat ~9px
   UNDERNEATH the fixed nav. Handing over to the off-canvas drawer at 64rem
   keeps the bar a single ~76px row at every width. js/main.js additionally
   syncs --nav-h to the measured height as a safety net. */
@media (max-width: 64rem) {
  /* The drawer sits at --z-drawer, above the nav's own --z-nav, so without
     this the open drawer paints its white panel straight over the toggle —
     and the toggle is exactly what animates into the X you close it with.
     Lift the button above the panel so that X is actually clickable
     (Escape and click-outside already worked; the visible control did not). */
  .nav-toggle {
    display: inline-flex;
    position: relative;
    z-index: calc(var(--z-drawer) + 1);
  }
  .nav-links { gap: var(--s-5); }

  .nav-drawer {
    position: fixed;
    inset-block-start: 0;
    inset-block-end: 0;
    inset-inline-end: 0;
    width: min(20rem, 84vw);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-8);
    padding: var(--s-16) var(--s-6) var(--s-6);
    background: var(--bg-raised);
    border-left: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
    transform: translateX(100%);
    /* `visibility: hidden` while closed is not decoration — a drawer parked
       off-screen with transform alone keeps its six links in the tab order,
       so a keyboard user tabs straight into invisible controls. Widening the
       drawer breakpoint to 64rem (above) put far more viewports on this
       path, so it is fixed here rather than left. The delayed visibility
       transition lets the slide-out animation finish before the panel is
       taken out of the tree; opening flips it back immediately. */
    visibility: hidden;
    transition: transform var(--t-slow) var(--ease-out),
                visibility 0s linear var(--t-slow);
    z-index: var(--z-drawer);
  }
  .nav-drawer.is-open {
    transform: translateX(0);
    visibility: visible;
    transition: transform var(--t-slow) var(--ease-out), visibility 0s;
  }
  .nav-drawer .nav-links { flex-direction: column; align-items: flex-start; gap: var(--s-5); }
}

/* ==========================================================================
   FOOTER
   ==========================================================================
   <footer class="site-footer">
     <div class="container footer-grid">
       <div class="footer-col footer-brand">
         <p class="footer-logo">Fresh<span>Dental</span></p>
         <p>Family dentistry in Portland, OR.</p>
       </div>
       <nav class="footer-col" aria-label="Explore">
         <h3 class="footer-heading">Explore</h3>
         <ul class="footer-list" role="list"><li><a href="/services.html">Services</a></li></ul>
       </nav>
       <div class="footer-col">
         <h3 class="footer-heading">Contact</h3>
         <address class="footer-address">
           <a href="tel:+15035551234">(503) 555-1234</a>
         </address>
       </div>
     </div>
     <div class="container footer-bottom">
       <p>&copy; 2026 Fresh Dental Solutions.</p>
     </div>
   </footer> */

.site-footer {
  /* One step lighter than .cta-band's --ink-900 (morphic.css), plus its own
     top accent line below, so two adjacent dark bands never merge into one
     undifferentiated mass at the bottom of the page. */
  background: var(--ink-800);
  color: var(--ink-200);
  padding-block: var(--s-16) var(--s-8);
  position: relative;
}
.site-footer::before {
  content: '';
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 1px;
  background: var(--ink-600);
}

.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--s-10);
  padding-bottom: var(--s-10);
}

.footer-logo {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--ink-50);
  margin-bottom: var(--s-3);
}
.footer-logo span { color: var(--brand-300); }

.footer-brand p:not(.footer-logo) { color: var(--ink-300); }

.footer-heading {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-300);
  margin-bottom: var(--s-4);
}

.footer-list { display: flex; flex-direction: column; gap: var(--s-3); }
.footer-list a,
.footer-address a {
  color: var(--ink-200);
  text-decoration: none;
  font-size: var(--fs-sm);
}
.footer-list a:hover,
.footer-address a:hover { color: var(--mint-400); }

.footer-address { font-style: normal; display: flex; flex-direction: column; gap: var(--s-3); font-size: var(--fs-sm); }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  justify-content: space-between;
  padding-top: var(--s-6);
  border-top: 1px solid var(--ink-700);
  font-size: var(--fs-xs);
  color: var(--ink-300); /* 7.3:1 on the footer; --ink-400 was only 4.2:1 */
}
/* base.css sets `p { color: var(--text-muted) }` on the ELEMENT, which beats
   this block's inherited colour. On the permanently-dark footer that put the
   copyright line at --ink-600 on --ink-800 = 1.72:1 in light mode — near
   invisible. (.footer-brand p already carries the same guard.) */
.footer-bottom p { color: inherit; }

/* ==========================================================================
   BUTTONS
   ==========================================================================
   <a class="btn btn-primary btn-md" href="…">Book a visit</a>
   <button class="btn btn-secondary btn-sm" type="button">Learn more</button>
   <button class="btn btn-ghost btn-lg" type="button">Cancel</button>
   <button class="btn btn-danger btn-md" type="button">Delete</button>
   Disabled: add the native `disabled` attribute (buttons) or
   `aria-disabled="true"` + tabindex="-1" (anchors acting as buttons). */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  border-radius: var(--r-md);
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--t) var(--ease-out), border-color var(--t) var(--ease-out),
    color var(--t) var(--ease-out), transform var(--t) var(--ease-out), box-shadow var(--t) var(--ease-out);
}
.btn:active { transform: translateY(1px); }
.btn:disabled,
.btn[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.55;
  transform: none;
}

.btn-sm { padding: var(--s-2) var(--s-4); font-size: var(--fs-sm); }
.btn-md { padding: var(--s-3) var(--s-6); font-size: var(--fs-md); }
.btn-lg { padding: var(--s-4) var(--s-8); font-size: var(--fs-lg); }

.btn-primary {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-contrast);
}
.btn-primary:hover:not(:disabled):not([aria-disabled="true"]) {
  background: var(--brand-hover);
  border-color: var(--brand-hover);
}

.btn-secondary {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text);
}
.btn-secondary:hover:not(:disabled):not([aria-disabled="true"]) {
  border-color: var(--brand);
  color: var(--brand);
}

.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text);
}
.btn-ghost:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--bg-subtle); }

.btn-danger {
  background: var(--danger);
  border-color: var(--danger);
  color: #ffffff;
}
.btn-danger:hover:not(:disabled):not([aria-disabled="true"]) { filter: brightness(0.92); }

/* ==========================================================================
   CARDS
   ==========================================================================
   Base card:
   <div class="card"><h3>Title</h3><p>Body.</p></div>

   Service card:
   <article class="card card-service">
     <div class="card-service-icon" aria-hidden="true"><svg …/></div>
     <h3>Preventive Care</h3>
     <p>Cleanings, exams and sealants.</p>
     <a class="card-link" href="/services.html#preventive">Learn more →</a>
   </article>

   KB card:
   <article class="card card-kb">
     <p class="card-kb-cat">Prevention</p>
     <h3><a href="/kb/slug.html">Article title</a></h3>
     <p>Summary…</p>
     <p class="card-kb-meta">6 min read · Reviewed Aug 2026</p>
   </article>

   Team card:
   <article class="card card-team">
     <img class="card-team-photo" src="…" alt="Dr. James Sloengaard" />
     <h3>Dr. James Sloengaard</h3>
     <p class="card-team-role">Lead Dentist, DMD</p>
   </article>

   Stat/figure card:
   <div class="card card-stat">
     <p class="card-stat-figure">98%</p>
     <p class="card-stat-label">Patient satisfaction</p>
   </div> */

.card {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--s-8);
  transition: box-shadow var(--t) var(--ease-out), transform var(--t) var(--ease-out), border-color var(--t) var(--ease-out);
}
.card > * + * { margin-top: var(--s-4); }
/* Icon (or photo) to title wants more air than title-to-body — the internal
   rhythm a squat card is missing. */
.card > :first-child:is(.card-service-icon, .card-team-photo) + * { margin-top: var(--s-5); }
/* Card title size is fixed regardless of heading level — a card's title is
   occasionally promoted from h3 to h2 to keep page heading order valid (see
   js/morphic.js's service-sections rendering), and that promotion must stay
   visually invisible per the "visual demotion is CSS, not markup demotion"
   rule. */
.card h2, .card h3 { font-size: var(--fs-lg); }

a.card:hover,
.card.is-interactive:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.card-link {
  display: inline-block;
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
}
/* Navigational card links carry an affordance arrow. It lives here, not in
   the link text, so it stays out of the accessible name and out of the
   markdown twins — and it can move on hover, which a text glyph cannot. */
.card-link.is-nav::after {
  content: '\2192';
  display: inline-block;
  margin-left: var(--s-2);
  transition: transform var(--t) var(--ease-out);
}
.card-link.is-nav:hover::after { transform: translateX(3px); }

.card-service { text-align: left; }
/* When the whole card is the link target (js/morphic.js's linkable
   service-grid), only the title should read as a link — the browser's
   underline otherwise paints straight through the body copy too. Kill it
   everywhere in the card except the title, which gets it back
   intentionally so the card still visibly reads as a doorway. */
a.card-service {
  text-decoration: none;
}
a.card-service h2,
a.card-service h3 {
  text-decoration: underline;
  text-decoration-color: var(--border-strong);
  /* The card titles are large serif display type with real descenders. At
     0.15em the rule cut straight through the "y" of "General Dentistry",
     and a 2px stroke under 20px+ type reads as heavy. Drop it clear of the
     descenders, keep it hairline, and let it break around the glyphs. */
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
  text-decoration-skip-ink: auto;
}
a.card-service:hover h2,
a.card-service:hover h3,
a.card-service:focus-visible h2,
a.card-service:focus-visible h3 {
  color: var(--brand);
  text-decoration-color: currentColor;
}
.card-service-icon {
  width: 4.5rem;
  height: 4.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-lg);
  background: var(--surface-accent);
  font-size: var(--fs-2xl);
}
/* A bit more type weight on the card-service title too — the icon-box bump
   above otherwise leaves the (still --fs-lg) heading looking small next to
   it. card-kb keeps --fs-lg; its denser, list-like card reads fine compact. */
.card-service h2, .card-service h3,
.card-team h2, .card-team h3 {
  font-size: var(--fs-xl);
}

.card-kb { display: flex; flex-direction: column; }
/* h2 covers the case where morphic.js promotes this card's title one level
   (its section heading became the page's <h1>) — must stay visually
   identical to the normal h3 case. */
.card-kb h2, .card-kb h3 { font-size: var(--fs-lg); }
.card-kb h2 a, .card-kb h3 a { color: var(--text); text-decoration: none; }
.card-kb h2 a:hover, .card-kb h3 a:hover { color: var(--brand); }
.card-kb-cat {
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent-text);
}
.card-kb-meta { margin-top: auto; padding-top: var(--s-3); font-size: var(--fs-xs); color: var(--text-faint); }

/* Left-aligned to match .card-service (about.html's value cards) — one
   alignment rule for every card on the page instead of team cards reading
   as a different, centered component next to them. */
.card-team { text-align: left; }
.card-team-photo {
  width: 128px;
  height: 128px;
  margin-inline: 0;
  object-fit: cover;
  border-radius: var(--r-full);
  border: 3px solid var(--bg);
  box-shadow: var(--shadow-md);
}
/* A team member without a photo falls back to the generic service-icon
   slot (js/morphic.js) — same element other cards use for a small square
   glyph. Inside a team card, match it to the photo slot's own size/shape so
   every seat in the row reads as the same kind of thing, whether it ends up
   holding a photo, a future avatar illustration, or this emoji fallback. */
.card-team .card-service-icon {
  width: 128px;
  height: 128px;
  margin-inline: 0;
  border-radius: var(--r-full);
  border: 3px solid var(--bg);
  box-shadow: var(--shadow-md);
  font-size: var(--fs-4xl);
}
.card-team-role { font-size: var(--fs-sm); color: var(--text-faint); }

.card-stat { text-align: center; }
.card-stat-figure {
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  color: var(--brand);
  letter-spacing: var(--tracking-tight);
}
.card-stat-label { font-size: var(--fs-sm); color: var(--text-muted); }

/* ==========================================================================
   BADGES / PILLS / TAGS — one component, tone + size modifiers
   ==========================================================================
   <span class="badge badge-brand">New patients welcome</span>
   <span class="badge badge-mint badge-sm">Tier 1</span>
   <span class="badge badge-danger">Urgent</span> */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.4;
  white-space: nowrap;
}
.badge-sm { padding: 0.1rem var(--s-2); font-size: 0.7rem; }

.badge-neutral { background: var(--bg-subtle); color: var(--text-muted); border: 1px solid var(--border); }
.badge-brand   { background: var(--surface-accent); color: var(--brand-700); }
.badge-cyan    { background: var(--cyan-100); color: var(--ink-900); }
.badge-mint    { background: var(--mint-100); color: var(--ink-900); }
.badge-danger  { background: var(--danger-bg); color: var(--danger); }
.badge-warn    { background: var(--warn-bg); color: var(--warn); }
.badge-ok      { background: var(--ok-bg); color: var(--ok); }
/* POP #3 of 4 (see --pop in tokens.css). For the ONE thing on a page that
   is genuinely new or genuinely needs a second look — never as a general
   category colour, and never two at once in the same view. */
.badge-pop     { background: var(--pop-soft); color: var(--pop-strong); }

/* The `:not([data-theme="light"])` half MUST sit inside the media query —
   without it the selector also matches a plain light-mode :root, which put
   --brand-300 text on the near-white --brand-50 fill at 1.8:1. */
:root[data-theme="dark"] .badge-brand { color: var(--brand-300); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .badge-brand { color: var(--brand-300); }
}

/* ==========================================================================
   FORMS
   ==========================================================================
   <div class="field">
     <label class="label" for="name">Full name</label>
     <input class="input" id="name" name="name" type="text" required aria-describedby="name-help" />
     <p class="help" id="name-help">As it appears on your insurance card.</p>
   </div>

   Error state:
   <div class="field has-error">
     <label class="label" for="email">Email</label>
     <input class="input" id="email" name="email" type="email" aria-invalid="true" aria-describedby="email-error" />
     <p class="error-msg" id="email-error">Enter a valid email address.</p>
   </div>

   <fieldset class="fieldset">
     <legend class="legend">Preferred contact method</legend>
     …radio/checkbox fields…
   </fieldset> */

.field { display: flex; flex-direction: column; gap: var(--s-2); }

.label { font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.label .is-optional { font-weight: 400; color: var(--text-faint); }

.input, .textarea, .select {
  width: 100%;
  padding: var(--s-3) var(--s-4);
  background: var(--bg-raised);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  font-size: var(--fs-md);
  transition: border-color var(--t) var(--ease-out), box-shadow var(--t) var(--ease-out);
}
.textarea { min-height: 8rem; resize: vertical; }

.input:hover, .textarea:hover, .select:hover { border-color: var(--text-faint); }

.input:focus-visible, .textarea:focus-visible, .select:focus-visible {
  border-color: var(--focus);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 22%, transparent);
}

.input::placeholder, .textarea::placeholder { color: var(--text-faint); }

.input:disabled, .textarea:disabled, .select:disabled {
  background: var(--bg-subtle);
  color: var(--text-faint);
  cursor: not-allowed;
}

.help { font-size: var(--fs-xs); color: var(--text-faint); }

.field.has-error .input,
.field.has-error .textarea,
.field.has-error .select { border-color: var(--danger); }
.error-msg { font-size: var(--fs-xs); font-weight: 600; color: var(--danger); }

.fieldset { border: 1px solid var(--border); border-radius: var(--r-md); padding: var(--s-5); }
.legend { padding-inline: var(--s-2); font-weight: 600; font-size: var(--fs-sm); }

/* Checkbox / radio: keep the native control, style the row */
.check-row { display: flex; align-items: flex-start; gap: var(--s-3); }
.check-row input[type="checkbox"],
.check-row input[type="radio"] { width: 1.1rem; height: 1.1rem; accent-color: var(--brand); margin-top: 0.15em; }

/* ==========================================================================
   TABLES
   ==========================================================================
   <div class="table-scroll">
     <table class="table">
       <caption class="visually-hidden">Appointment types and durations</caption>
       <thead><tr><th scope="col">Service</th><th scope="col">Duration</th></tr></thead>
       <tbody><tr><td>Cleaning</td><td>45 min</td></tr></tbody>
     </table>
   </div> */

.table-scroll { overflow-x: auto; }

.table { font-size: var(--fs-sm); }
.table th, .table td {
  text-align: left;
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.table thead th {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-faint);
  border-bottom: 2px solid var(--border-strong);
}
.table tbody tr:hover { background: var(--bg-subtle); }

/* ==========================================================================
   BREADCRUMBS
   ==========================================================================
   <nav class="breadcrumb" aria-label="Breadcrumb">
     <ol>
       <li><a href="/kb/index.html">Knowledge Base</a></li>
       <li><a href="/kb/index.html#prevention">Prevention</a></li>
       <li aria-current="page">Article title</li>
     </ol>
   </nav> */

.breadcrumb ol { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.breadcrumb li { display: flex; align-items: center; gap: var(--s-2); font-size: var(--fs-sm); color: var(--text-faint); }
.breadcrumb li:not(:last-child)::after { content: '/'; color: var(--border-strong); }
.breadcrumb a { color: var(--text-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--brand); }
.breadcrumb li[aria-current="page"] { color: var(--text); font-weight: 600; }

/* ==========================================================================
   SECTIONS — vertical rhythm band, and its eyebrow + heading + lede header
   ==========================================================================
   <section class="section">
     <div class="container">
       <header class="section-head">
         <p class="eyebrow">Our approach</p>
         <h2>Care that starts with listening</h2>
         <p class="lede">A calm, modern practice for the whole family.</p>
       </header>
       … section content …
     </div>
   </section>
   `.section-subtle` swaps in the subtle background for alternating bands. */

.section { padding-block: var(--s-16); }
.section-subtle { background: var(--bg-subtle); }
.section-tight { padding-block: var(--s-10); }

.section-head { max-width: var(--container-narrow); margin-bottom: var(--s-10); }
.section-head.is-centered { margin-inline: auto; text-align: center; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--accent-text);
  margin-bottom: var(--s-3);
}
.eyebrow::before {
  content: '';
  display: inline-block;
  width: 1.5rem;
  height: 2px;
  background: var(--grad-fresh);
}

.section-head h2 { margin-bottom: var(--s-3); }
.lede { font-size: var(--fs-lg); color: var(--text-muted); }

/* ==========================================================================
   PROSE — long-form typography, shared by KB articles and any hand-written
   content. The markdown renderer (js/markdown.js) only ever emits the tags
   styled below: h1–h4, p, strong, em, a, ul/ol (single level), blockquote,
   hr, code/pre.
   ==========================================================================
   <div class="prose"> … rendered markdown … </div> */

.prose { max-width: var(--measure); color: var(--text); }
.prose > * + * { margin-top: var(--s-5); }

.prose h1 { font-size: var(--fs-3xl); margin-top: var(--s-12); }
.prose h2 { font-size: var(--fs-2xl); margin-top: var(--s-10); }
.prose h3 { font-size: var(--fs-xl); margin-top: var(--s-8); }
.prose h4 { font-size: var(--fs-lg); margin-top: var(--s-6); }
.prose > :first-child { margin-top: 0; }

.prose p { color: var(--text-muted); line-height: var(--lh-body); }

.prose ul, .prose ol { padding-left: 1.4em; color: var(--text-muted); }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li + li { margin-top: var(--s-2); }
.prose li::marker { color: var(--text-faint); }

.prose a { text-decoration: underline; text-underline-offset: 0.15em; }

.prose blockquote {
  padding: var(--s-4) var(--s-6);
  border-left: 3px solid var(--mint);
  background: var(--bg-subtle);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  color: var(--text);
  font-style: italic;
}
.prose blockquote > * + * { margin-top: var(--s-3); }

.prose hr {
  border-top: 1px solid var(--border);
  margin-block: var(--s-10);
}

.prose code {
  font-size: 0.9em;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 0.15em 0.4em;
}
.prose pre {
  overflow-x: auto;
  padding: var(--s-4) var(--s-5);
  background: var(--ink-900);
  color: var(--ink-50);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  line-height: 1.6;
}
.prose pre code { background: none; border: none; padding: 0; color: inherit; }
