/* US Dental Compass — the prototype's design system, translated from its inline
   styles into tokens and classes.

   The prototype computes colours in JavaScript and injects them into every
   style attribute. That cannot ship: a search-engine crawler and a reader with
   JS blocked would both get unstyled text, and the whole site is a static-first
   SEO play. So the palette lives in CSS custom properties, the theme switches
   through `prefers-color-scheme` plus a `data-theme` attribute, and the toggle
   only flips that attribute. */

:root{
  --bg:#F1F4F3; --panel:#FFFFFF;
  --ink:#14232B; --ink2:#4C5F66; --ink3:#8698A0;
  --rule:#DBE3E2;
  --teal:#25646F; --teal-deep:#123B44; --teal-wash:#E3EDED;
  --wax:#B8492A; --wax-wash:#F7E7E1;
  --good:#2F6B4F; --good-wash:#E4EFE8;

  --serif:'Newsreader',Georgia,'Times New Roman',serif;
  --sans:'Public Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  --mono:'SF Mono',SFMono-Regular,Menlo,Consolas,monospace;
  --r:4px;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --bg:#0D171B; --panel:#152329;
    --ink:#EAF0EF; --ink2:#A5B6BB; --ink3:#6B7F86;
    --rule:#26383F;
    --teal:#6FB6C2; --teal-deep:#9AD2DB; --teal-wash:#17323A;
    --wax:#E88A66; --wax-wash:#31201A;
    --good:#7FC49E; --good-wash:#172C22;
  }
}
:root[data-theme="dark"]{
  --bg:#0D171B; --panel:#152329;
  --ink:#EAF0EF; --ink2:#A5B6BB; --ink3:#6B7F86;
  --rule:#26383F;
  --teal:#6FB6C2; --teal-deep:#9AD2DB; --teal-wash:#17323A;
  --wax:#E88A66; --wax-wash:#31201A;
  --good:#7FC49E; --good-wash:#172C22;
}

*{box-sizing:border-box}
/* The UA stylesheet's [hidden]{display:none} is an author-beatable rule, so
   any class here that sets `display` silently outranks it. Both places that
   toggle `hidden` set one — .row is flex, .cards is block then grid — so the
   clinics behind "Show clinics with no confirmed dental services" rendered
   openly, and a paginated roster kept all 334 rows in layout while reporting
   itself hidden. This restores the attribute's meaning for the whole site. */
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--ink);
  font:400 16px/1.5 var(--sans);-webkit-font-smoothing:antialiased}
a{color:inherit}
img{max-width:100%}

/* The prototype's three shells. Detail and list pages go to 1120; home to 1080. */
.shell{width:100%;max-width:600px;margin:0 auto}
@media (min-width:768px){.shell{max-width:760px}}
@media (min-width:1024px){.shell{max-width:1120px}}
.shell.home{max-width:600px}
@media (min-width:768px){.shell.home{max-width:760px}}
@media (min-width:1024px){.shell.home{max-width:1080px}}

/* ---- chrome ---------------------------------------------------------- */
.site-head{display:flex;align-items:center;justify-content:space-between;
  padding:26px 20px;border-bottom:1px solid var(--rule)}
/* The home page opens on the photograph, which is its own divider; a rule
   directly above it reads as a doubled edge. Every other page keeps the rule,
   having nothing below it to do the job. */
.home .site-head{border-bottom:none}
.mark{display:flex;align-items:center;gap:9px;text-decoration:none;color:var(--ink)}
.mark svg{width:24px;height:24px;flex:0 0 24px}
.mark b{font:500 19px/1 var(--serif);letter-spacing:.01em;font-weight:500}
.theme-btn{border:none;background:transparent;color:var(--ink2);cursor:pointer;
  padding:6px;display:flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px}
.theme-btn .moon{display:block}
.theme-btn .sun{display:none}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .theme-btn .moon{display:none}
  :root:not([data-theme="light"]) .theme-btn .sun{display:block}
}
:root[data-theme="dark"] .theme-btn .moon{display:none}
:root[data-theme="dark"] .theme-btn .sun{display:block}

.crumbs{padding:20px 20px 0;font:500 11px var(--sans);letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink3)}
.crumbs a{color:var(--ink3);text-decoration:none}
.crumbs a:hover{color:var(--teal)}
.crumbs .sep{padding:0 8px}

.titleblock{padding:18px 20px 18px}
.eyebrow{margin:0 0 8px;font:600 11px var(--sans);letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink3)}
.eyebrow.teal{color:var(--teal);letter-spacing:.18em;margin-bottom:20px}
h1{margin:0;font:500 30px/1.2 var(--serif);letter-spacing:-.01em;color:var(--ink)}
h1.big{font-size:clamp(34px,5.5vw,52px);line-height:1.08;max-width:15ch;margin-bottom:22px}
/* Under a person's name: what they do, once you know whose name it is. */
.subtitle{margin:8px 0 0;font:500 15px var(--sans);letter-spacing:.01em;color:var(--teal)}

/* Section heading — one pattern used on every page of the prototype. */
.sec{padding:32px 20px 8px}
.sec:first-of-type{padding-top:0}
.sec h2{margin:0 0 16px;font:700 11.5px var(--sans);letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink);
  padding:0 0 14px 14px;border-bottom:1px solid var(--rule);position:relative}
/* A short accent rule marks a heading as structural. Colour alone was not
   enough to separate it from a label at the same size. */
.sec h2::before{content:"";position:absolute;left:0;top:1px;
  width:4px;height:12px;background:var(--teal);border-radius:2px}
.sec p{margin:0 0 8px;font-size:15px;line-height:1.6;color:var(--ink2);max-width:56ch}
.sec ul{margin:14px 0 0;padding-left:20px;font-size:15px;line-height:1.75;color:var(--ink2)}
.note{margin:8px 0 0;font-size:12.5px;color:var(--ink3);line-height:1.6}

/* ---- facts ----------------------------------------------------------- */
.facts{background:var(--panel);border:1px solid var(--rule);border-radius:var(--r);
  overflow:hidden}
.fact{display:grid;grid-template-columns:110px 1fr;gap:12px;padding:14px 16px;
  border-bottom:1px solid var(--rule)}
.fact:last-child{border-bottom:0}
/* Field labels step down deliberately: lighter, smaller, barely tracked —
   subordinate to the heading above them rather than a peer of it. */
.fact dt,.fact .k{font:500 10.5px var(--sans);letter-spacing:.03em;
  text-transform:uppercase;color:var(--ink3);margin:0;padding-top:2px}
.fact dd,.fact .v{font-size:14.5px;color:var(--ink);margin:0}
.fact-plain{padding:14px 0}

/* ---- rows (dentist lists, nearby, states) ---------------------------- */
.row{display:flex;justify-content:space-between;align-items:center;gap:16px;
  text-decoration:none;color:inherit;padding:14px 0;border-bottom:1px solid var(--rule)}
.row-name{display:block;font:500 16.5px var(--serif);color:var(--ink)}
.row-sub{display:block;font-size:12.5px;color:var(--ink3)}
.row-chev{color:var(--teal);font-size:18px}
.row-count{font:500 11px var(--sans);letter-spacing:.08em;text-transform:uppercase;
  color:var(--teal);white-space:nowrap}
.row.state{align-items:baseline;padding:18px 0}
.row.state .row-name{font-size:20px}
/* The cell that opens the rest of a state sits in the same grid as the clinic
   rows and keeps their flat geometry, so the block stays even. A filled box read
   as a different component and a leading icon added a third thing to look at;
   what carries the difference is weight and colour — the heaviest text in the
   block, in teal, without the serif that marks a row as somebody's name. */
/* 700, not 800: the stylesheet loads Public Sans at 400/500/600/700, so a
   heavier declaration either resolves back to this face or gets synthesised
   into a smeared fake bold. */
.row.row-all .row-name{font:700 12.5px var(--sans);letter-spacing:.08em;
  text-transform:uppercase;color:var(--teal)}
.row.row-all .row-sub{color:var(--teal);opacity:.75;font-weight:500}
.row.row-all .row-chev{font-size:19px;font-weight:700}
.row.row-all:hover .row-name{text-decoration:underline}

/* ---- clinic / dentist card ------------------------------------------ */
.cards{display:block}
@media (min-width:768px){.cards{display:grid;grid-template-columns:1fr 1fr;gap:14px}}
.card{background:var(--panel);border:1px solid var(--rule);border-radius:var(--r);
  padding:20px;margin-bottom:14px}
@media (min-width:768px){.card{margin-bottom:0}}
/* Cards in a grid row already stretch to the tallest one, but their contents
   are ragged — a two-line name, or a second row of badges, pushed the action
   row down while its neighbours' sat higher, so the buttons stepped up and down
   across the row. Making the card a column and letting the actions take the
   slack puts every button on one line. Below 768px the cards are stacked one
   per row, where there is nothing to align against and the extra height would
   only leave a gap, so this stays inside the grid breakpoint. */
@media (min-width:768px){
  .card{display:flex;flex-direction:column}
  .card .actions{margin-top:auto}
}
.card-link{text-decoration:none;color:inherit;display:block;margin-bottom:12px}
.card-name{margin:0 0 4px;font:500 19px var(--serif);color:var(--ink)}
.star-rating{display:inline-flex;align-items:baseline;gap:1px;margin-left:8px;vertical-align:.08em;
  white-space:nowrap;font:600 .7em/1 var(--sans);letter-spacing:0;color:var(--wax)}
.star-rating .star.empty{color:var(--rule)}
.star-rating .star.half{background:linear-gradient(90deg,var(--wax) 50%,var(--rule) 50%);
  -webkit-background-clip:text;background-clip:text;color:transparent}
h1 .star-rating{font-size:.52em;vertical-align:.16em}
.row-name .star-rating{font-size:.64em;vertical-align:.1em}
.card-meta{margin:0 0 8px;font:500 11px var(--sans);letter-spacing:.06em;
  text-transform:uppercase;color:var(--teal)}
.card-line{margin:0 0 2px;font-size:13.5px;color:var(--ink2)}
.card-line:last-child{margin-bottom:0}
.badges{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 10px}
.badge{display:inline-flex;align-items:center;min-height:24px;padding:4px 8px;
  border:1px solid var(--rule);border-radius:3px;background:var(--teal-wash);
  color:var(--teal);font:600 10px var(--sans);letter-spacing:.03em}
.contact-links{display:grid;gap:10px}
.contact-item{display:flex;align-items:center;gap:12px;min-width:0;padding:12px 14px;
  border:1px solid var(--rule);border-radius:var(--r);background:var(--panel);
  color:var(--ink);text-decoration:none;transition:border-color .15s,background .15s}
.contact-item:hover{border-color:var(--teal);background:var(--teal-wash)}
.contact-icon{display:flex;align-items:center;justify-content:center;flex:0 0 28px;
  width:28px;height:28px;border-radius:50%;background:var(--teal-wash);color:var(--teal)}
.contact-icon svg{width:17px;height:17px}
.contact-copy{display:flex;flex-direction:column;gap:2px;min-width:0}
.contact-label{font:700 10px var(--sans);letter-spacing:.12em;text-transform:uppercase;color:var(--ink3)}
.contact-value{font-size:14px;color:var(--ink);overflow-wrap:anywhere}
.contact-arrow{margin-left:auto;flex:0 0 auto;color:var(--teal);font-size:19px;line-height:1}
.feature-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:24px}
.feature-item{display:flex;align-items:flex-start;gap:10px;padding:11px 0;border-bottom:1px solid var(--rule);
  color:var(--ink);font-size:14px;line-height:1.45}
.feature-check{display:flex;align-items:center;justify-content:center;flex:0 0 20px;width:20px;height:20px;
  margin-top:1px;border:1px solid var(--teal);border-radius:50%;background:var(--teal-wash);
  color:var(--teal);font:700 12px/1 var(--sans)}
@media (max-width:600px){.feature-list{grid-template-columns:1fr}}
.hours{border-collapse:collapse;width:100%;font-size:14px}
.hours th,.hours td{text-align:left;padding:9px 12px 9px 0;border-bottom:1px solid var(--rule)}
.hours th{font:600 11px var(--sans);letter-spacing:.06em;text-transform:uppercase;color:var(--ink3)}
.hours td{color:var(--ink)}

/* The two-button row. The phone is an outlined circle here and the filled pill
   is "View details", because on a list nobody yet knows enough to place a call.
   The accent colour is spent once, on the detail page's own call bar. */
.actions{display:flex;gap:10px;align-items:center}
.btn-call-sm{width:44px;height:44px;flex:0 0 44px;border-radius:99px;
  border:1.5px solid var(--ink2);display:flex;align-items:center;justify-content:center;
  text-decoration:none;color:var(--ink2)}
.btn-call-sm svg{width:18px;height:18px}
.btn-primary{flex:1;text-align:center;background:var(--ink);color:var(--bg);
  padding:12px;border-radius:3px;font:600 13px var(--sans);letter-spacing:.06em;
  text-transform:uppercase;text-decoration:none;min-height:44px;
  display:flex;align-items:center;justify-content:center}

/* ---- filters --------------------------------------------------------- */
.filters{padding:0 20px 16px;display:flex;gap:8px;overflow-x:auto;
  -webkit-overflow-scrolling:touch}
.chip{flex:0 0 auto;padding:9px 14px;border-radius:3px;font:600 12px var(--sans);
  letter-spacing:.06em;text-transform:uppercase;border:1.5px solid var(--rule);
  background:var(--panel);color:var(--ink2);cursor:pointer;min-height:44px;
  text-decoration:none;display:flex;align-items:center}
.chip[aria-pressed="true"],.chip.on{border-color:var(--teal);
  background:var(--teal-wash);color:var(--teal)}
.reveal{width:100%;background:transparent;border:1px dashed var(--rule);
  color:var(--ink3);padding:12px;border-radius:3px;font-size:13px;cursor:pointer;
  font-family:var(--sans)}

/* ---- detail + list layouts ------------------------------------------ */
.detail-grid{display:block}
@media (min-width:1024px){
  .detail-grid{display:grid;grid-template-columns:1fr 340px;
    grid-template-rows:auto auto auto auto;
    column-gap:32px;row-gap:0;
    align-items:start;padding:0 20px}
  .detail-main{grid-column:1;grid-row:1;min-width:0}
  .sidebar{grid-column:2;grid-row:1/-1}
  .office-slot{grid-column:1;grid-row:2;min-width:0}
  .detail-pre{grid-column:1;min-width:0}
  .detail-post{grid-column:1;min-width:0}
  .sidebar .ask.sec{padding:24px 0 8px}
}
.detail-pre:empty,.detail-post:empty{display:none}
.sidebar{display:none}
@media (min-width:1024px){.sidebar{display:block;position:sticky;top:88px}}
@media (max-width:1023px){
  .clinic-detail-grid{display:flex;flex-direction:column}
  .clinic-detail-grid .detail-main{order:1}
  .clinic-detail-grid .office-slot{order:2}
  .clinic-detail-grid .detail-pre{order:3}
  .clinic-detail-grid .sidebar{display:block;position:static;order:4}
  .clinic-detail-grid .sidebar .map,
  .clinic-detail-grid .sidebar > .btn-call{display:none}
  .clinic-detail-grid .detail-post{order:5}
}
/* The call bar: the one place the accent colour appears. */
.callbar{position:sticky;bottom:0;left:0;right:0;background:var(--panel);
  border-top:1px solid var(--rule);
  padding:14px 20px calc(14px + env(safe-area-inset-bottom))}
@media (min-width:1024px){.callbar{display:none}}
.btn-call{display:block;text-align:center;background:var(--wax);color:#fff;
  padding:16px;border-radius:var(--r);font:700 18px var(--mono);
  text-decoration:none;letter-spacing:.02em}
.callbar .btn-call{padding:15px}
.has-callbar{padding-bottom:88px;position:relative}
@media (min-width:1024px){.has-callbar{padding-bottom:0}}

/* ---- home ------------------------------------------------------------ */
/* The hero runs edge to edge over a photograph with a scrim on top, so its
   text is white on a dark ground in both themes — the one place on the site
   where the palette does not follow the theme, because the image underneath
   does not either. */
.hero{position:relative;overflow:hidden;isolation:isolate}
.hero-pic{position:absolute;inset:0;z-index:-2}
.hero-bg{width:100%;height:100%;object-fit:cover;object-position:50% 52%;display:block}
/* Two stacked gradients rather than one. The photograph is bright everywhere —
   its mean luminance is 176 and the brightest tenth reaches 229 — so there is
   no dark corner to hide text in, and a single scrim heavy enough to carry the
   text would flatten the whole image.

   The horizontal layer holds its full weight to 48% and is spent by 85%. That
   is not arbitrary: the light text ends at 54% of the hero (the hint is the
   widest line; the search button past it is dark-on-white and needs no help),
   so everything beyond that can be given back to the photograph. Holding the
   plateau until the text ends and then falling steeply is what buys the right
   of the frame its brightness — mean luminance 90 against 76 for a scrim that
   fades gradually from the left edge. The fall is spread over 37% rather than
   dumped in 3%: the steepest ramp that still passed contrast banded visibly.

   The vertical layer is now slight, doing little more than seating the search
   field. Measured against the brightest pixel under each string, the tightest
   margin is 1.49 above its threshold. */
.hero-scrim{position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    linear-gradient(90deg,rgba(8,18,22,.66) 0%,rgba(8,18,22,.62) 48%,
                          rgba(8,18,22,.32) 66%,rgba(8,18,22,.08) 85%,
                          rgba(8,18,22,0) 100%),
    linear-gradient(180deg,rgba(10,22,26,.18),rgba(10,22,26,.22))}
@media (max-width:1023px){
  /* Narrow viewports run the text the full width, so there is no half of the
     frame to give back and a single even wash is the whole story. This one
     cannot be lightened further: the 11px eyebrow sits over the ceiling, the
     brightest band in the phone crop, and it is what caps the value. */
  .hero-scrim{background:
    linear-gradient(180deg,rgba(8,19,23,.71),rgba(8,19,23,.75))}}
@media (max-width:640px){
  /* A phone crops the frame to a narrow column, and at the default centre that
     column is the wall-mounted X-ray display — the busiest, brightest object in
     the room, sitting directly behind the headline. Contrast still passes there;
     it just reads badly. Shifting away from it lands on the chair and the
     instrument tray instead, which say "dentist" more plainly than a mouth of
     teeth does. (Mirrored with the image: this tracks MIRROR in build_hero.py.) */
  .hero-bg{object-position:34% 52%}}
.hero-in{position:relative;padding:64px 20px 48px;max-width:44rem}
@media (min-width:1024px){.hero-in{padding:104px 20px 88px}}

.hero .eyebrow.teal{color:#A5E2EA}
.hero h1.big{color:#fff;text-shadow:0 1px 2px rgba(6,16,20,.38)}
/* Raised from .84/.66/.65, which were tuned against the old dark illustration
   and fell to 2.5:1 and 1.5:1 over a photograph, then again to pay for the
   lighter scrim. Size still carries the hierarchy, so the near-white hint does
   not compete with the lede. */
.hero .lede{margin:0 0 32px;font-size:17px;line-height:1.6;
  color:rgba(255,255,255,.92);max-width:38ch;text-shadow:0 1px 2px rgba(6,16,20,.34)}
.hero .search{border-bottom-color:#fff}
.hero .search input{color:#fff}
.hero .search input::placeholder{color:rgba(255,255,255,.72)}
.hero .geo-btn{color:#8FD9E3}
.hero .search-go{background:#fff;color:#14232B}
.hero .hint{margin:0;color:rgba(255,255,255,.85)}

.lede{margin:0 0 32px;font-size:17px;line-height:1.6;color:var(--ink2);max-width:38ch}
.search{display:flex;align-items:flex-end;gap:12px;border-bottom:2px solid var(--ink);
  padding-bottom:12px;margin-bottom:14px}
.search input{flex:1;min-width:0;border:none;outline:none;background:transparent;
  font:400 19px var(--serif);color:var(--ink);padding:4px 0}
.search input::placeholder{color:var(--ink3)}
.geo-btn{flex:0 0 auto;background:transparent;border:none;color:var(--teal);
  cursor:pointer;padding:6px;display:flex;align-items:center;min-width:44px;min-height:44px}
.search-go{flex:0 0 auto;background:var(--ink);color:var(--bg);padding:11px 22px;
  border-radius:3px;font:600 13px var(--sans);letter-spacing:.06em;
  text-transform:uppercase;text-decoration:none;white-space:nowrap;border:none;
  cursor:pointer;min-height:44px}
.hint{margin:0 0 32px;font-size:12px;color:var(--ink3)}

.entries{display:block;border-top:1px solid var(--rule)}
@media (min-width:640px){.entries{display:grid;grid-template-columns:1fr 1fr;gap:0}}
.entry{display:flex;align-items:center;justify-content:space-between;gap:16px;
  text-decoration:none;color:inherit;padding:26px 20px;
  border-bottom:1px solid var(--rule)}
@media (min-width:640px){.entry+.entry{border-left:1px solid var(--rule)}}
.entry-name{display:block;font:500 21px/1.3 var(--serif);color:var(--ink);
  margin-bottom:6px}
.entry-count{display:block;font:500 11px var(--sans);letter-spacing:.08em;
  text-transform:uppercase;color:var(--teal)}
.entry-arrow{font:400 22px var(--serif);color:var(--teal)}

.more{display:flex;align-items:center;gap:8px;width:100%;padding:18px 0;
  font:500 13px var(--sans);letter-spacing:.02em;color:var(--teal);text-decoration:none}

.colgrid{display:grid;grid-template-columns:1fr 1fr;gap:2px 24px}
@media (min-width:640px){.colgrid{grid-template-columns:1fr 1fr 1fr}}
@media (min-width:1024px){.colgrid{grid-template-columns:repeat(4,1fr)}}

.taglist{display:flex;flex-wrap:wrap;gap:8px 20px}
.taglist a{font:500 15px var(--serif);color:var(--teal);text-decoration:none}

/* ---- prose (about, methodology, legal) ------------------------------ */
.prose{padding:8px 20px 24px;max-width:70ch}
.prose h2{margin:34px 0 14px;font:600 11px var(--sans);letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink3);
  padding-bottom:14px;border-bottom:1px solid var(--rule)}
.prose h3{margin:22px 0 10px;font:500 21px/1.3 var(--serif);color:var(--ink)}
.prose p,.prose li{font-size:15.5px;line-height:1.7;color:var(--ink2)}
.prose strong{color:var(--ink)}
.prose table{border-collapse:collapse;width:100%;font-size:14px;margin:16px 0}
.prose th,.prose td{text-align:left;padding:9px 12px 9px 0;
  border-bottom:1px solid var(--rule);vertical-align:top}
.prose th{font:600 10.5px var(--sans);letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink3)}
.scroll{overflow-x:auto}

/* ---- guides: long reads want real headings, not the label style ------ */
.prose.guide h2{margin:40px 0 12px;padding:0;border:0;font:500 26px/1.25 var(--serif);
  letter-spacing:0;text-transform:none;color:var(--ink);scroll-margin-top:16px}
.prose.guide ol li{margin-bottom:6px}
.prose .answer{margin:20px 0;padding:16px 18px;border-left:3px solid var(--teal);
  background:var(--teal-wash)}
.prose .answer p{margin:0;color:var(--ink)}
.prose .toc{margin:24px 0 8px;padding:14px 0;border-top:1px solid var(--rule);
  border-bottom:1px solid var(--rule)}
.prose .toc p{margin:0 0 8px;font:600 11px var(--sans);letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink3)}
.prose .toc ol{margin:0;padding-left:20px}
.prose .toc li{font-size:14.5px;line-height:1.6}
.prose .toc a{color:var(--teal)}

/* ---- footer ---------------------------------------------------------- */
.site-foot{background:var(--bg);border-top:1px solid var(--rule);margin-top:56px;
  padding:56px 20px 32px}
.foot-grid{display:grid;grid-template-columns:1fr;gap:32px;margin-bottom:48px;
  align-items:start}
@media (min-width:640px){.foot-grid{grid-template-columns:1fr 1fr;gap:24px}}
@media (min-width:960px){.foot-grid{grid-template-columns:1fr 1fr 1fr 1fr}}
.foot-col p{margin:0 0 18px;font:600 11px var(--sans);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink)}
.foot-links{display:flex;flex-direction:column;gap:13px}
.foot-links a{font-size:14.5px;color:var(--ink2);text-decoration:none}
.foot-links a:hover{color:var(--teal)}
.foot-base{border-top:1px solid var(--rule);padding-top:22px}
.foot-base p{margin:0;font-size:12.5px;color:var(--ink3)}

/* ---- accessibility --------------------------------------------------- */
a:focus-visible,button:focus-visible,input:focus-visible{
  outline:2px solid var(--teal);outline-offset:2px}
.skip{position:absolute;left:-9999px;top:0;background:var(--panel);color:var(--ink);
  padding:12px 16px;z-index:10}
.skip:focus{left:0}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* ---- search results --------------------------------------------------- */
.sr-group{margin:0 0 28px}
.sr-group h2{margin:0 0 12px;font:600 11px var(--sans);letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink3);padding-bottom:14px;
  border-bottom:1px solid var(--rule)}
.sr-place{display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  text-decoration:none;color:inherit;padding:16px 0;border-bottom:1px solid var(--rule)}
.sr-place b{font:500 20px var(--serif);color:var(--ink);font-weight:500}
.sr-empty{font-size:15px;color:var(--ink2)}
.sr-busy{font-size:14px;color:var(--ink3)}

/* The result type is an axis the reader chooses, not three stunted lists. Both
   counts are always shown, so picking one never makes the other look empty. */
.sr-tabs{display:flex;gap:4px;margin:0 0 4px;border-bottom:1px solid var(--rule)}
.sr-tab{display:inline-flex;align-items:baseline;gap:8px;padding:11px 14px;
  background:none;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;
  font:600 12px var(--sans);letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink3);cursor:pointer}
.sr-tab:hover:not(:disabled){color:var(--ink)}
.sr-tab.on{color:var(--teal);border-bottom-color:var(--teal)}
.sr-tab:disabled{opacity:.45;cursor:default}
.sr-n{font:500 11px var(--sans);letter-spacing:.02em;text-transform:none;color:var(--ink3)}
.sr-tab.on .sr-n{color:var(--teal)}

/* "Showing 10 of 4,123" — the sentence whose absence was the whole problem. */
.sr-count{margin:14px 0 4px;font:500 12px var(--sans);letter-spacing:.04em;color:var(--ink3)}
.sr-list .row:last-child{border-bottom:0}
.sr-more{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;
  padding:14px;margin-top:8px;background:none;border:1px solid var(--rule);
  border-radius:var(--r);font:600 12px var(--sans);letter-spacing:.06em;
  text-transform:uppercase;color:var(--teal);cursor:pointer}
.sr-more:hover{border-color:var(--teal);background:var(--teal-wash)}

/* How the query was understood, and the way out of it. */
.sr-read{margin:0 0 12px;font-size:13.5px;color:var(--ink2)}
.sr-read b{color:var(--ink);font-weight:600}
.sr-read a{color:var(--teal)}
.sr-dist{display:inline-block;margin-right:8px;font:600 11px var(--sans);
  letter-spacing:.04em;color:var(--teal)}
.sr-radius{margin:0 0 14px;font-size:13px;color:var(--ink2)}
.sr-rad{padding:4px 9px;margin:0 2px;background:none;border:1px solid var(--rule);
  border-radius:3px;font:600 11px var(--sans);color:var(--ink2);cursor:pointer}
.sr-rad.on{border-color:var(--teal);background:var(--teal-wash);color:var(--teal)}
.sr-geo{display:inline-block;width:auto;margin-left:6px;padding:8px 14px}

/* When the exact question is honestly empty, the nearest real answers. */
.sr-widen{display:flex;flex-direction:column;gap:8px;margin-top:12px}
.sr-wide{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:13px 14px;background:none;border:1px solid var(--rule);border-radius:var(--r);
  font:600 12px var(--sans);letter-spacing:.05em;text-transform:uppercase;
  color:var(--teal);cursor:pointer;text-align:left}
.sr-wide:hover{border-color:var(--teal);background:var(--teal-wash)}

/* The compass mark inherits currentColor, so it is ink in light mode and
   enamel in dark without a second asset. */
.mark-glyph{flex:0 0 24px;color:var(--teal)}
.site-foot .mark-glyph{color:var(--teal)}

/* ---- pagination ------------------------------------------------------- */
/* `.pg-of` is a caption and takes its own line, which is what the wrap on this
   container is for. What must never break across lines is the run of page
   numbers, so the nowrap lives on `.pg-nums` — putting it here instead left the
   caption nowhere to go and pushed it off the side of the phone. */
.pager{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:6px;
  padding:20px 0 8px;border-top:1px solid var(--rule);margin-top:8px}
.pg{display:inline-flex;align-items:center;justify-content:center;min-width:44px;
  min-height:44px;padding:0 12px;border:1px solid var(--rule);border-radius:3px;
  background:var(--panel);color:var(--ink2);text-decoration:none;
  font:600 13px var(--sans)}
.pg:hover{border-color:var(--teal);color:var(--teal)}
.pg.num{padding:0 10px}
.pg.num.on{background:var(--ink);border-color:var(--ink);color:var(--bg)}
.pg-nums{display:flex;flex-wrap:nowrap;flex-shrink:0;gap:6px;align-items:center}
/* Too narrow for numbers at all: Previous, Next and the caption say everything
   the numbers would, and nothing has to fold onto a second line to fit. */
@media (max-width:560px){.pg-nums{display:none}}
.pg-gap{color:var(--ink3);padding:0 2px}
.pg-of{width:100%;margin:10px 0 0;text-align:center;font:500 11px var(--sans);
  letter-spacing:.08em;text-transform:uppercase;color:var(--ink3)}

/* ---- dentist cards ---------------------------------------------------- */
/* Three across on a desktop, five rows to a page. A dentist card holds less
   than a clinic card — name, credentials, city — so a two-up grid left half
   the row empty. */
.cards.three{display:block}
@media (min-width:768px){.cards.three{display:grid;grid-template-columns:1fr 1fr;gap:14px}}
@media (min-width:1024px){.cards.three{grid-template-columns:repeat(3,1fr)}}

/* Someone scanning this list is looking for a person, so the name is the
   loudest thing on the card and the credentials recede under it. */
.dcard .card-name{font:600 22px/1.25 var(--serif);letter-spacing:-.01em;margin-bottom:6px}
.dcard .card-meta{font:600 10px var(--sans);letter-spacing:.07em;margin-bottom:6px}
.dcard .card-line{font-size:13px;color:var(--ink3)}

/* The brand mark is a single-colour tooth in #25646F. That reads at 6.06:1 on
   the light ground but only 2.71:1 on the dark one — under the 3:1 minimum for
   a non-text graphic. Rather than ship a second file, the dark theme brightens
   the one we have to roughly the lightness of --teal in that theme. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) img.mark-glyph{filter:brightness(1.9)}
}
:root[data-theme="dark"] img.mark-glyph{filter:brightness(1.9)}

/* ============================================================ maps ==== */
/* One definition per selector, in one place. Everything about maps used to be
   spread across four appended blocks, and three bugs came out of the later
   copy quietly beating the earlier one at equal specificity. */

.map{background:var(--teal-wash);border-radius:var(--r);overflow:hidden;padding:0}
.map iframe,.map>div,.leaflet-container{width:100%;height:100%;border:0;display:block}
.map-note{position:absolute;left:0;right:0;bottom:0;z-index:2;
  background:var(--panel);color:var(--ink2);font:400 11.5px var(--sans);
  padding:6px 10px;text-align:center;border-top:1px solid var(--rule)}
.map-pop{font:400 13px var(--sans)}
.map-pop a{color:var(--teal)}

/* Detail page: one location, inline on a phone and in the sidebar above the
   call button on a desktop. */
.map-inline{height:180px;margin:0 20px 20px;position:relative}
@media (min-width:1024px){.map-inline{display:none}}
.sidebar .map{height:200px;margin-bottom:16px;position:relative}

/* List page: a single map, below the cards on a phone and pinned beside them
   on a desktop. */
.list-grid{display:block;padding:0 20px}
.map-col{margin:20px 0 0}
.map-col .map{height:clamp(240px,42vh,360px)}

@media (min-width:1024px){
  .list-grid{display:grid;grid-template-columns:1fr 380px;gap:32px;
    /* stretch, not start: the map column must be as tall as the list or the
       sticky map has nowhere to travel. */
    align-items:stretch}
  .map-col{margin:0;height:100%}
  /* The wrapper is what sticks. Google Maps writes position:relative inline
     onto the element it takes over, and an inline style outranks any rule
     here — so the library never owns the positioned box. */
  .map-sticky{position:sticky;top:24px}
  .map-col .map{height:clamp(360px,62vh,560px)}
}

/* ---- row lists in columns -------------------------------------------- */
/* A run of .row links is one tall column on a phone, which is right, and was
   still one tall column at 1120px, which read as an unfinished mobile layout.
   The count is per list: 56 states and 138 cities want three, a mixed run of
   clinic names wants two so the names have room. */
.rows{display:block}
@media (min-width:768px){
  .rows.c2,.rows.c3{display:grid;grid-template-columns:1fr 1fr;column-gap:36px}
}
@media (min-width:1024px){
  .rows.c3{grid-template-columns:repeat(3,1fr);column-gap:32px}
}
/* Each cell keeps its own rule, so the columns read as lists rather than as a
   table with a ragged bottom edge. */
.rows .row{border-bottom:1px solid var(--rule)}

/* The section after a results grid was butting straight into the pagination.
   32px of section padding reads as ample between two text blocks and as almost
   nothing under a list that has just ended with a row of buttons. */
.list-grid + .sec{padding-top:52px}

/* ---- list controls ---------------------------------------------------- */
/* Filters are <details> disclosures holding ordinary links, not <select>s: a
   select needs script to navigate and hides its targets from a crawler, and
   these targets are pre-rendered pages that only get indexed because something
   links to them. */
.controls{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:0 20px 18px}
.fgroup{position:relative;flex:0 0 auto}
.fgroup>summary{display:flex;align-items:center;gap:8px;min-height:44px;
  padding:8px 14px;border:1.5px solid var(--rule);border-radius:3px;
  background:var(--panel);cursor:pointer;list-style:none;user-select:none}
.fgroup>summary::-webkit-details-marker{display:none}
.fgroup>summary::after{content:"";width:7px;height:7px;margin-left:2px;
  border-right:1.5px solid var(--ink3);border-bottom:1.5px solid var(--ink3);
  transform:rotate(45deg) translate(-2px,-2px)}
.fgroup[open]>summary{border-color:var(--teal)}
.fgroup-k{font:600 10.5px var(--sans);letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink3)}
.fgroup-v{font:500 14px var(--serif);color:var(--ink)}
.fpanel{position:absolute;z-index:30;top:calc(100% + 6px);left:0;min-width:270px;
  max-width:min(88vw,360px);max-height:min(58vh,420px);overflow-y:auto;
  background:var(--panel);border:1px solid var(--rule);border-radius:4px;
  padding:6px;box-shadow:0 12px 34px rgba(0,0,0,.22)}
.fopt{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:10px 12px;border-radius:3px;font-size:14.5px;color:var(--ink2);
  text-decoration:none;min-height:44px}
.fopt:hover{background:var(--teal-wash);color:var(--teal)}
.fopt.on{color:var(--teal);font-weight:600;background:var(--teal-wash)}
.fopt-n{flex:0 0 auto;font:500 11px var(--sans);letter-spacing:.06em;color:var(--ink3)}
.fopt.on .fopt-n{color:var(--teal)}

/* The location control sits at the end of the row, away from the filters —
   it does something different in kind: the filters navigate to a page that
   exists, this one asks the browser where you are. */
.nearbtn{margin-left:auto;flex:0 0 auto;white-space:nowrap;gap:7px}
.nearbtn:disabled{opacity:.6;cursor:default}
.nearbtn.on{border-color:var(--teal);background:var(--teal-wash);color:var(--teal)}
@media (max-width:560px){.nearbtn{margin-left:0}}

/* Says what the filter means before the reader draws the wrong conclusion
   from it, so it sits above the results rather than under them. */
.scopenote{margin:0 20px 16px;padding:12px 14px;border-left:2px solid var(--teal);
  background:var(--teal-wash);border-radius:0 3px 3px 0;
  font-size:13.5px;line-height:1.6;color:var(--ink2);max-width:70ch}
.scopenote a{color:var(--teal)}

/* ---- in-page pagination ----------------------------------------------- */
/* The rows above it already end on a rule, so this pager drops the border the
   list pagers need. Buttons rather than links, because there is no URL to go
   to — .pg carries the appearance either way. */
.rowpager{border-top:none;margin-top:0;padding-top:14px}
.rowpager .pg{font-family:var(--sans)}
.rowcount{margin:-6px 0 12px;font:500 11px var(--sans);letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink3)}
/* Focus is moved here on page change; it should read as a destination, not
   look like a clicked control. */
.rowpage .row:focus{outline:2px solid var(--teal);outline-offset:-2px}

/* ---- Google Places (preview only) -------------------------------------- */
/* Score and sample size read as one unit, so they are sized as one: the count
   in grey 11px under a large number is how a directory ends up implying that
   5.0 from two people beats 4.1 from three hundred. */
.ratebar{display:flex;align-items:baseline;gap:6px;margin:10px 0 0}
.rate-n{font:500 20px var(--serif);color:var(--ink);line-height:1}
.rate-count{font:400 15px var(--serif);color:var(--ink2);line-height:1}
