@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css');

/* ==========================================================================
   OOI Dental · Design System  ·  v2.0
   Built on the client's Brand Identity doc: "Nature Inspired Digital
   Dentistry". Ocean Blue and Nature Green carry the brand, warm neutrals
   carry the surface, Forest Evergreen is the ink and the footer, and
   Champagne Gold is the signature at under 5% of the page.

   Every spec colour is used at its exact published value wherever the
   contrast maths allows it. Four places it does not, and each has a
   same-hue darkened partner instead; those four are the only deviations
   and every one is labelled below with its measured ratio.

   Typography follows the same doc: Playfair Display display + headings,
   Inter body and UI. Fonts load via <link> in each page head, not
   @import, so they download in parallel with this stylesheet.
   ========================================================================== */

:root {
  /* ---- Brand colours · exact spec values ---- */
  --ocean:          #2E8FE6;   /* Ocean Blue   · trust, technology       */
  --nature:         #8DB44A;   /* Nature Green · healing, growth         */
  --forest:         #2F4B3A;   /* Forest Evergreen · footer, premium     */
  --gold:           #C8A76A;   /* Champagne Gold · signature only, <=5%  */
  /* Footer navy · not in the brand doc's palette, added 2026-08-07 on
     Kelvin's call to match the client's footer comp. This exact value was
     chosen because it is the only dark the wordmark can sit on directly:
     the mark's grey Chinese lockup measures 3.02:1 here versus 2.03:1 on
     Forest Evergreen, which is why the logo needed a white plate before. */
  --navy:           #1E2B3C;

  /* ---- Neutrals · exact spec values ---- */
  --paper:          #FAF8F3;   /* Warm White  · main background          */
  --card:           #F5F1EA;   /* Soft Cream  · cards                    */
  --sand:           #ECE6DA;   /* Sand        · sections                 */
  --oak:            #C7A87A;   /* Natural Oak · wood                     */
  --stone:          #DCCDB7;   /* Warm Stone  · secondary neutral        */

  /* ---- The four working variants ----
     Same hue as their spec parent, walked down in lightness only until
     text on them clears WCAG AA. Measured, not guessed:
       ocean  #2E8FE6 behind white type = 3.39:1  -> fails AA body
       ocean  #2E8FE6 as type on paper  = 3.18:1  -> fails AA body
       nature #8DB44A behind white type = 2.42:1  -> fails everything
       oak    #C7A87A as type on paper  = 1.98:1  -> fails everything
     They stay exact wherever they are a graphic, a fill or a background. */
  --ocean-fill:     #2478CC;   /* white type on this = 4.54:1 */
  --ocean-type:     #1F73C4;   /* as link type on paper = 4.79:1 */
  --nature-fill:    #5F7A2E;   /* white type on this = 4.88:1 */
  /* ---- Hero headline · sampled from the logo file itself ----
     The mark's own blue is #33A0D9 (hue 201) and its green is #A3C646
     (hue 76). Neither is the brand doc's Ocean/Nature, and neither can be
     used as type: on paper they measure 2.76:1 and 1.85:1, both under the
     3:1 large-text floor. The two -type values hold the mark's exact hue and
     drop only in value until the headline is legible.
     Saturation goes to full rather than staying at the mark's own: at a fixed
     contrast target a more saturated colour keeps more of its value, so the
     blue lands at value .84 against the mark's .85, and the green stays a
     live green instead of turning olive. Same hue either way. */
  --logo-blue:      #33A0D9;   /* the mark, unaltered */
  --logo-green:     #A3C646;   /* the mark, unaltered */
  --logo-blue-type: #008DD6;   /* hue 201 · as display type on paper = 3.42:1 */
  /* 2026-08-21 Kelvin's call, twice reaffirmed with the contrast maths on the
     table: display headlines use the logo wordmark green EXACTLY as rendered
     in the header (#A3C646). This is below the 3:1 large-text floor -
     a deliberate brand-matching decision, not an oversight. Small text and
     links keep the compliant tokens below. */
  --logo-green-type:#A3C646;
  /* Service card panels and the link colour that works on them. The titles
     run at the -type values (3.23:1 and 3.34:1 at 24px, over the large-text
     floor); "Learn more" is 16px so it needs 4.5:1 and takes a step down. */
  --tint-blue:      #EAF3FB;
  --tint-green:     #F2F4E8;
  --logo-blue-link: #0074B0;   /* on --tint-blue  = 4.54:1 */
  --logo-green-link:#577800;   /* on --tint-green = 4.61:1 */
  --oak-type:       #7A5E33;   /* as type on paper = 5.66:1 */

  /* ---- Ink · Forest Evergreen doubles as the text colour, which is why
     the footer is simply the ink at full bleed ---- */
  --ink:            #2F4B3A;   /*  9.10:1 on paper · 7.82:1 on sand */
  --ink-deep:       #24392C;
  --ink-70:         #3F5A4A;   /*  7.03:1 on paper */
  --muted:          #55665C;   /*  5.70:1 on paper · 4.90:1 on sand */

  /* ---- Surface aliases used by the components ---- */
  --cream:          var(--paper);
  --white:          #FFFFFF;
  --surface:        var(--card);
  --wood-100:       var(--card);
  --wood-200:       var(--sand);
  --wood-300:       var(--stone);
  --wood-400:       var(--oak);
  --wood-500:       var(--oak);
  --wood-700:       var(--oak-type);
  --line:           #E3DACB;
  --lime:           var(--stone);
  --lime-soft:      var(--card);
  --blue-soft:      var(--card);
  --blue:           var(--ocean);
  --green:          var(--nature);

  /* Shape */
  --r-xl: 24px;
  --r-lg: 20px;
  --r-md: 16px;
  --r-sm: 12px;
  --r-pill: 999px;

  /* Layout */
  --container: 1280px;
  --pad: 80px;
  --gutter: 20px;

  /* Type · Playfair Display display face, Inter text face */
  --font:         'Inter', 'Noto Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-display: 'Playfair Display', 'Noto Serif SC', Georgia, 'Times New Roman', serif;

  /* The brand doc specifies a 64px hero. That figure assumes a full-width
     headline; in this two-column hero "Restoring Function." would break
     mid-phrase at 64px, so the ceiling is 56px and the line holds. */
  --fs-display: clamp(2.375rem, 3.7vw, 3.5rem);  /* hero      · 38 → 56 */
  --fs-h1:      clamp(2.25rem, 3.6vw, 3rem);     /* page h1   · 36 → 48 */
  /* h2 ladder, ratio 1.26. Eleven separate clamps had accumulated here and
     rendered as four different h2 sizes on desktop and five on mobile, which
     is drift rather than hierarchy. Three steps, each a real jump. */
  --fs-h2-xl:   clamp(2.125rem, 3.4vw, 3rem);    /* statement · 34 → 48 */
  --fs-h2:      clamp(1.6875rem, 2.9vw, 2.375rem); /* section · 27 → 38 */
  --fs-h2-md:   clamp(1.375rem, 2.3vw, 1.875rem); /* in-card  · 22 → 30 */
  --fs-h3:      clamp(1.375rem, 2.1vw, 1.75rem); /* card      · 22 → 28 */
  --fs-lead:    clamp(1.0625rem, 1.4vw, 1.25rem);
  --fs-body:    1.125rem;                        /* 18 · older patients read this site */
  --fs-small:   1rem;                            /* 16 */
  --fs-caption: 0.875rem;                        /* 14 */
  --fs-kicker:  0.8125rem;

  /* Motion */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --t-micro: 160ms;
  --t-base: 280ms;

  /* Elevation · kept almost flat, depth comes from background steps */
  --shadow-card: 0 1px 2px rgba(47, 75, 58, .05), 0 8px 24px rgba(47, 75, 58, .07);
  --shadow-lift: 0 2px 4px rgba(47, 75, 58, .07), 0 18px 40px rgba(47, 75, 58, .13);

  /* Nav 占位高：胶囊 72 + 悬浮量。首屏区块用它把内容让出来，
     背景（照片/底色）则上探到屏幕顶，胶囊浮在上面。 */
  --nav-float: clamp(14px, 2.4vw, 36px);
  --nav-block: calc(72px + var(--nav-float));

  /* z-index scale */
  --z-sticky: 200;
  --z-float: 300;
}

/* ---------- 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;
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--ink);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;   /* 不用 hidden：hidden 生成滚动容器会弄坏 sticky nav */
}

img, svg { max-width: 100%; display: block; }
img { object-fit: cover; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }

/* Playfair is a high-contrast didone. It wants air, not the tight tracking
   a grotesk can take, so letter-spacing stays near zero and never below
   -0.02em. Weight 600 across headings, 700 reserved for the hero. */
h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -0.012em;
  text-wrap: balance;
}
h4 {
  margin: 0;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
h1 { font-size: var(--fs-display); font-weight: 700; line-height: 1.06; letter-spacing: -0.02em; }
h2 { font-size: var(--fs-h2); line-height: 1.12; }
h3 { font-size: var(--fs-h3); line-height: 1.2; }
p  { margin: 0; text-wrap: pretty; }

/* Numerals set in the display face: the stats read as part of the voice
   rather than as a dashboard readout. */
.num-display {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
  font-variant-numeric: lining-nums;
}

:focus-visible {
  outline: 3px solid var(--ocean-type);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------- Icons ----------
   Outline, rounded, thin line, per the brand doc's Icon Style. Drawn from
   the Lucide set (ISC) plus one house-drawn tooth, which Lucide has no
   equivalent for. Stroke, never fill, so they inherit the text colour. */
.ico {
  width: 1em;
  height: 1em;
  flex: none;
  display: inline-block;
  vertical-align: -0.125em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.skip-link {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--white);
  padding: 12px 20px; border-radius: 0 0 var(--r-sm) 0; z-index: 999;
}
.skip-link:focus { left: 0; }

/* ---------- Layout primitives ---------- */
.container {
  width: 100%;
  max-width: calc(var(--container) + var(--pad) * 2);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.section { padding-block: clamp(64px, 8vw, 120px); }
/* 同底色相邻区不叠双倍内距（2026-08-28 Kelvin：FAQ→CTA 空档过大） */
.section--cream + .section--cream { padding-top: clamp(8px, 1.5vw, 20px); }
.section--cream { background: var(--sand); }
.section--white { background: var(--paper); }
.section--ink   { background: var(--forest); color: var(--paper); }

.stack-sm > * + * { margin-top: 12px; }
.stack   > * + * { margin-top: 20px; }
.stack-lg > * + * { margin-top: 32px; }

.lead {
  font-size: var(--fs-lead);
  color: var(--muted);
  max-width: 62ch;
}
.section--ink .lead { color: rgba(250, 248, 243, .84); }

.muted { color: var(--muted); }
.center { text-align: center; }

/* Section head: title left, supporting copy right */
.sec-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--gutter) 60px;
  align-items: end;
  margin-bottom: clamp(32px, 4vw, 56px);
}
.sec-head--center {
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
}
.sec-head--center .lead { text-align: center; }

.kicker {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-kicker);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  margin-bottom: 14px;
}
.kicker i { color: var(--wood-700); font-size: 0.8em; }
.kicker .ico { color: var(--nature-fill); width: 1.15em; height: 1.15em; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 52px;
  padding: 0 26px;
  border: 2px solid transparent;
  border-radius: var(--r-pill);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: -0.01em;
  transition: transform var(--t-micro) var(--ease),
              background-color var(--t-micro) var(--ease),
              color var(--t-micro) var(--ease),
              border-color var(--t-micro) var(--ease);
}
.btn i { font-size: 0.9em; }
.btn .ico { width: 1.15em; height: 1.15em; }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

/* Ocean Blue is the button colour per the brand doc. The fill is the
   darkened partner because white type on the published #2E8FE6 measures
   3.39:1, under the 4.5:1 body-text floor. */
.btn--primary { background: var(--ocean-fill); color: #fff; }
.btn--primary:hover { background: #1F6BB5; }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--paper); }

.btn--lime { background: var(--nature); color: var(--forest); }
.btn--lime:hover { background: #7FA33F; }

.btn--onink { background: var(--paper); color: var(--forest); }
.btn--onink:hover { background: #fff; }

.btn--block { width: 100%; }

@media (prefers-reduced-motion: reduce) {
  .btn:hover { transform: none; }
}

/* ---------- Icon chip sizing ----------
   Each swapped <svg class="ico"> is the chip itself, so the box size and
   the inset both live here rather than on a wrapper. */
.hero-feats .ico     { width: 44px; height: 44px; padding: 11px; }
.promise-list .ico   { width: 30px; height: 30px; padding: 6px; stroke-width: 2; }
.ticks .ico          { width: 28px; height: 28px; padding: 6px; stroke-width: 2; }
.faq-q .ico          { width: 36px; height: 36px; padding: 9px; }
.branch dt .ico      { width: 18px; height: 18px; }
.value-mark .ico     { width: 23px; height: 23px; }
.voice-avatar .ico   { width: 20px; height: 20px; }
.nav-toggle .ico     { width: 22px; height: 22px; }
.ph .ico             { width: 28px; height: 28px; margin: 0 auto 10px; }
.tbd .ico            { width: 15px; height: 15px; }
.svc-list .arrow .ico { width: 20px; height: 20px; }
.branch-rating .ico  { width: 16px; height: 16px; }

/* ---------- Navbar ---------- */
/* Floating pill navbar (2026-08-20, per client reference premierartsdental.com).
   Detached from the top edge, fully rounded, frosted. Kept in our own
   language: translucent paper + forest ink, not the reference's colours.
   The bar is the sticky element; the pill is its inner container, so the
   services mega-menu (absolute inside) can still escape without clipping. */
.nav {
  /* Measured off the live reference at 1512px: top 36, side inset 116
     (7.7vw), pill 72 tall, logo 48. Scaled with clamp so phones keep
     sane margins. */
  position: sticky; top: 0; z-index: var(--z-sticky);
  /* 2026-08-21 定案：胶囊保留悬浮量，「贴顶」的是背后的首屏照片 ——
     负 margin 让下一个区块钻到 nav 背后，photo 自然到达屏幕顶。
     贴顶动作走 transform（不触发 reflow），--p 丝滑机制不变。 */
  padding-top: var(--nav-float);
  padding-inline: calc(clamp(14px, 7.6vw, 116px) * (1 - var(--p, 0)));
  margin-bottom: calc(-1 * var(--nav-block));
  transform: translateY(calc(var(--nav-float) * -1 * var(--p, 0)));
  background: none;
}
.nav .container {
  max-width: none;
  min-height: 72px;
  transition: transform 380ms var(--ease);
  display: flex;
  align-items: center;
  gap: 24px;
  padding-left: clamp(18px, 2vw, 28px);
  padding-right: clamp(12px, 1.5vw, 20px);
  /* 胶囊 72px 高时全圆角的有效半径 = 36px，从 36 插值到 0 */
  border-radius: calc(36px * (1 - var(--p, 0)));
  background: rgb(250 248 243 / calc(0.82 + 0.18 * var(--p, 0)));
  -webkit-backdrop-filter: blur(calc(14px * (1 - var(--p, 0))));
  backdrop-filter: blur(calc(14px * (1 - var(--p, 0))));
  border: 1px solid rgb(227 218 203 / calc(0.7 * (1 - var(--p, 0))));
  border-bottom-color: rgb(227 218 203 / calc(0.7 + 0.3 * var(--p, 0)));
  box-shadow: 0 10px 34px rgb(47 75 58 / calc(0.10 * (1 - var(--p, 0))));
}
/* Scrolled state is fully driven by --p (scroll progress, see scripts).
   .is-stuck remains as a hook only; no geometry lives here anymore. */
/* Page content must start below the bar plus its 12px float gap; the body's
   first section already has its own padding, so only the hero needs care.
   The bar overlaps content by design when floating: that is the pill look. */

/* The wordmark already carries the name in both scripts, so the lockup is
   the image alone, run large. The accessible name lives in the alt text. */
.brand { display: flex; align-items: center; gap: 12px; flex: none; }
/* Logo sizing (2026-08-20). The official horizontal logo is 4.9:1, wider
   than the old composite. Fixed height + global img max-width:100% +
   object-fit:cover was cropping both ends in any narrow container, so the
   logo fits by containment instead: never crop a brand mark. */
.brand-logo {
  height: clamp(34px, 3.2vw, 48px);
  width: auto;
  max-width: 100%;
  object-fit: contain;
  object-position: left center;
}
.brand-name { font-weight: 700; font-size: 1.25rem; letter-spacing: -0.03em; line-height: 1.1; }
.brand-cn { font-size: var(--fs-caption); font-weight: 500; color: var(--muted); letter-spacing: 0.02em; }
.brand-locale {
  align-self: center;
  padding-left: 12px;
  border-left: 1px solid var(--line);
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0.04em;
}

/* Links sit centred between logo and CTA, like the reference bar */
.nav-links { display: flex; align-items: center; gap: 26px; margin-inline: auto; }
.nav-links a {
  position: relative;
  font-size: var(--fs-small);
  font-weight: 500;
  padding: 8px 0;
  transition: color var(--t-micro) var(--ease);
}
.nav-links a:hover { color: var(--ocean-type); }
/* Current page is marked by a rule under the word, not a bullet beside it:
   the underline sits in the reading line instead of pushing the label off
   the tab rhythm. */
.nav-links a.is-active { color: var(--ocean-type); font-weight: 600; }
/* Active state is colour only, like the reference. The underline bar is
   removed (client call 2026-08-20). */
.nav-cta { flex: none; }
/* The in-menu CTA is a mobile-only duplicate of .nav-cta */
.nav-links > .btn { display: none; }

.nav-toggle {
  display: none;
  width: 48px; height: 48px;
  margin-left: auto;
  background: transparent;
  border: 2px solid var(--ink);
  border-radius: var(--r-pill);
  color: var(--ink);
  font-size: 1.05rem;
}

/* ---------- Hero ----------
   The photograph bleeds off the right edge and its left side is masked to
   transparent, so it dissolves into the page instead of ending on an edge.
   The copy sits on that dissolve. A curve closes the section. */
.hero {
  position: relative;
  background: var(--paper);
  padding-block: calc(clamp(44px, 5.5vw, 88px) + var(--nav-block)) clamp(132px, 15vw, 216px);
  overflow: hidden;
}
.hero > .container { position: relative; z-index: 2; }
.hero-text { max-width: 34rem; }
/* Two solid colours on two lines, not a gradient across the words. Both
   are taken from the logo's own hues rather than the brand doc's Ocean and
   Nature, so the headline and the mark above it read as one family. */
.hero h1 { max-width: none; }
.h1-fn { color: var(--logo-blue-type); }
.h1-lv { color: var(--logo-green-type); }
.hero-copy { margin-top: clamp(24px, 3vw, 36px); }
.hero-copy .lead { max-width: 42ch; }
.hero-copy .cta-actions { margin-top: clamp(24px, 3vw, 32px); }

.hero-photo {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: min(64%, 1040px);
  z-index: 1;
  pointer-events: none;
}
.hero-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 58% center;
  /* the dissolve · transparent at the left, solid by just under halfway */
  -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.5) 20%, #000 46%);
          mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.5) 20%, #000 46%);
}

.hero-curve {
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  width: 100%;
  height: clamp(58px, 7.5vw, 108px);
  z-index: 3;
  display: block;
}
.hero-curve-fill { fill: var(--paper); }
.hero-curve-line {
  fill: none;
  stroke: url(#heroCurveStroke);
  stroke-width: 2.5;
  vector-effect: non-scaling-stroke;
}

/* Three grounds for trust, stated once, right under the buttons. */
.hero-feats {
  list-style: none;
  margin: clamp(32px, 4vw, 44px) 0 0;
  padding: clamp(24px, 3vw, 28px) 0 0;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 14px 36px;
}
.hero-feats li { display: flex; align-items: center; gap: 12px; }

/* Mobile-only twin of .hero-feats, living inside the photo frame as a frosted
   band (Kelvin 2026-08-31: the badges should melt into the photograph instead
   of stacking dryly above it). aria-hidden - it duplicates the text-column
   list, and screen readers only need one. */
.hero-feats--overlay { display: none; }

.hero-feats i,
.hero-feats .ico {
  flex: none;
  display: grid; place-items: center;
  width: 44px; height: 44px;
  background: var(--sand);
  border-radius: var(--r-pill);
  color: var(--ocean-type);
  font-size: 1rem;
}
.hero-feats span {
  font-size: var(--fs-caption);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.005em;
}


/* ---------- Photo placeholder (swap for real clinic photos) ---------- */
.ph {
  display: grid;
  place-items: center;
  width: 100%; height: 100%;
  background:
    repeating-linear-gradient(45deg, var(--sand) 0 12px, var(--stone) 12px 24px);
  color: var(--ink);
  font-size: var(--fs-small);
  font-weight: 600;
  text-align: center;
  padding: 20px;
  letter-spacing: 0.02em;
}
.ph i { font-size: 1.5rem; margin-bottom: 8px; display: block; }

/* ---------- Value / OOI Way ---------- */
.values {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: var(--gutter);
}
.journey {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--gutter);
}
.jstep {
  background: rgba(250, 248, 243, .09);
  border: 1px solid rgba(250, 248, 243, .2);
  border-radius: var(--r-lg);
  padding: 28px 24px;
}
.jstep b {
  display: block;
  font-family: var(--font-display);
  font-size: 2.125rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--gold);
}
.jstep span { display: block; margin-top: 14px; font-size: var(--fs-small); line-height: 1.55; color: rgba(250, 248, 243, .88); }
.promise-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.promise-list li { display: flex; gap: 14px; align-items: flex-start; }
.promise-list i,
.promise-list .ico {
  flex: none; display: grid; place-items: center;
  width: 30px; height: 30px; margin-top: 1px;
  background: var(--nature); color: var(--forest);
  border-radius: var(--r-pill); font-size: 0.72rem;
}

.value {
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: 32px 28px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.value:nth-child(3) { background: var(--nature); color: var(--ink-deep); }
.value-mark {
  display: grid; place-items: center;
  width: 48px; height: 48px;
  background: var(--white);
  border-radius: var(--r-pill);
  color: var(--ink);
  font-size: 1.1rem;
  font-weight: 800;
}
.value h3 { letter-spacing: -0.02em; }
.value p { color: var(--muted); }
.value:nth-child(3) p { color: var(--ink-deep); }
.value:nth-child(3) .value-mark { background: var(--paper); color: var(--nature-fill); }

/* The hero curve already does the separating, so this section opens tighter
   than the standard section rhythm instead of stacking whitespace on top of
   the paper wedge the curve leaves behind. */
#services { padding-top: clamp(28px, 3.4vw, 48px); }

/* ---------- Our Services ----------
   Three across, photograph down one side and a tinted panel down the other,
   per the client's row comp. The third card mirrors so the row does not
   march. The client also supplied finished artwork with the type baked in;
   it is not used here, because at a third of the container that baked body
   copy renders at 8-9px against the 18px this site uses everywhere, measured
   on a real render. The photographs are cropped out of that artwork and the
   words are live markup, which is also the only form an answer engine reads. */
.svc-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gutter);
}
.svc-card-media .ph { height: 100%; min-height: 220px; }
.svc-card {
  /* 2026-08-31 (Kelvin): photo moved from a 38% side strip to a full-width
     banner on top. The side strip was cramping the photographs once the tick
     lists made the cards taller; photo-top also matches the Resources cards,
     so the page keeps one card grammar. The --flip mirror is retired with it. */
  display: flex;
  flex-direction: column;
  background: var(--tint-blue);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform var(--t-base) var(--ease), box-shadow var(--t-base) var(--ease);
}
.svc-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); }
.svc-card--green { background: var(--tint-green); }

.svc-card-media { flex: none; height: 220px; position: relative; overflow: hidden; }
.svc-card-media img { width: 100%; height: 100%; object-fit: cover; }
/* Landscape banner from a portrait source: anchor each photograph on its own
   subject (faces sit high in frames 2 and 3). */
.svc-card:nth-child(1) .svc-card-media img { object-position: center 30%; }
.svc-card:nth-child(2) .svc-card-media img { object-position: center 22%; }
.svc-card:nth-child(3) .svc-card-media img { object-position: center 20%; }

.svc-card-body {
  flex: 1;
  min-width: 0;
  padding: 26px 24px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.svc-card-mark {
  display: grid; place-items: center;
  width: 48px; height: 48px;
  border-radius: var(--r-pill);
  background: var(--logo-blue-type);
  color: #fff;
}
.svc-card-mark .ico { width: 24px; height: 24px; }
.svc-card--green .svc-card-mark { background: var(--logo-green-type); }

.svc-card h3 {
  font-size: clamp(1.25rem, 1.7vw, 1.5rem);
  color: var(--logo-blue-type);
  margin-top: 4px;
}
.svc-card--green h3 { color: var(--logo-green-type); }
.svc-card-rule {
  display: block;
  width: 46px; height: 2px;
  background: var(--logo-blue-type);
  border-radius: var(--r-pill);
}
.svc-card--green .svc-card-rule { background: var(--logo-green-type); }

.svc-card-body p { font-size: var(--fs-small); color: var(--ink-70); line-height: 1.55; }
/* Treatment checklist (2026-08-31): the concrete-items density borrowed from
   the reference Kelvin liked, without giving up the client's own photography
   for a generic icon grid. Names are verbatim from data.py - never invented. */
.svc-ticks {
  list-style: none; margin: 2px 0 0; padding: 0;
  display: grid; gap: 8px;
}
.svc-ticks li {
  display: flex; align-items: center; gap: 10px;
  font-size: var(--fs-small); font-weight: 500;
}
.svc-ticks .ico {
  flex: none; width: 22px; height: 22px; padding: 4px; box-sizing: border-box;
  border-radius: 50%;
  background: rgba(255, 255, 255, .85);
}
.svc-card .svc-ticks .ico { color: var(--logo-blue-type); }
.svc-card--green .svc-ticks .ico { color: var(--logo-green-type); }

/* Learn More: was a bare text link; now a pill so the card ends on a real
   action, per the reference. Colour stays the per-card contrast-checked link
   colour (4.54:1 / 4.61:1). */
.svc-card-go {
  margin-top: auto;
  padding: 11px 20px;
  border: 1.5px solid currentColor;
  border-radius: var(--r-pill);
  font-weight: 600;
  transition: background var(--t-base) var(--ease), color var(--t-base) var(--ease);
  display: inline-flex; align-items: center; gap: 10px;
  align-self: flex-start;
  font-size: var(--fs-small);
  font-weight: 600;
  white-space: nowrap;
  color: var(--logo-blue-link);
}
.svc-card--green .svc-card-go { color: var(--logo-green-link); }
.svc-card-go .ico { transition: transform var(--t-micro) var(--ease); }
.svc-card:hover .svc-card-go .ico { transform: translateX(5px); }

@media (prefers-reduced-motion: reduce) {
  .svc-card:hover { transform: none; }
  .svc-card:hover .svc-card-go .ico { transform: none; }
}

/* Short rule under a centred section title */
.head-rule {
  display: block;
  width: 56px; height: 3px;
  margin: 16px auto 0;
  background: var(--logo-green-type);
  border-radius: var(--r-pill);
}

/* ---------- About ----------
   Copy column, three principles, and a photograph that bleeds off the right
   edge, then a full-width strip of four. The left column keeps the site's
   container gutter at every width: max() holds it at --pad up to 1440 and
   tracks the centred container above that. */
.about { background: var(--paper); padding-block: clamp(56px, 7vw, 96px); }

/* About 卡（2026-08-28 实测 straightteeth layout1：radius 32 · 640/640 · h2 48/1.2 · 图 640×427） */
/* Card surfaces that sit on --paper are only 12 per channel away from their
   own ground (the FAQ page's --card fill was 9), so the shadow was doing all
   the work of saying "this is a card". A hairline in --line is 23-40 away from
   paper and defines the edge properly. Cards on --sand are already 37 away and
   are left alone. */
.about-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 32px;
  box-shadow: var(--shadow-card);
  /* 参考站实测：卡本体 pad 0，文字列自带内距，图整半幅满贴（Kelvin 2026-08-28 要更大）*/
  padding: 0;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
}
.about-card-body {
  padding: clamp(40px, 5.5vw, 88px) clamp(28px, 3.5vw, 64px)
           clamp(40px, 5.5vw, 88px) clamp(32px, 5.5vw, 96px);
}
.about-card-body h2 { font-size: var(--fs-h2-xl); line-height: 1.2; }
.about-card-body p { margin-top: 22px; color: var(--ink-70); max-width: 54ch; }
.about-card-body .btn { margin-top: 34px; }
.about-card-media { height: 100%; }
.about-card-media img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: 58% center;
  display: block;
}
@media (max-width: 1000px) {
  .about-card-media { height: auto; }
  .about-card-media img { aspect-ratio: 16 / 10; height: auto; }
}
@media (max-width: 1000px) {
  .about-card { grid-template-columns: 1fr; }
  .about-card-body { padding: 28px; }
}
.about-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr) minmax(0, 0.86fr);
  align-items: stretch;
}
.about-lead {
  padding-block: clamp(56px, 7vw, 100px);
  padding-inline: max(var(--pad), calc(50vw - 720px + var(--pad))) clamp(24px, 3vw, 48px);
}
.eyebrow {
  display: block;
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--muted);
  margin-bottom: 14px;
}
.about-lead h2 { line-height: 1.14; }
.head-rule--left { margin: 20px 0 0; }
.about-lead p { margin-top: 22px; color: var(--ink-70); max-width: 44ch; }
.about-lead .btn { margin-top: 32px; }

.about-points {
  list-style: none;
  margin: 0;
  padding: clamp(56px, 7vw, 100px) clamp(24px, 3vw, 44px);
  border-left: 1px solid var(--line);
  display: grid;
  align-content: center;
  gap: clamp(24px, 3vw, 36px);
}
.about-points li { display: flex; gap: 18px; align-items: flex-start; }
.about-point-mark {
  flex: none;
  display: grid; place-items: center;
  width: 56px; height: 56px;
  border-radius: var(--r-pill);
  background: var(--tint-blue);
  color: var(--logo-blue-link);
}
.about-point-mark--green { background: var(--tint-green); color: var(--logo-green-link); }
.about-point-mark .ico { width: 26px; height: 26px; }
.about-points h3 { font-size: 1.25rem; line-height: 1.25; }
.about-points p { margin-top: 8px; font-size: var(--fs-small); color: var(--ink-70); line-height: 1.5; }

.about-photo { position: relative; overflow: hidden; }
.about-photo img { width: 100%; height: 100%; object-fit: cover; object-position: 58% center; }

/* Strip of four */
.about-strip { background: var(--tint-green); }
.about-features {
  list-style: none;
  margin: 0;
  padding: clamp(32px, 4vw, 48px) 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(20px, 2.4vw, 36px);
}
.about-features li {
  display: flex; gap: 16px; align-items: flex-start;
  padding-right: clamp(20px, 2.4vw, 36px);
  border-right: 1px solid rgba(47, 75, 58, .14);
}
.about-features li:last-child { border-right: 0; padding-right: 0; }
.about-feature-mark {
  flex: none;
  display: grid; place-items: center;
  width: 52px; height: 52px;
  border-radius: var(--r-pill);
  background: rgba(250, 248, 243, .8);
  color: var(--logo-green-link);
}
.about-feature-mark .ico { width: 24px; height: 24px; }
.about-features h3 { font-size: 1.125rem; line-height: 1.25; }
.about-features p { margin-top: 8px; font-size: var(--fs-caption); color: var(--ink-70); line-height: 1.5; }

@media (max-width: 1100px) {
  .about-top { grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr); }
  .about-photo { grid-column: 1 / -1; aspect-ratio: 16 / 7; }
  .about-features { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .about-features li:nth-child(2n) { border-right: 0; padding-right: 0; }
}
@media (max-width: 860px) {
  .about-top { grid-template-columns: 1fr; }
  .about-lead { padding-inline: var(--pad); padding-bottom: 0; }
  .about-points { border-left: 0; border-top: 1px solid var(--line); padding-inline: var(--pad); }
  .about-photo { aspect-ratio: 16 / 10; }
  .about-features { grid-template-columns: 1fr; }
  .about-features li { border-right: 0; padding-right: 0; }
}

/* Outlined pill, used where a section needs a secondary route out */
.btn--outline {
  background: transparent;
  color: var(--logo-blue-link);
  border-color: var(--logo-blue-link);
}
.btn--outline:hover { background: var(--logo-blue-link); color: #fff; }

/* ---------- Service index list ---------- */
.svc-layout {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(32px, 4vw, 64px);
  align-items: start;
}
.svc-visual {
  border-radius: var(--r-lg);
  overflow: hidden;
  aspect-ratio: 4 / 5;
  background: var(--surface);
}
.svc-note {
  margin-top: var(--gutter);
  background: var(--wood-200);
  border-radius: var(--r-md);
  padding: 24px;
  font-weight: 600;
}
.svc-list { list-style: none; margin: 0; padding: 0; }
.svc-list li { border-bottom: 1px solid var(--line); }
.svc-list a {
  display: flex;
  align-items: baseline;
  gap: 20px;
  padding: 22px 4px;
  transition: transform var(--t-base) var(--ease), color var(--t-micro) var(--ease);
}
.svc-list a:hover { transform: translateX(14px); color: var(--ocean-type); }
/* No 01/02/03 markers here: the treatments are a set, not a sequence, and
   numbering them would imply an order the patient does not follow. */
.svc-list .name { font-size: 1.375rem; font-weight: 600; letter-spacing: -0.02em; }
.svc-list .arrow { margin-left: auto; opacity: 0; transition: opacity var(--t-micro) var(--ease); }
.svc-list a:hover .arrow { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .svc-list a:hover { padding-left: 4px; }
}

/* ---------- Branch cards ---------- */
.branches {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gutter);
}
.branch {
  background: var(--white);
  border-radius: var(--r-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-card);
}
.branch-media { aspect-ratio: 16 / 9; background: var(--surface); }
.branch-media img { width: 100%; height: 100%; }
.branch-body { padding: 28px; display: flex; flex-direction: column; gap: 16px; flex: 1; }
.branch-rating {
  display: inline-flex; align-items: center; gap: 8px;
  align-self: flex-start;
  background: var(--lime);
  border-radius: var(--r-pill);
  padding: 7px 14px;
  font-size: var(--fs-small);
  font-weight: 700;
}
.branch-rating i, .branch-rating .ico { color: var(--gold); }
.branch dl { margin: 0; display: grid; gap: 12px; }
.branch dl div { display: flex; gap: 12px; align-items: flex-start; }
.branch dt {
  flex: none;
  display: grid; place-items: center;
  width: 34px; height: 34px;
  background: var(--wood-100);
  color: var(--ink);
  border-radius: var(--r-pill);
  font-size: 0.85rem;
}
.branch dd { margin: 0; font-size: var(--fs-small); line-height: 1.5; }
.branch-actions { margin-top: auto; padding-top: 8px; display: flex; gap: 12px; flex-wrap: wrap; }

/* ---------- Proof band ---------- */
.proof {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--gutter);
}
.proof-item {
  background: rgba(250, 248, 243, .09);
  border: 1px solid rgba(250, 248, 243, .2);
  border-radius: var(--r-lg);
  padding: 28px 24px;
}
.proof-item b {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.125rem, 4.4vw, 3rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--gold);   /* signature colour · 4.22:1 on Forest Evergreen */
}
.proof-item span { display: block; margin-top: 12px; font-size: var(--fs-caption); line-height: 1.45; color: rgba(250, 248, 243, .82); }

/* ---------- Steps ---------- */
.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gutter);
}
.step {
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: 14px 14px 28px;
}
.step-media {
  position: relative;
  border-radius: var(--r-md);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--blue-soft);
  margin-bottom: 22px;
}
.step-media img { width: 100%; height: 100%; }
.step-tag {
  position: absolute; top: 14px; left: 14px;
  display: flex; align-items: baseline; gap: 8px;
  color: var(--white);
  text-shadow: 0 1px 12px rgba(8, 39, 65, .6);
}
.step-tag span { font-size: var(--fs-small); font-weight: 500; }
.step-tag b { font-size: 1.75rem; font-weight: 800; letter-spacing: -0.03em; }
.step-body { padding-inline: 14px; }
.step-body h3 { margin-bottom: 10px; }
.step-body p { font-size: var(--fs-small); color: var(--muted); }

/* ---------- FAQ ---------- */
.faq { max-width: 860px; margin-inline: auto; }
/* Inside an article column the block aligns with the text, it does not float
   in its own centre - that offset was the core of the "randomly placed" read. */
.docbody .faq,
.prose-col .faq { max-width: none; margin-inline: 0; }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 72px;
  padding: 20px 0;
  background: none;
  border: 0;
  text-align: left;
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.faq-q i {
  flex: none;
  display: grid; place-items: center;
  width: 36px; height: 36px;
  background: var(--surface);
  border-radius: var(--r-pill);
  font-size: 0.85rem;
  transition: transform var(--t-base) var(--ease), background-color var(--t-micro) var(--ease);
}
.faq-item.is-open .faq-q i,
.faq-item.is-open .faq-q .ico { transform: rotate(45deg); background: var(--nature); color: var(--forest); }
.faq-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--t-base) var(--ease);
}
.faq-item.is-open .faq-a { grid-template-rows: 1fr; }
.faq-a > div { overflow: hidden; color: var(--muted); max-width: 68ch; }
.faq-item.is-open .faq-a > div { padding-bottom: 24px; }
@media (prefers-reduced-motion: reduce) { .faq-a { transition: none; } }

/* ---------- Patient voices ----------
   Structure only. Every quote below is an empty slot: nothing goes live
   here until Cindy supplies real, consented patient words. See HANDOFF.md. */
.voices {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gutter);
}
.voice {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 32px 28px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.voice-quote {
  font-family: var(--font-display);
  font-size: 2.75rem;
  font-weight: 700;
  line-height: 0.6;
  color: var(--gold);
}
.voice-body {
  flex: 1;
  min-height: 5.5em;
  display: grid;
  place-items: center;
  border: 1px dashed var(--wood-400);
  border-radius: var(--r-md);
  padding: 20px;
  text-align: center;
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: var(--ink-70);
  background: var(--wood-100);
}
.voice-by { display: flex; align-items: center; gap: 12px; }
.voice-avatar {
  flex: none;
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink-70);
  font-size: 0.9rem;
}
.voice-by b { display: block; font-size: var(--fs-small); font-weight: 600; line-height: 1.3; }
.voice-by span { display: block; font-size: var(--fs-caption); color: var(--muted); line-height: 1.3; }

/* ---------- CTA band ----------
   The one place the two brand colours meet: Ocean walking into Nature,
   technology into healing, which is the positioning line stated as a
   surface. Both ends are the darkened partners so the white type holds
   4.5:1 the whole way across. */
.cta-band {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(104deg, var(--ocean-fill) 0%, #3C7C8E 52%, var(--nature-fill) 100%);
  color: #fff;
  border-radius: var(--r-xl);
  padding: clamp(40px, 5vw, 72px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 32px;
  align-items: center;
}
/* A leaf drawn large and cropped by the band's own corner. Nature stated
   once, at size, instead of sprinkled as decoration. */
.cta-leaf {
  position: absolute;
  right: -5%; bottom: -46%;
  width: clamp(200px, 23vw, 320px);
  height: auto;          /* .ico locks 1em square; the motif needs to grow */
  color: #fff;
  opacity: .16;
  stroke-width: 1;
  pointer-events: none;
}

/* Outlined button sitting directly on the gradient. The leaf lightens the
   green end enough that plain white type measured 3.00:1 there, so the
   button carries its own dark scrim and never depends on what is behind it. */
.btn--onink-ghost {
  background: rgba(20, 40, 28, .28);
  color: #fff;
  border-color: rgba(255, 255, 255, .55);
}
.btn--onink-ghost:hover { background: rgba(20, 40, 28, .42); }
/* The band isolates, so a negative z-index would hide the leaf behind the
   gradient. The copy is lifted above it instead. */
.cta-band > div { position: relative; z-index: 1; }
.cta-band h2 { color: #fff; max-width: 18ch; }
.cta-band .lead { color: rgba(255, 255, 255, .9); margin-top: 14px; }
.cta-actions { display: flex; gap: 12px; flex-wrap: wrap; }

/* ---------- Footer ----------
   Full bleed, not an inset rounded panel: the comp runs it edge to edge and
   closes the page with a flat bar. A hairline of the two brand colours sits
   on the top edge, echoing the curve that opens the page. */
.footer {
  background: var(--navy);
  color: var(--paper);
  /* 顶部渐变线 2026-08-25 拆除（Kelvin：不好看） */
}
.footer-inner {
  padding-block: clamp(48px, 6vw, 76px) 0;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.28fr 0.76fr 1.1fr 1.72fr 1.14fr;
  gap: 40px clamp(20px, 2.4vw, 40px);
}
/* 2026-08-25 Kelvin：栏间竖线拆除（参考 Premier footer 的干净分栏） */
.footer-col { padding-left: clamp(16px, 1.8vw, 26px); }
.footer .brand-name { color: var(--cream); }
.footer .brand-cn { color: rgba(250, 248, 243, .66); }
/* No plate: on --navy every part of the mark clears 3:1, including the grey
   Chinese lockup, so the wordmark sits straight on the background at size. */
.footer .brand { background: none; padding: 0; display: block; }
.footer .brand-logo {
  /* Column is ~260px in the footer grid; height follows from width so the
     4.9:1 mark always shows whole. */
  width: min(100%, 250px);
  height: auto;
  object-fit: contain;
  object-position: left center;
}
.footer-tag { margin-top: 20px; color: rgba(250, 248, 243, .9); font-size: var(--fs-small); line-height: 1.5; }
.footer-tag--sub { margin-top: 10px; color: rgba(250, 248, 243, .66); font-size: var(--fs-caption); }
.footer-social { display: flex; gap: 10px; margin-top: 24px; }
.footer-social a {
  display: grid; place-items: center;
  width: 42px; height: 42px;
  border: 1px solid rgba(250, 248, 243, .3);
  border-radius: var(--r-pill);
  transition: background-color var(--t-micro) var(--ease), color var(--t-micro) var(--ease);
}
.footer-social a:hover { background: var(--nature); color: var(--forest); border-color: var(--nature); }

/* Footer column headings are h3, not h4: the last content heading on every
   page is an h2, so h4 here left an h2 -> h4 gap in the outline on all 15
   pages. h3 keeps the outline legal. The declarations below restore the h4
   look exactly, because the base h3 rule sets Playfair at 28px. */
.footer h3 {
  font-family: var(--font);
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.25;
  margin-bottom: 20px;
  letter-spacing: -0.015em;
}
.footer-links { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.footer-links a { font-size: var(--fs-small); color: rgba(250, 248, 243, .86); text-wrap: nowrap; }
.footer-links a:hover { color: var(--gold); }

.footer-contact { list-style: none; margin: 0; padding: 0; display: grid; gap: 18px; }
.footer-contact li { display: flex; gap: 12px; align-items: flex-start; }
.footer-contact .ico { width: 18px; height: 18px; margin-top: 3px; color: var(--gold); }
.footer-contact span { font-size: var(--fs-caption); line-height: 1.55; color: rgba(250, 248, 243, .86); }
.footer-contact b {
  text-wrap: nowrap;
  display: block;
  font-size: var(--fs-caption);
  letter-spacing: 0;
  color: rgba(250, 248, 243, .80);
  margin-bottom: 5px;
}
.footer-contact a { text-decoration: none; white-space: nowrap; transition: color var(--t-micro) var(--ease); }
.footer-contact a:hover { color: var(--gold); }

.footer-base {
  margin-top: clamp(40px, 5vw, 56px);
  padding-block: 22px;
  border-top: 1px solid rgba(250, 248, 243, .16);
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  font-size: var(--fs-caption);
  color: rgba(250, 248, 243, .7);
}

/* ---------- Floating WhatsApp ---------- */
.wa-float {
  position: fixed;
  right: 24px; bottom: 24px;
  z-index: var(--z-float);
  display: grid; place-items: center;
  width: 60px; height: 60px;
  background: #25D366;
  border-radius: var(--r-pill);
  box-shadow: 0 10px 30px rgba(37, 211, 102, .38);
  transition: transform var(--t-micro) var(--ease);
}
.wa-float:hover { transform: scale(1.06); }
.wa-float svg { width: 32px; height: 32px; fill: #fff; }
.wa-float::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: var(--r-pill);
  border: 2px solid #25D366;
  animation: wa-pulse 2.4s var(--ease) infinite;
}
@keyframes wa-pulse {
  0%   { transform: scale(1);    opacity: .7; }
  100% { transform: scale(1.55); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .wa-float::after { animation: none; }
  .wa-float:hover { transform: none; }
}

/* ---------- Page header (inner pages) ---------- */
/* Centred hero pagehead (2026-08-21, client call: all sub-page titles
   centred like the reference). Measured at 1512vp: crumb 12px/ls1.2
   uppercase · kicker 14.4/600/ls1.2 · h1 56px centred, max 768 ·
   gaps 34 / 25 / 16 / 32. Lead stays at our 18px body size: the
   audience skews older and body copy does not shrink (PRODUCT.md). */
.pagehead {
  background: var(--cream);
  padding-block: calc(clamp(40px, 5vw, 72px) + var(--nav-block)) clamp(32px, 4vw, 56px);
  text-align: center;
  position: relative;
  overflow: hidden;
}
/* 页头装饰（2026-08-25 Kelvin 选 B）：青海波 Seigaiha —— 日本传统波纹，
   呼应诊所技术与装修的日本渊源。logo 蓝细线、顶部起向下渐隐，不压内容。
   inline data-URI 零请求。 */
.pagehead::before {
  content: "";
  position: absolute; inset: 0;
  background: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%22120%22%20height%3D%2260%22%20viewBox%3D%220%200%20120%2060%22%3E%3Cg%20fill%3D%22none%22%20stroke%3D%22%2333A0D9%22%20stroke-width%3D%221.6%22%20opacity%3D%220.16%22%3E%3Ccircle%20cx%3D%2230%22%20cy%3D%2260%22%20r%3D%2228%22/%3E%3Ccircle%20cx%3D%2230%22%20cy%3D%2260%22%20r%3D%2220%22/%3E%3Ccircle%20cx%3D%2230%22%20cy%3D%2260%22%20r%3D%2212%22/%3E%3Ccircle%20cx%3D%2290%22%20cy%3D%2260%22%20r%3D%2228%22/%3E%3Ccircle%20cx%3D%2290%22%20cy%3D%2260%22%20r%3D%2220%22/%3E%3Ccircle%20cx%3D%2290%22%20cy%3D%2260%22%20r%3D%2212%22/%3E%3Ccircle%20cx%3D%220%22%20cy%3D%2230%22%20r%3D%2228%22/%3E%3Ccircle%20cx%3D%220%22%20cy%3D%2230%22%20r%3D%2220%22/%3E%3Ccircle%20cx%3D%220%22%20cy%3D%2230%22%20r%3D%2212%22/%3E%3Ccircle%20cx%3D%2260%22%20cy%3D%2230%22%20r%3D%2228%22/%3E%3Ccircle%20cx%3D%2260%22%20cy%3D%2230%22%20r%3D%2220%22/%3E%3Ccircle%20cx%3D%2260%22%20cy%3D%2230%22%20r%3D%2212%22/%3E%3Ccircle%20cx%3D%22120%22%20cy%3D%2230%22%20r%3D%2228%22/%3E%3Ccircle%20cx%3D%22120%22%20cy%3D%2230%22%20r%3D%2220%22/%3E%3Ccircle%20cx%3D%22120%22%20cy%3D%2230%22%20r%3D%2212%22/%3E%3Ccircle%20cx%3D%2230%22%20cy%3D%220%22%20r%3D%2228%22/%3E%3Ccircle%20cx%3D%2230%22%20cy%3D%220%22%20r%3D%2220%22/%3E%3Ccircle%20cx%3D%2230%22%20cy%3D%220%22%20r%3D%2212%22/%3E%3Ccircle%20cx%3D%2290%22%20cy%3D%220%22%20r%3D%2228%22/%3E%3Ccircle%20cx%3D%2290%22%20cy%3D%220%22%20r%3D%2220%22/%3E%3Ccircle%20cx%3D%2290%22%20cy%3D%220%22%20r%3D%2212%22/%3E%3C/g%3E%3C/svg%3E") top center / 120px 60px repeat;
  -webkit-mask-image: linear-gradient(180deg, #000, transparent 78%);
  mask-image: linear-gradient(180deg, #000, transparent 78%);
  pointer-events: none;
}
.pagehead > .container { position: relative; }
/* 页头与首个内容区之间的垫距会叠加（56 + 80 ≈ 136px 的洞，客户抓包
   2026-08-25）。紧跟 pagehead 的区块上垫距减半。 */
.pagehead + .section { padding-top: clamp(20px, 2.5vw, 36px); }
.crumbs {
  font-size: var(--fs-caption); letter-spacing: 0;
  color: var(--muted); margin-bottom: 34px;
}
.crumbs a:hover { color: var(--ink); text-decoration: underline; }
/* Was .ph-kicker, an uppercase tracked eyebrow sitting over every section
   heading on the site. Removed 2026-08-30: on the homepage six of the nine
   repeated the h2 directly beneath them, and on the inner pages it repeated
   the breadcrumb directly above it. What survives is this: a role label on a
   person, where "Founder" is information the name does not carry. Set as a
   label, not as decoration. */
.person-role {
  margin: 0 0 6px;
  font-size: var(--fs-caption); font-weight: 600;
  color: var(--ocean-type);
}
.pagehead h1 {
  /* 2026-08-21 四改（日式方向）：字用墨、色用印 —— 大字回沉静的墨绿，
     logo 蓝绿降级为标题下的一条短色线（判子原则：色彩是一笔，不是一片）。
     契合客户的日本手艺与日式装修语言。 */
  color: var(--ink);
  font-size: clamp(2.25rem, 4.4vw, 3.5rem);
  line-height: 1.2;
  max-width: 768px; margin-inline: auto;
  text-wrap: balance;
}
.pagehead h1 em { font-style: italic; color: var(--logo-blue-type); }
.pagehead .lead { margin: 16px auto 0; max-width: 768px; }
.ph-actions {
  margin-top: 32px;
  display: flex; gap: 14px; justify-content: center; flex-wrap: wrap;
}

/* ---------- Service detail blocks ---------- */
.svc-detail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
.svc-detail + .svc-detail { margin-top: clamp(56px, 7vw, 96px); }
.svc-detail:nth-child(even) .svc-detail-media { order: 2; }
.svc-detail-media {
  border-radius: var(--r-lg);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--surface);
}
.svc-detail-media img { width: 100%; height: 100%; }
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.ticks li { display: flex; gap: 12px; align-items: flex-start; font-size: var(--fs-small); }
.ticks i,
.ticks .ico {
  flex: none;
  display: grid; place-items: center;
  width: 28px; height: 28px;
  background: var(--nature);
  color: var(--forest);
  border-radius: var(--r-pill);
  font-size: 0.7rem;
  margin-top: 1px;
}


/* ---------- Map ---------- */
.map-wrap {
  border-radius: var(--r-lg);
  overflow: hidden;
  aspect-ratio: 16 / 10;
  background: var(--surface);
}
.map-wrap iframe { width: 100%; height: 100%; border: 0; display: block; }

/* ---------- TBD flag (remove before client handoff) ---------- */
.tbd {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #FFF0CC;
  color: #7A5200;
  border: 1px dashed #C79A2E;
  border-radius: var(--r-sm);
  padding: 6px 12px;
  font-size: var(--fs-kicker);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 1100px) {
  :root { --pad: 40px; }
  .hero h1 { max-width: 16ch; }
  .hero-bottom { grid-template-columns: 1fr; align-items: start; }
  .svc-layout { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-col { border-left: 0; padding-left: 0; }
  .cta-band { grid-template-columns: 1fr; }
  .proof { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .voices { grid-template-columns: 1fr; }
}

/* Nav collapses at 1000px, not 860px (2026-08-18).
   Adding "Our Team" made six links. Measured at 880px the header needed 933px
   against an 880px viewport, so the bar overflowed. The rest of the tablet
   rules stay at 860px: moving them would change the approved homepage between
   861 and 1000px, and only the nav had the problem. */
@media (max-width: 1000px) {
  .nav .container { min-height: 76px; gap: 16px; }
  .nav-toggle { display: grid; place-items: center; }
  .nav-cta { display: none; }
  .nav-links {
    /* Aligned to the pill's side padding and rounded to match it. */
    position: absolute;
    left: clamp(12px, 2.5vw, 32px);
    right: clamp(12px, 2.5vw, 32px);
    top: calc(100% + 8px);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin: 0;
    padding: 8px 24px 24px;
    background: rgba(250, 248, 243, .96);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    border: 1px solid rgba(227, 218, 203, .7);
    border-radius: var(--r-lg);
    box-shadow: 0 20px 40px rgba(47, 75, 58, .14);
    display: none;
  }
  .nav-links.is-open { display: flex; }
  .nav-links a { min-height: 52px; display: flex; align-items: center; border-bottom: 1px solid var(--line); }
  .nav-links a.is-active::after { display: none; }
  /* Re-show the in-menu duplicate. Without this both it and .nav-cta are
     display:none below the break and the menu ships with no booking button. */
  .nav-links > .btn { display: inline-flex; margin-top: 16px; border-bottom: 0; }
}

@media (max-width: 860px) {
  :root { --pad: 24px; }


  /* Below the tablet break the photograph stops being a backdrop and
     becomes a banner under the copy, unmasked and full width. */
  /* No bottom padding: the photo has to reach the section's edge so the
     curve cuts it, instead of floating in empty paper below it. */
  /* Must keep + var(--nav-block): the nav is a floating pill overlaying the
     page, and this override once dropped the term - on real phones the pill
     sat straight on top of the headline (Kelvin's screenshot, 2026-08-31). */
  .hero { padding-block: calc(clamp(20px, 4vw, 36px) + var(--nav-block)) 0; }
  .hero-text .hero-feats { display: none; }
  /* Three small caption chips at the photo's bottom edge, not one slab -
     the first frosted-band version covered the family and read as a patch
     pasted over the photograph (Kelvin: 很刻意). Chips hug their text and
     leave the people visible. */
  .hero-feats--overlay {
    display: flex;
    position: absolute;
    left: 0; right: 0; bottom: 30px;
    z-index: 2;
    margin: 0; padding: 0 12px;
    border-top: 0;
    justify-content: center;
    gap: 8px;
    flex-wrap: wrap;
  }
  .hero-feats--overlay li {
    background: rgba(250, 248, 243, .85);
    -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
    border-radius: var(--r-pill);
    padding: 7px 13px;
  }
  .hero-feats--overlay span {
    font-size: 11.5px; font-weight: 600; line-height: 1;
    word-break: keep-all; white-space: nowrap;
  }
  .hero-text { max-width: none; }
  .hero-photo {
    position: static;
    width: 100%;
    height: clamp(280px, 66vw, 360px);
    margin-top: clamp(32px, 6vw, 44px);
  }
  .hero-photo img {
    object-position: center 32%;
    -webkit-mask-image: none;
            mask-image: none;
  }
  .hero-feats { gap: 14px 24px; }

  .sec-head { grid-template-columns: 1fr; align-items: start; }
  .values, .steps, .branches, .voices, .svc-cards { grid-template-columns: 1fr; }
  .svc-card, .svc-card--flip { flex-direction: column; }
  .svc-card-media { flex: none; aspect-ratio: 16 / 10; }
  .brand-locale { display: none; }
  .svc-detail { grid-template-columns: 1fr; }
  .svc-detail:nth-child(even) .svc-detail-media { order: 0; }

  /* Touch targets: 48px minimum on handheld */
  .footer-social a { width: 48px; height: 48px; }
}

@media (max-width: 560px) {
  .footer-grid { grid-template-columns: 1fr; }
  .proof { grid-template-columns: 1fr; }
  .svc-list .name { font-size: 1.125rem; }
  .btn { width: 100%; }
  .cta-actions .btn { width: auto; flex: 1 1 auto; }
  .wa-float { right: 16px; bottom: 16px; }
}

/* ---------- Guide list (added 2026-08-14) ----------
   Question left, one-line summary right. Extends .svc-list rather than
   introducing a card grid: 23 question pages as a card wall is the
   "cards everywhere" anti-pattern. */
.guide-list a { justify-content: space-between; }
.guide-list h3 { flex: 0 0 auto; max-width: 48%; font-size: var(--fs-body); font-weight: 600; }
.guide-list p { flex: 1 1 auto; color: var(--muted); font-size: var(--fs-small); text-align: right; }
@media (max-width: 720px) {
  .guide-list a { flex-direction: column; align-items: flex-start; gap: 6px; }
  .guide-list h3, .guide-list p { max-width: none; text-align: left; }
}

/* ---------- Sub-page composition: fact rail + prose (2026-08-18) ----------
   Replaces the full-bleed colour band that held a single paragraph. That band
   read as an empty slab: the text filled half the column and nothing filled the
   rest. Facts now sit in their own rail, which is what turns the whitespace into
   structure instead of a hole, and it puts every harvestable fact in one place.
   Registration number, qualification, hours, phone: one block, scannable by a
   person and by a crawler. */

.docpage { display: grid; gap: clamp(28px, 4vw, 56px); align-items: start; }
@media (min-width: 900px) {
  .docpage { grid-template-columns: minmax(230px, 290px) minmax(0, 1fr); }
  .docrail { position: sticky; top: 104px; }
}
.docbody { max-width: 68ch; }
/* 无侧栏时正文居中放宽 */
.docbody--solo { margin-inline: auto; }
.docbody > * + * { margin-top: 28px; }
.docbody h2 { margin-top: 56px; }
.docbody h2:first-child { margin-top: 0; }
.docbody p { text-wrap: pretty; }

/* The direct answer. Contained in the prose column, never full-bleed. */
.answer {
  background: var(--tint-blue);
  border-radius: var(--r-lg);
  padding: clamp(22px, 3vw, 34px);
  font-size: var(--fs-lead);
  line-height: 1.55;
  color: var(--ink);
}
.answer :last-child { margin-bottom: 0; }


/* Portrait slot. Monogram until the clinic supplies photographs, then swap the
   markup for an <img> and delete this rule. */
.portrait { width: 100%; max-width: 260px; border-radius: var(--r-lg); display: block; }
.monogram {
  aspect-ratio: 1; display: grid; place-items: center;
  background: var(--tint-green); color: var(--logo-green-link);
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(2.75rem, 6vw, 4rem); letter-spacing: -0.02em;
}
.byline { font-size: var(--fs-caption); color: var(--muted); line-height: 1.5; }
.byline a { color: var(--ocean-type); text-decoration: underline; text-underline-offset: 3px; }

/* ---------- Nav dropdown panels (2026-08-20, second pass) ----------
   Client reference: compact frosted panel with a bold head, care-line rows,
   and a chevron per row that expands a nested treatment list (accordion).
   One panel language for both Services and Patient Info. */

.nav-item.has-menu { position: relative; display: flex; align-items: center; gap: 2px; }
.nav-sub-toggle {
  display: grid; place-items: center;
  width: 32px; height: 32px;
  border: 0; background: none; cursor: pointer;
  color: var(--ink); border-radius: var(--r-sm);
  transition: transform var(--t-micro) var(--ease);
}
.nav-sub-toggle .ico { width: 16px; height: 16px; }
.nav-sub-toggle.is-open { transform: rotate(180deg); }

.nav-menu-head {
  margin: 0 0 20px;
  font-weight: 700;
  font-size: 0.9rem;   /* 14.4 · measured off reference */
  color: var(--ink);
}

/* Accordion rows inside the panel */
/* Reference list has no full-width separators between rows.
   The whole row is one toggle button (name and arrow act as one,
   client call 2026-08-20); the line's overview link lives as the
   first item inside the nested card, same as the reference. */
.nav-acc-row {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; padding: 8px 0;
  border: 0; background: none; cursor: pointer; text-align: left;
  font-size: 0.9rem; font-weight: 500; color: var(--ink);
}
.nav-acc-row:hover { color: var(--ocean-type); }
.nav-acc-row .ico { width: 15px; height: 15px; flex: none; color: var(--muted);
  transition: transform var(--t-micro) var(--ease); }
.nav-acc-row.is-open .ico { transform: rotate(180deg); }
/* Nested treatment list: the lighter inner card from the reference */
.nav-acc-panel {
  display: none;
  list-style: none;
  margin: 0 0 12px; padding: 16px;
  background: var(--white);
  border-radius: var(--r-md);
}
.nav-acc-panel.is-open { display: block; }
.nav-acc-panel a {
  display: block; padding: 8px 0;
  font-size: 0.9rem; font-weight: 500; color: var(--ink);
}
.nav-acc-panel a:hover { color: var(--ocean-type); }

@media (min-width: 1001px) {
  .nav-menu {
    /* 30px clears the pill's lower edge from the row's own bottom */
    /* Measured off the live reference (1512vp): panel 288w, pad 24, r20,
       flush with the pill bottom edge (reference panel touches the bar, gap 0). 15px = trigger-text bottom to pill bottom at 72px pill height. */
    /* Left-aligned to the trigger, not centred: measured offset 0 between
       the reference panel's text edge and its trigger text. -24px cancels
       the panel's own padding so the text columns line up. */
    position: absolute; top: calc(100% + 13px); left: -24px;
    display: none;
    width: 300px;
    /* Tall enough that the longest line (9 treatments) fits without a
       scrollbar at desktop heights; thin scrollbar only as fallback. */
    max-height: calc(100vh - 150px);
    overflow-y: auto;
    scrollbar-width: thin;
    padding: 24px;
    /* Opaque on purpose (client call 2026-08-20): panels are reading
       surfaces. Translucency stays on the pill, never on a text panel,
       because over a heavy photo the text stops being legible. */
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: 0 9px 25px rgba(47, 75, 58, .12);
    z-index: var(--z-float);
  }
  /* Click-to-open only (client call 2026-08-20): hover-open plus any gap
     means the pointer path can break mid-journey and the menu vanishes.
     Click pins it; it stays until outside click, Esc, or second click.
     No hover bridge needed since nothing opens on hover. */
  .nav-menu.is-open { display: block; }
}

@media (max-width: 1000px) {
  .nav-item.has-menu { flex-wrap: wrap; border-bottom: 1px solid var(--line); }
  .nav-item.has-menu > a { flex: 1 1 auto; border-bottom: 0 !important; }
  .nav-sub-toggle { width: 48px; height: 48px; }
  .nav-menu {
    display: none; flex: 1 1 100%;
    margin: 0 0 12px; padding: 6px 16px;
    background: var(--card);
    border-radius: var(--r-lg);
  }
  .nav-menu.is-open { display: block; }
  .nav-menu-head { display: none; }
  .nav-acc-row { min-height: 44px; }
}

/* Patient Info compact panel (2026-08-20). Small single-column drop, same
   frosted language as the pill. Unlike the treatments list, these links DO
   show inside the stacked mobile menu: there are only four. */
.nav-menu-pages { list-style: none; margin: 0; padding: 0; }
.nav-menu-pages a {
  display: block; padding: 2px 0;
  font-size: 0.9rem; font-weight: 500; color: var(--ink);
}
.nav-menu-pages li + li { margin-top: 13px; }

.nav-menu-pages a:hover { color: var(--ocean-type); }
@media (max-width: 1000px) {
  .nav-menu-pages { display: block; padding: 0; }
  .nav-menu-pages li + li { border-top: 0; }
}

/* ---------- Panel grid (2026-08-20) ----------
   Layout follows the reference's insurer logo wall. We have no logo assets
   and do not fabricate them, so the tiles are typographic: white cards on
   the warm surface, name centred. Swap in real logos if the panels ever
   supply them. */
.panel-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
}
.panel-grid li {
  display: grid; place-items: center;
  min-height: 150px; padding: 24px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-weight: 600; font-size: var(--fs-small);
  text-align: center; color: var(--ink);
}
.panel-grid img {
  max-height: 48px; max-width: 70%;
  width: auto; height: auto; object-fit: contain;
}

/* ---------- Reference-metric FAQ + CTA banner (2026-08-21) ----------
   Measured off premierartsdental insurance page at 1512vp:
   kicker 14.4/600 ls1.2 uppercase · title 48 serif centred ·
   FAQ rows 768w r16 · question 20/600 serif ·
   banner 1280w r24, photo with dark overlay, centred white serif. */
.faq-center { text-align: center; }
.faq-center h2 { font-size: var(--fs-h2-xl); }
.faq--narrow {
  max-width: 768px; margin: 40px auto 0; text-align: left;
}
/* Unified with the homepage FAQ card recipe (2026-08-31 Kelvin: one FAQ look
   site-wide - serif blue question, circled +, 22px radius, soft shadow).
   垫底距只能在展开态给 —— 无条件给会在 0fr 折叠时把答案第一行顶出来
   （2026-08-21 实錯，别再犯）。 */
.faq--narrow .faq-item,
.faq--rows .faq-item {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 22px;
  box-shadow: var(--shadow-card);
  padding: 8px 28px;
}
.faq--narrow .faq-item + .faq-item,
.faq--rows .faq-item + .faq-item { margin-top: 18px; }
.faq--narrow .faq-q,
.faq--rows .faq-q {
  min-height: 64px;
  padding: 20px 0;
  font-family: var(--font-display);
  font-size: 1.3rem; font-weight: 600;
  color: var(--ocean-type);
}
.faq--narrow .faq-a > div,
.faq--rows .faq-a > div { padding: 0; }
.faq--narrow .faq-item.is-open .faq-a > div,
.faq--rows .faq-item.is-open .faq-a > div { padding-bottom: 22px; }
.faq--narrow .faq-q .ico,
.faq--rows .faq-q .ico {
  flex: none;
  width: 36px; height: 36px;
  padding: 8px;
  box-sizing: border-box;
  background: var(--surface);
  border-radius: 50%;
}
.faq--narrow .faq-item.is-open .faq-q .ico,
.faq--rows .faq-item.is-open .faq-q .ico { background: var(--nature); color: var(--forest); }

.cta-banner {
  position: relative; overflow: hidden;
  border-radius: var(--r-xl);
  min-height: clamp(360px, 34vw, 519px);
  display: grid; place-items: center;
}
.cta-banner > img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.cta-banner::before {
  content: ""; position: absolute; inset: 0;
  background: rgba(36, 57, 44, .72);   /* forest ink overlay, not the ref's navy */
}
.cta-banner-inner {
  position: relative; text-align: center;
  padding: clamp(40px, 6vw, 80px);
  max-width: 820px;
}
.cta-banner-inner h2 {
  color: #fff;
  font-size: var(--fs-h2-xl);
  line-height: 1.2;
  text-wrap: balance;
}
.cta-banner-inner p { margin-top: 16px; color: rgba(250, 248, 243, .85); }
.cta-banner-inner .cta-actions { margin-top: 28px; justify-content: center; }

/* ---------- Split panel section + benefits card (2026-08-21) ----------
   Reference: left column carries the heading, prose, logo wall and italic
   note; right is a floating white card with check-circle points. */
/* 2026-08-21 三改：逐元素 68ch 居中废除 —— ch 随字号浮动，标题/导语/正文
   各有各的左缘，读起来歪（客户抓包）。改成一根统一内容柱：所有文字共用
   同一条左缘，split 分栏区块自行满宽。 */
/* Article column. Was full container width (2026-08-25); Kelvin reversed it
   2026-08-31 - 1280px lines plus a self-centring FAQ block read as unplanned.
   One centred measure, everything inside aligns to the same left edge. */
.docbody--solo { max-width: 820px; }
.prose-col { max-width: 820px; margin-inline: auto; }
@media (min-width: 1100px) {
  /* (the desktop full-width override died with the same decision) */
}
.prose-col p, .prose-col .lead { line-height: 1.55; }
.prose-col .ticks li + li { margin-top: 8px; }
/* 文章语境覆盖（2026-08-25）：
   1. 基础 .lead 的 62ch 上限在满宽正文里造成句中断层（Kota↵Laksamana）
   2. 正文改近黑 —— 长文阅读比灰绿的 muted/forest 舒服（Kelvin 试黑色） */
.prose-col .lead { max-width: none; }
.prose-col p, .prose-col .lead, .prose-col li { color: #1F2328; }
.prose-col .answer p { color: var(--ink); }
/* 2026-08-27 节奏对齐参考文章页：标题大而贴正文、段落紧凑、行距 1.5。
   段与段近、节与节远 —— 间距本身就是层级。 */
.prose-col > * + * { margin-top: 16px; }
.prose-col h2 {
  font-size: var(--fs-h2);
  margin-top: 12px;
  color: #1F2328;   /* 2026-08-27 Kelvin：文章内标题同正文近黑（参考页做法） */
}
.prose-col > div + div { margin-top: 56px; }
.docbody--solo > .prose-col + .prose-col { margin-top: 56px; }
.docbody--solo > .split { max-width: none; margin-top: 56px; }
.split {
  display: grid; gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
@media (min-width: 980px) {
  .split { grid-template-columns: minmax(0, 1.3fr) minmax(320px, 1fr); }
  .split .aside-card { position: sticky; top: 120px; }
}
.split-main { text-align: left; }
.split-main > * + * { margin-top: 24px; }
.aside-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: clamp(28px, 3vw, 40px);
  box-shadow: var(--shadow-lift);
}
.aside-card h2 { font-size: var(--fs-h2-md); }
.aside-card ul { list-style: none; margin: 24px 0 0; padding: 0; }
.aside-card li { display: flex; gap: 16px; }
.aside-card li + li { margin-top: 24px; }
.aside-card h3 { font-family: var(--font-display); font-size: 1.125rem; font-weight: 600; }
.aside-card li p { margin-top: 6px; font-size: var(--fs-small); color: var(--muted); }
.aside-mark {
  flex: none; display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--tint-blue); color: var(--ocean-type);
}
.aside-mark .ico { width: 16px; height: 16px; stroke-width: 2.5; }

/* ---------- Google reviews section (2026-08-21, Fitcom-pattern) ----------
   Real reviews pulled from both clinics' public Google profiles; names,
   dates and text verbatim. Layout follows the Fitcom homepage reviews
   band: score line, AI-summary card, then review cards. */
.gr-score {
  text-align: center; margin: 8px 0 32px;
  display: flex; gap: 14px; align-items: baseline; justify-content: center; flex-wrap: wrap;
}
.gr-score strong { font-family: var(--font-display); font-size: 2.25rem; }
.gr-clinic { display: inline-flex; align-items: baseline; gap: 8px; }
.gr-stars { color: var(--gold); font-size: 1.375rem; letter-spacing: 2px; }
.gr-count { color: var(--muted); }
.gr-ai {
  /* Widened 2026-08-31 (Kelvin): the 820px panel floated narrow above the
     full-width review strip. Its edges now line up with the first and last
     review card below (the strip's 72px arrow gutters), and the text keeps a
     readable measure inside via .gr-ai-text. */
  margin: 0 72px 40px;
  padding: clamp(24px, 3vw, 40px);
  background: var(--tint-blue);
  border-radius: var(--r-lg);
  text-align: center;
}
/* Kept, because it is a disclosure: these sentences are summarised from
   reviews rather than written by the clinic, and the reader is entitled to
   know that. Restyled off the uppercase-tracked eyebrow device so it reads as
   a label on the content rather than as decoration above a section. */
.gr-ai-kicker {
  margin: 0 0 12px;
  font-size: var(--fs-caption); font-weight: 600;
  letter-spacing: 0; text-transform: none;
  color: var(--ocean-type);
}
.gr-ai-text { font-size: var(--fs-lead); line-height: 1.6; max-width: 58rem; margin-inline: auto; }
.gr-chips {
  list-style: none; margin: 18px 0 0; padding: 0;
  display: flex; gap: 10px; justify-content: center; flex-wrap: wrap;
}
.gr-chips li {
  padding: 7px 16px;
  border: 1px solid var(--logo-blue-link);
  border-radius: var(--r-pill);
  color: var(--logo-blue-link); font-size: var(--fs-caption); font-weight: 600;
}
.gr-ai-note { margin-top: 16px; font-size: var(--fs-caption); color: var(--muted); font-style: italic; }
.gr-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 24px;
}
.gr-card header { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.gr-card header b { display: block; font-size: var(--fs-small); }
.gr-card header span:not(.gr-g) { font-size: var(--fs-caption); color: var(--muted); }
.gr-g {
  flex: none; display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 50%;
  border: 1px solid var(--line);
  font-weight: 700; font-size: 14px; color: var(--ocean-type);
}
.gr-stars-sm { margin: 10px 0 8px; color: var(--gold); letter-spacing: 2px; }
.gr-card > p:last-child { font-size: var(--fs-small); color: var(--ink-70); }

/* ---------- Knowledge cards (2026-08-21, reference blog grid) ----------
   Measured off the reference at 1512vp: 3-up, card 405x524, photo 269
   tall, 32px gaps, 24px serif title, white card with soft shadow. */
.kcards {
  display: grid; gap: 32px;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
}
.kcard {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: box-shadow var(--t-base) var(--ease), transform var(--t-base) var(--ease);
}
.kcard:hover { box-shadow: var(--shadow-lift); transform: translateY(-3px); }
@media (prefers-reduced-motion: reduce) { .kcard:hover { transform: none; } }
.kcard a { display: block; }
.kcard-media { height: 269px; }
.kcard-media img { width: 100%; height: 100%; object-fit: cover; }
.kcard-body { padding: 28px; }
/* h2 on the /knowledge hub (the cards are the page's top-level items, sitting
   directly under the h1), h3 on the homepage Resources row (that one sits
   under a section h2). Same look either way. */
.kcard-body h2,
.kcard-body h3 {
  font-family: var(--font-display);
  font-size: 1.5rem; font-weight: 600; line-height: 1.3;
  color: var(--ink);
}
.kcard-body p {
  margin-top: 12px;
  font-size: var(--fs-small); color: var(--muted);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.kcard-go {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 18px;
  font-weight: 600; font-size: var(--fs-small); color: var(--ocean-type);
}
.kcard:hover .kcard-go { text-decoration: underline; text-underline-offset: 3px; }

/* ---------- Byline chip + info lines (2026-08-21) ----------
   Replaces the label:value fact tables (client: too Wikipedia). Same
   credentials, one elegant line. */
.byline-chip {
  display: flex; align-items: center; gap: 14px;
  margin-top: 20px; padding: 14px 18px;
  background: var(--card); border-radius: var(--r-md);
}
.byline-avatar { width: 44px; height: 44px; flex: none; border-radius: 50%; font-size: 1rem !important; }
.byline-chip p { font-size: var(--fs-caption); color: var(--muted); line-height: 1.5; }
.byline-chip a { color: var(--ocean-type); font-weight: 600; }
.cred-line { margin-top: 14px; font-size: var(--fs-small); }
.info-lines { list-style: none; margin: 0; padding: 0; }
.info-lines li { display: flex; gap: 12px; align-items: flex-start; }
.info-lines li + li { margin-top: 14px; }
.info-lines .ico { flex: none; width: 20px; height: 20px; margin-top: 3px; color: var(--nature-fill); }
.info-lines a { color: var(--ocean-type); }

/* Related reading (2026-08-21, Fitcom-style internal mesh) */
.related-block ul { list-style: none; margin: 20px 0 0; padding: 0; }
.related-block li + li { margin-top: 12px; }
.related-block a { color: var(--ocean-type); font-weight: 500; text-decoration: underline; text-underline-offset: 3px; }

/* Review marquee removed 2026-08-31 (Kelvin). A photo-left framed version
   lived for an hour the same day and was also rejected - final form is the
   .rv-strip below: centred AI panel, one row of cards, side arrows. */

/* ---------- Reviews strip (2026-08-31, second pass) ----------
   Kelvin: no photo, AI summary back to its centred panel, reviews in ONE row,
   two cards per view, arrows flanking the row (reference: premier-arts style).
   The row is a native scroll-snap region, so touch swiping works on mobile for
   free and the buttons just scroll it one viewport at a time. */
/* The whole-section heading block leaves the stock 56px under the h2; with no
   lead line here that read as a hole, so this section tightens it. */
#reviews .sec-head { margin-bottom: 16px; }
#reviews .gr-score { margin-bottom: 24px; }

/* The strip reserves a 72px gutter each side and the arrows live inside it,
   so they can never sit on top of the review text. */
.rv-strip { position: relative; margin-top: 8px; padding-inline: 72px; }
.rv-view {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc(50% - 8px);
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding: 4px 2px;
}
.rv-view::-webkit-scrollbar { display: none; }
.rv-view .gr-card { scroll-snap-align: start; }
.rv-btn {
  position: absolute; top: 50%; transform: translateY(-50%);
  z-index: 2;
  display: grid; place-items: center;
  width: 48px; height: 48px;
  border: 1px solid var(--line); border-radius: 50%;
  background: var(--white); color: var(--ocean-type);
  box-shadow: var(--shadow-card);
  transition: background var(--t-base) var(--ease), opacity var(--t-base) var(--ease);
}
.rv-btn[data-dir="-1"] { left: 6px; }
.rv-btn[data-dir="1"] { right: 6px; }
.rv-btn[data-dir="-1"] .ico { transform: rotate(180deg); }
.rv-btn .ico { width: 20px; height: 20px; }
.rv-btn:hover { background: var(--tint-blue); }
.rv-btn:disabled { opacity: .35; pointer-events: none; }
@media (max-width: 860px) {
  /* Swipe territory: the arrows go, the gutters go, and a sliver of the next
     card stays visible as the swipe affordance. */
  .gr-ai { margin-inline: 0; }
  .rv-strip { padding-inline: 0; }
  .rv-btn { display: none; }
  .rv-view { grid-auto-columns: 88%; }
}



.gr-avatar {
  flex: none; display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: 50%;
  font-weight: 700; font-size: 1rem;
}
.gr-card header { align-items: center; }
.gr-card header > div { flex: 1; min-width: 0; }
.gr-glogo { flex: none; width: 22px; height: 22px; }
/* 评论附图（来自该则 Google 评论本身，2026-08-23 目验为诊所环境照，无人像） */
.gr-photo {
  margin-top: 14px;
  width: 100%; height: 150px;
  object-fit: cover;
  border-radius: var(--r-sm);
}
/* 头像换真图（评论者的公开 Google 头像，2026-08-23） */
img.gr-avatar { object-fit: cover; display: block; }

/* 下滑收起 / 上滑召回（2026-08-25）。收起动作放内层胶囊：
   nav 本体的 transform 被滚动变形（--p）占用，两者分层互不干扰。 */
.nav.nav-hidden .container { transform: translateY(calc(-100% - 24px)); }
@media (prefers-reduced-motion: reduce) {
  .nav .container { transition: none; }
}

/* ---------- FAQ page: jump-to sidebar + scrollspy (2026-08-25) ----------
   Measured off functionhealth.com/faq at 1512vp: kicker 11px/ls1.1
   uppercase, links 14/600 with colour-change active state, section heads
   34px, rows 62 tall / radius 6 / 12px apart, parchment bg + thin border. */
.faqpage { display: grid; gap: clamp(32px, 5vw, 80px); align-items: start; }
@media (min-width: 980px) {
  .faqpage { grid-template-columns: minmax(220px, 300px) minmax(0, 1fr); }
  .faqside { position: sticky; top: 120px; }
}
.faqside-kicker {
  margin: 0 0 16px;
  font-size: var(--fs-caption); font-weight: 600;
  letter-spacing: 0; text-transform: none;
  color: var(--muted);
}
.faqside-nav a {
  display: block; padding: 6px 0;
  font-size: 0.9375rem; font-weight: 600; color: var(--ink);
}
.faqside-nav a:hover { color: var(--ocean-type); }
.faqside-nav a.is-current { color: var(--ocean-type); text-decoration: underline; text-underline-offset: 4px; }
.faqgroup + .faqgroup { margin-top: 64px; }
.faqgroup h2 { font-size: var(--fs-h2-md); margin-bottom: 24px; }
/* 光学对齐：衬线字行高留白让字面比 Search 药丸顶低 ~6px，首组标题上提补偿 */
.faqmain > .faqgroup:first-of-type h2 { margin-top: -6px; }
.faq--rows { margin-inline: 0; }   /* 基础 .faq 的 22px 左缩进在这不适用（对齐修正 2026-08-25） */
/* .faq--rows item/q/a rules merged into the unified card recipe above. */
.faq--rows .faq-item.is-open .faq-a > div { padding-bottom: 18px; }

/* FAQ 极简 hero（2026-08-25，参考 Function）：只有斜体标题 + 一句话 */
.pagehead--slim { padding-bottom: clamp(24px, 3vw, 40px); }
.pagehead--slim h1 em { font-style: italic; color: var(--logo-green-type); }
.pagehead--slim .lead { margin-top: 12px; }

/* FAQ 搜索（2026-08-25，Function 式药丸框 · 打字即筛选） */
.faq-search {
  position: relative;
  margin-bottom: 28px;
}
.faq-search input {
  width: 100%;
  padding: 13px 48px 13px 20px;
  font: inherit; font-size: var(--fs-small);
  color: var(--ink);
  background: transparent;
  border: 1.5px solid var(--muted);
  border-radius: var(--r-pill);
}
.faq-search input:focus { outline: 2px solid var(--ocean-type); outline-offset: 1px; border-color: transparent; }
.faq-search .ico {
  position: absolute; right: 18px; top: 50%;
  transform: translateY(-50%);
  width: 20px; height: 20px; color: var(--ink);
  pointer-events: none;
}
.faq-noresult { color: var(--muted); display: none; }

/* ---------- Team page (2026-08-25, hellodentalclinic pattern) ----------
   Founder and co-founder each take a near-full-viewport section; the rest
   of the team renders as cards with a circular portrait overlapping the
   card top (reference style, our brand language). */
.team-hero { min-height: 72vh; display: grid; align-items: center; padding-block: clamp(48px, 7vw, 96px); }
.team-hero:nth-of-type(odd) { background: var(--paper); }
.team-hero-grid {
  display: grid; gap: clamp(32px, 5vw, 72px); align-items: center;
}
@media (min-width: 900px) {
  .team-hero-grid { grid-template-columns: minmax(280px, 420px) minmax(0, 1fr); }
  .team-hero--flip .team-hero-grid { grid-template-columns: minmax(0, 1fr) minmax(280px, 420px); }
  .team-hero--flip .team-hero-media { order: 2; }
}
.team-hero-media .monogram {
  max-width: none; aspect-ratio: 1;
  border-radius: 50%;
  font-size: clamp(4rem, 8vw, 6.5rem);
}
.team-hero-body h2 { font-size: var(--fs-h2-xl); }
.team-hero-body .lead { margin-top: 16px; }
.team-hero-body .cta-actions { margin-top: 28px; }
.team-hero-body p + p { margin-top: 14px; }

.tcards {
  display: grid; gap: 96px 32px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 420px));
  justify-content: center;
  /* 头像上探 64px 会吃掉间距 —— 132 = 64 补偿 + 68 呼吸位 */
  margin-top: 132px;
}
.tcard {
  position: relative;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 96px 32px 32px;
  text-align: center;
}
.tcard-avatar {
  position: absolute; top: -64px; left: 50%;
  transform: translateX(-50%);
  width: 128px; height: 128px;
}
.tcard-avatar .monogram {
  width: 128px; height: 128px; max-width: none;
  border-radius: 50%;
  border: 4px solid var(--white);
  box-shadow: var(--shadow-card);
  font-size: 2.5rem;
}
.tcard h3 { font-family: var(--font-display); font-size: 1.5rem; font-weight: 600; color: var(--ocean-type); }
.tcard-role { margin-top: 6px; font-weight: 600; font-size: var(--fs-small); }
.tcard-bio { margin-top: 14px; font-size: var(--fs-small); color: var(--ink-70); text-align: left; }
.tcard-cred { margin-top: 14px; font-size: var(--fs-caption); }

/* 分店照取代地图（2026-08-28 Kelvin）。照片拉伸到与右侧文字块同高，
   靠 grid 的 stretch 对齐，两栏顶底齐平。 */
.branch-photo {
  align-self: stretch;
  aspect-ratio: auto;   /* 解除 map-wrap 的 16:10，高度交给 grid 与文字块对齐 */
  height: 100%; min-height: 0;
}
.branch-photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: var(--r-lg);
  display: block;
}

/* CRO 2026-08-28：冷流量 5 秒测试 —— 品牌线上方一行事实 eyebrow */
.hero-eyebrow {
  font-size: 0.9rem; font-weight: 600;
  letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--ocean-type);
  margin-bottom: 14px;
}
/* 末端 CTA 的 proof 回声（决策点旁放证据） */
.cta-band .cta-proof { margin-top: 10px; font-size: var(--fs-caption); color: rgba(250, 248, 243, .75); }


/* 真人头像圆形版（2026-08-28 · Cindy 照片自 BNI） */
.portrait--round {
  max-width: none; width: 100%;
  aspect-ratio: 1; object-fit: cover;
  border-radius: 50%;
  box-shadow: var(--shadow-lift);
}

/* ---------- Stat row (2026-08-28, open editorial · GSAP count-up) ----------
   No boxes: numbers sit on the page, hairline dividers, one gold star as
   the single distinctive touch. */
.stat-strip { padding-block: clamp(36px, 4.5vw, 56px); }
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: clamp(24px, 3vw, 40px);
}
.stat { text-align: center; }
@media (min-width: 900px) {
  .stat + .stat { border-left: 1px solid var(--line); }
}
.stat b {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 4.6vw, 4rem);
  font-weight: 600; line-height: 1;
  color: var(--forest);
  font-variant-numeric: tabular-nums;   /* count-up 时数字不抖 */
}
.stat-star { color: var(--gold); font-size: 0.55em; vertical-align: 0.45em; margin-left: 6px; }
.stat-label { display: block; margin-top: 10px; font-size: var(--fs-caption); color: var(--muted); line-height: 1.45; }

/* Rich section head (2026-08-28, reference: kicker + big serif + lead) */
.sec-head--rich h2 { font-size: var(--fs-h2); }
.sec-head--rich .lead { margin: 14px auto 0; max-width: 640px; }

/* ── straightteeth 阶梯改版新区块（2026-08-28）────────────── */
/* Why Choose Us 暗带：节奏抄参考站 team1，色温回品牌 forest */
.why-tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 48px 44px;
  max-width: 1080px;
  margin: 52px auto 0;
  text-align: center;
}
.why-tile { display: flex; flex-direction: column; align-items: center; }
.why-tile-mark {
  display: grid; place-items: center;
  width: 64px; height: 64px;
  border-radius: 50%;
  background: var(--nature);
  color: var(--forest);
  margin-bottom: 16px;
}
.why-tile-mark .ico { width: 30px; height: 30px; }
.why-tile h3 {
  font-family: var(--font-display);
  font-size: 1.3rem; font-weight: 600; line-height: 1.3;
  color: var(--paper);
}
.why-tile p {
  margin-top: 8px;
  font-size: var(--fs-small); line-height: 1.5;
  color: rgba(250, 248, 243, .72);
  max-width: 30ch;
}
.section--ink .sec-head--rich .ph-kicker { color: var(--nature); }

/* Same-Day Technology 卡（参考「Advanced Technology」卡：白卡32圆角 · 图左满贴） */
.tech-card {
  background: var(--white);
  border-radius: 32px;
  box-shadow: var(--shadow-card);
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  align-items: center;
}
.tech-card-media { height: 100%; }
.tech-card-media .ph { height: 100%; min-height: 460px; border-radius: 0; }
.tech-card-body {
  padding: clamp(40px, 5vw, 72px) clamp(32px, 5vw, 88px)
           clamp(40px, 5vw, 72px) clamp(28px, 3.5vw, 64px);
}
.tech-card-body h2 { font-size: var(--fs-h2); line-height: 1.2; margin-top: 10px; }
.tech-card-body > p { margin-top: 18px; color: var(--ink-70); max-width: 56ch; }
.tech-card-body .tech-lead-in { margin-top: 22px; color: var(--ink); font-weight: 600; }
.tech-list { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 12px; }
.tech-list li { display: flex; gap: 14px; align-items: center; }
.tech-badge {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px;
  border-radius: 10px;
  background: var(--tint-green);
  color: var(--logo-green-link);
}
.tech-badge .ico { width: 18px; height: 18px; }
.tech-ctas { margin-top: 28px; display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
.tech-more {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: 600; font-size: var(--fs-small);
  color: var(--ocean-type);
}
.tech-more:hover { text-decoration: underline; text-underline-offset: 3px; }

/* See the Difference · 拖动对比滑块（2026-08-28 参考站二稿） */
.ba-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  gap: clamp(32px, 4.5vw, 72px);
  align-items: center;
}
.ba-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 32px;
  box-shadow: var(--shadow-card);
  padding: clamp(18px, 1.8vw, 26px);
}
.ba-wrap {
  --x: 50%;
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: 20px;
  overflow: hidden;
  cursor: ew-resize;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.ba-layer { position: absolute; inset: 0; }
.ba-layer img { width: 100%; height: 100%; object-fit: cover; display: block; -webkit-user-drag: none; user-select: none; pointer-events: none; }
.ba-before { clip-path: inset(0 calc(100% - var(--x)) 0 0); }
.ba-tag {
  position: absolute; top: 14px;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  background: rgba(31, 35, 40, .68);
  color: #fff;
  font-size: 0.8rem; font-weight: 600; letter-spacing: .04em;
  pointer-events: none;
}
.ba-tag--before { left: 14px; }
.ba-tag--after { right: 14px; }
.ba-line {
  position: absolute; top: 0; bottom: 0; left: var(--x);
  width: 2px; margin-left: -1px;
  background: var(--gold);
  pointer-events: none;
}
.ba-handle {
  position: absolute; top: 50%; left: var(--x);
  transform: translate(-50%, -50%);
  width: 44px; height: 44px;
  border-radius: 50%;
  background: var(--gold);
  color: var(--forest);
  display: grid; place-items: center;
  box-shadow: var(--shadow-card);
  pointer-events: none;
}
.ba-body h2 { font-size: var(--fs-h2); }
.ba-body .lead { margin-top: 16px; }
.ba-body > p:not(.lead) { margin-top: 14px; color: var(--ink-70); max-width: 52ch; }

.kcards--home { margin-top: 44px; }

@media (max-width: 1000px) {
  .tech-card, .ba-grid { grid-template-columns: 1fr; }
  .tech-card-media .ph { min-height: 260px; }
  .why-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 36px 28px; }
}

@media (max-width: 640px) {
  /* Two compact columns instead of one tall single-file stack (Kelvin
     2026-08-31, reference: premier-arts why-grid). Nine tiles = 4 rows of
     two plus the last one centred full-width. */
  .why-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 14px; }
  .why-tile:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .why-tile-mark { width: 48px; height: 48px; margin-bottom: 10px; }
  .why-tile-mark .ico { width: 22px; height: 22px; }
  .why-tile h3 { font-size: 1.05rem; }
  .why-tile p { font-size: var(--fs-caption); }
}

/* Locations 卡（复用 about-card 版式 + tech-list 图标行） */
.loc-list { margin-top: 24px; }
.loc-list b { font-weight: 600; }
.about-card-media a { display: block; height: 100%; }
.about-card-body > .btn { margin-top: 30px; }

/* Why 带收尾句（原 promise 目的句并入） */
.why-close {
  margin: 52px auto 0;
  max-width: 56ch;
  text-align: center;
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: rgba(250, 248, 243, .84);
}

/* FAQ 预览 · 左标题右白卡（2026-08-28 参考版式） */
.faqp-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  gap: clamp(32px, 4.5vw, 80px);
  align-items: start;
}
.faqp-head h2 { font-size: var(--fs-h2-xl); line-height: 1.15; }
.faqp-head .ph-kicker { margin-bottom: 10px; }
.faqp-head .lead { margin-top: 18px; max-width: 34ch; }
.faqp-head .btn { margin-top: 28px; }
.faq-cards { max-width: none; margin-inline: 0; display: grid; gap: 18px; }
.faq-cards .faq-item {
  border-bottom: 0;
  background: var(--white);
  border-radius: 22px;
  box-shadow: var(--shadow-card);
  padding: 8px 28px;
}
.faq-cards .faq-q {
  min-height: 64px;
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--ocean-type);
}
.faq-cards .faq-item.is-open .faq-a > div { padding-bottom: 22px; }
.faq-cards .faq-q .ico {
  flex: none;
  width: 36px; height: 36px;
  padding: 8px;
  box-sizing: border-box;
  background: var(--surface);
  border-radius: 50%;
}
.faq-cards .faq-item.is-open .faq-q .ico { background: var(--nature); color: var(--forest); }
@media (max-width: 1000px) {
  .faqp-grid { grid-template-columns: 1fr; }
}

/* CTA 卡（2026-08-28 参考 Contact 卡式 · 复用 tech-card 骨架） */
.tech-card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cta-card .cta-proof { margin-top: 14px; font-size: var(--fs-small); color: var(--muted); }
@media (max-width: 1000px) {
  .tech-card-media img { aspect-ratio: 16 / 10; height: auto; }
}

/* Real in-house laboratory photograph (client supplied 2026-08-30), filling
   slots that are portrait on desktop (0.77), landscape on the services hub
   (1.33) and on mobile (1.26), from one 1.67 landscape original. Cover plus a
   left-of-centre anchor keeps the milling unit - the thing that makes the
   same-day claim true - in frame at every one of those ratios. Centring it
   would crop the machine out on the desktop portrait slot. */
.lab-photo {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 26% center;
  display: block;
}
.tech-card-media .lab-photo { min-height: 460px; }
/* The services hub slot is 1.33 where the homepage one is 0.77, so it needs its
   own anchor: at 48% the frame reaches the etched "Dental Laboratory" door and
   still holds the milling unit. Same photo, three ratios, three anchors. */
.svc-detail-media .lab-photo { object-position: 48% center; }
@media (max-width: 860px) {
  .tech-card-media .lab-photo { min-height: 260px; }
  .lab-photo { object-position: 62% center; }
}

/* Named section eyebrow, used deliberately and sparingly - not the retired
   per-section .ph-kicker. It survives on the locations block because "Where to
   Find Us" states the section's job, which the heading ("Two clinics across
   Melaka") does not; the ones removed on 2026-08-30 were restating their own
   heading. Two on the page (hero, locations) is voice; thirteen was grammar. */
/* p.sec-eyebrow, not .sec-eyebrow: inside the locations card it competes with
   .about-card-body p, which is also (0,1,1) and would otherwise repaint it
   --ink-70 and add a 22px top margin. Matching specificity plus later in the
   file wins cleanly, without a doubled-class hack. */
p.sec-eyebrow {
  margin: 0 0 10px;
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--ocean-type);
}

/* Generated stand-in, not a photograph of this clinic. Anchored right of centre
   because the source frames her right of a wide empty wall, and the desktop
   slot crops to 0.98 - centring it would fill a third of the card with blank
   wall. Replace with a real front-desk photograph before launch. */
.reception-photo {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 68% center;
  display: block;
}
@media (max-width: 860px) { .reception-photo { object-position: 60% center; } }
