/* BRS+ Medical Clinic — implementation of `BRS Clinic Website.dc.html`.
   Tokens and measurements are taken from the design's 1440px artboards;
   the breakpoints below are additions (the design is desktop-only). */

:root {
  /* Brand.
     --teal stays the original brand colour, but it only ever fills large
     shapes now. Text and buttons use --teal-ink, darkened from #0FA8A1 to
     #0A7D78 so white-on-teal reaches 4.98:1 instead of failing at 2.42:1.
     The hue is unchanged, so the page still reads as the same brand. */
  --teal: #0FBAB2;
  --teal-ink: #0A7D78;
  --teal-deep: #0A7D78;
  --teal-soft: #5ecfc8;

  /* Dark surfaces */
  --ink: #0B2B29;
  --ink-raised: #12403d;
  --ink-line: #2f5b58;
  --on-dark: #b9d8d5;
  --on-dark-mute: #8fbdb9;
  --on-dark-soft: #cfeae8;
  --on-dark-faint: #6f9c99;
  --on-dark-legal: #6f9c99;
  --on-dark-util: #9fd8d4;
  --on-dark-label: #8fcfca;

  /* Text on light */
  --text: #26403e;
  --body: #4a5f5e;
  --body-mute: #5f7271;
  --label: #647473;
  --muted: #5f6f6e;

  /* Lines and tints */
  --line: #e2eeed;
  --line-soft: #e6eeed;
  --line-strong: #cfe6e4;
  --tint: #f4fbfa;
  --tint-mint: #e6f7f6;
  --tint-sage: #e6f4f3;
  --tint-pale: #f8fdfd;

  --gutter: 56px;
  --maxw: 1440px;
  --radius: 16px;

  --display: 'Anuphan', 'IBM Plex Sans Thai', system-ui, sans-serif;
  --sans: 'IBM Plex Sans Thai', system-ui, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Surfaces. Split out of --ink, which used to mean both "dark panel" and
     "strong text" — two things that must move in opposite directions when the
     palette inverts. */
  --surface: #fff;        /* the page */
  --surface-2: #fff;      /* cards sitting on the page */
  --surface-inv: #0B2B29; /* the dark bands, footer and utility bar */
  --on-inv: #fff;         /* text on those */
  --on-accent: #fff;      /* text on a filled accent button */
  --teal-hover: #086B66;

  /* Frosted surfaces. 85% is not a style choice: it is the floor at which the
     teal accent still clears 4.5:1 over the darkest thing that scrolls under
     the bar. See "Glass" in the README for the measured numbers. */
  --surface-glass: rgba(255, 255, 255, .85);
  --glass: blur(16px) saturate(1.4);

  /* Open / closing-soon / closed pills. Paired bg+fg so each mode stays legible. */
  --ok-bg: #e3f6ec;   --ok-fg: #1a6b41;
  --warn-bg: #fdf0dd; --warn-fg: #8a5410;
  --off-bg: #f2f1f0;  --off-fg: #5c5f5e;

  /* One elevation scale instead of five hand-tuned shadows. Tinted with the
     brand's dark green rather than pure black, so shadows sit in the palette. */
  --shadow-sm: 0 1px 2px rgba(11, 43, 41, .04), 0 2px 8px rgba(11, 43, 41, .04);
  --shadow-md: 0 2px 4px rgba(11, 43, 41, .05), 0 8px 24px rgba(11, 43, 41, .08);
  --shadow-lg: 0 4px 8px rgba(11, 43, 41, .06), 0 18px 40px rgba(11, 43, 41, .14);
  --shadow-accent: 0 8px 28px rgba(10, 125, 120, .18);

  --ease: cubic-bezier(.2, .6, .3, 1);
}

/* Tell the browser which form-control palette to render, and let the OS know
   the page has a dark treatment. */
:root { color-scheme: light dark; accent-color: var(--teal-ink); }

/* ── Dark mode ───────────────────────────────────────────────────
   Only the tokens change; no component rule is duplicated. The accent has to
   get LIGHTER here — #0A7D78 passes on white but fails on a dark surface, so
   dark mode uses #5CD3C9 (8.1:1 on --surface). */
@media (prefers-color-scheme: dark) {
  :root {
    --surface: #0C1A19;
    --surface-2: #122523;
    --surface-inv: #081412;
    --on-inv: #eaf5f3;
    --surface-glass: rgba(12, 26, 25, .85);

    --teal: #16C4BB;
    --teal-ink: #5CD3C9;
    --on-accent: #06211F;  /* dark label on the light accent */
    --teal-hover: #7fe0d8;
    --teal-deep: #5CD3C9;
    --teal-soft: #7fe0d8;

    --ink: #E8F4F2;
    --text: #dbe9e7;
    --body: #b9cdcb;
    --body-mute: #a3b8b6;
    --label: #94a9a7;
    --muted: #93a8a6;

    --line: #22403d;
    --line-soft: #1d3735;
    --line-strong: #2c4f4b;

    --tint: #10201F;
    --tint-mint: #14332F;
    --tint-sage: #132A28;
    --tint-pale: #0F1E1D;

    --ink-raised: #17302D;
    --ink-line: #2b4d49;
    --on-dark: #c3d9d6;
    --on-dark-mute: #a9c4c1;
    --on-dark-legal: #8fa9a6;

    --ok-bg: #102E1E;   --ok-fg: #6EE7A6;
    --warn-bg: #33240D; --warn-fg: #F2C078;
    --off-bg: #1C2322;  --off-fg: #A6B2B1;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow-md: 0 2px 4px rgba(0, 0, 0, .4), 0 8px 24px rgba(0, 0, 0, .35);
    --shadow-lg: 0 4px 8px rgba(0, 0, 0, .45), 0 18px 40px rgba(0, 0, 0, .5);
    --shadow-accent: 0 8px 28px rgba(22, 196, 187, .16);
  }
  /* Photographs are a touch bright against a dark page. */
  .card__photo img, .branchrow__photo img, .minibranch__photo img,
  .pagehero__figure img { filter: brightness(.92) contrast(1.02); }
  .branchmap, .branchrow__mapframe { filter: brightness(.9); }
}

*, *::before, *::after { box-sizing: border-box; }

/* Cross-document view transitions: navigating between pages cross-fades
   instead of flashing white. Chrome/Edge/Safari honour it, everything else
   ignores it — no fallback needed. */
@view-transition { navigation: auto; }

/* In-page anchors (#quote, #nearest, #branch-01) glide, and stop underneath
   the sticky bar rather than behind it. */
html { scroll-behavior: smooth; scroll-padding-top: 96px; }

::selection { background: color-mix(in srgb, var(--teal) 30%, transparent); }

body {
  margin: 0;
  background: var(--surface);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
}

/* Must outrank the component rules that set `display` — collapsible panels are
   hidden with the `hidden` attribute, and a plain `display:flex` would win. */
[hidden] { display: none !important; }

img { max-width: 100%; }
a { color: var(--teal-ink); text-decoration: none; }
a:hover { color: var(--ink); }
h1, h2, h3 { margin: 0; }
address { font-style: normal; }

:focus-visible {
  outline: 3px solid var(--teal-ink);
  outline-offset: 2px;
  border-radius: 4px;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: -9999px;
  z-index: 100;
  padding: 12px 20px;
  background: var(--surface-inv);
  color: #fff;
  border-radius: 0 0 10px 0;
}
.skip-link:focus { left: 0; top: 0; color: #fff; }

/* ── Shared type ─────────────────────────────────────────── */

.display {
  font-family: var(--display);
  font-weight: 600;
  color: var(--ink);
  /* Scales with the viewport, so the breakpoint overrides below are no longer
     doing the work; Thai display type also needs slightly tighter tracking. */
  font-size: clamp(26px, 1.4rem + 1.4vw, 38px);
  line-height: 1.28;
  letter-spacing: -0.005em;
  text-wrap: balance;
}
.display--xl { font-size: clamp(32px, 1.5rem + 2.6vw, 52px); line-height: 1.18; }
.display--lg { font-size: clamp(30px, 1.5rem + 2vw, 46px); line-height: 1.2; }
.display--sm { font-size: clamp(25px, 1.35rem + 1.1vw, 34px); }
.band--dark .display, .band--dark .display--lg { color: #fff; }

.eyebrow {
  font-size: 14px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--teal-ink);
  font-weight: 600;
}
/* The "+" in BRS+ appeared in exactly one place on the whole site: the logo.
   It is an owned, medically-coded, purely geometric mark -- the cheapest way
   to make these pages read as authored rather than templated, and it costs
   nothing to download. Two uses only; a motif stops being a signature once it
   is everywhere.

   The `/ ""` gives the pseudo-element empty alt text so screen readers do not
   announce "plus" before every section label. */
.eyebrow::before {
  content: '+' / '';
  margin-right: .5em;
  font-weight: 700;
}
.eyebrow--on-dark { color: var(--teal-soft); }

/* Use 2: a plus field on the dark band.
   It was on .band--tint first, which was wrong: --label and the teal link
   colour sit at roughly 4.2-4.5:1 on that tint already, so ANY texture behind
   them drops below AA -- even at 5% opacity (measured 4.38 and 4.46). The dark
   band's text is --on-inv at 15:1, which has the headroom to carry a pattern
   and is the most striking section on the page anyway. */
.band--dark { position: relative; isolation: isolate; overflow: hidden; }
.band--dark > * { position: relative; z-index: 1; }
.band--dark::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #fff;
  opacity: .07;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='64' height='64'%3E%3Cpath d='M32 26v12M26 32h12' stroke='%23000' stroke-width='1.6' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='64' height='64'%3E%3Cpath d='M32 26v12M26 32h12' stroke='%23000' stroke-width='1.6' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
  -webkit-mask-size: 64px 64px;
  mask-size: 64px 64px;
  pointer-events: none;
}
@supports not ((mask-image: none) or (-webkit-mask-image: none)) {
  .band--dark::before { display: none; }
}
@media print { .band--dark::before { display: none; } }
.eyebrow--sm { font-size: 15px; letter-spacing: .14em; }

.lead {
  margin: 0;
  font-size: 19px;
  line-height: 1.75;
  color: var(--body);
  max-width: 560px;
  text-wrap: pretty;
}
.lead--on-dark { color: var(--on-dark); font-size: 18px; max-width: 520px; }
.lead--wide { max-width: 720px; }
.lead--narrow { font-size: 18px; color: var(--body-mute); max-width: 440px; }

.fineprint {
  font-size: 15px;
  color: var(--muted);
  line-height: 1.7;
}

.link-more { font-size: 16px; font-weight: 600; }
.fineprint--center { text-align: center; margin: 28px auto 0; max-width: 620px; }

/* ── Prices ──────────────────────────────────────────────── */

.card__price {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 600;
  color: var(--teal-ink);
  margin-top: auto;
}
/* "เริ่มต้น / From" reads as a qualifier, not part of the number. */
.price__from {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  color: var(--body-mute);
  margin-right: 5px;
}
.servicerow__price .price__from { font-size: 14px; }
/* Quote-only services shouldn't shout as loudly as a real number. */
.card__price--ask {
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 500;
  color: var(--body-mute);
}

.servicerow__price {
  font-family: var(--display);
  font-size: 24px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  text-align: right;
}
.servicerow__price--ask {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 500;
  color: var(--body-mute);
  max-width: 170px;
  white-space: normal;
}

/* ── Open / closed status ────────────────────────────────── */

.statusline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
}
.status::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}
/* Preparation a visitor must do BEFORE arriving. Flagged on the row itself,
   not only in the FAQ: someone who reads "฿1,190" and books has already made
   the decision, and finding out about the 8-hour fast afterwards costs them
   the trip. Warning colours, because this one is a cost of getting it wrong. */
.servicerow__prep {
  display: block;
  margin-top: 6px;
  padding: 7px 10px;
  border-radius: 9px;
  background: var(--warn-bg);
  color: var(--warn-fg);
  font-size: 13px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}

/* FAQ. <details> rather than a custom accordion: it is searchable by the
   browser's own find-in-page, works with no JS, and prints expanded. */
.faq { display: grid; gap: 10px; }
.faq__item {
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface-2);
  box-shadow: var(--shadow-sm);
}
.faq__q {
  cursor: pointer;
  list-style: none;
  padding: 16px 48px 16px 18px;
  font-weight: 600;
  color: var(--ink);
  position: relative;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after {
  content: '';
  position: absolute;
  right: 20px;
  top: 50%;
  width: 9px;
  height: 9px;
  margin-top: -6px;
  border-right: 2px solid var(--teal-ink);
  border-bottom: 2px solid var(--teal-ink);
  transform: rotate(45deg);
  transition: transform .2s var(--ease);
}
.faq__item[open] .faq__q::after { transform: rotate(-135deg); margin-top: -2px; }
.faq__a {
  padding: 0 18px 18px;
  color: var(--body);
  line-height: 1.7;
  overflow-wrap: anywhere;
  /* Branch-derived answers are one line per branch. */
  white-space: pre-line;
}

/* Per-branch practicalities on /branches: which insurers the counter takes and
   where to leave the bike. Both differ by branch, so they belong on the card
   rather than in a single FAQ answer. */
.branchfacts { display: grid; gap: 8px; margin-top: 4px; }
.branchfact { display: flex; gap: 8px; font-size: 14px; line-height: 1.6; }
.branchfact__k { color: var(--label); flex: none; }
.branchfact__v { color: var(--body); min-width: 0; overflow-wrap: anywhere; }
@media print { .faq__item { break-inside: avoid; } .faq__a { display: block !important; } }

/* The reassurance line above the booking button. Quiet, but not fineprint:
   "we store nothing" is the reason someone finishes this form. */
.formnote--calm {
  background: var(--tint-mint);
  border-radius: 12px;
  padding: 12px 14px;
  color: var(--body);
  font-size: 14px;
  line-height: 1.6;
}
.plainlist { list-style: none; padding: 0; margin: 10px 0 0; display: grid; gap: 6px; font-size: 15px; }

.status__detail[hidden] { display: none; }
.status__detail {
  font-size: 13px;
  font-weight: 600;
  color: var(--body);
}
/* Demoted by hours.js once the live badge is showing, so the schedule never
   out-shouts the state. */
.pill.is-secondary,
.contactcard__hours.is-secondary {
  opacity: .72;
  font-weight: 400;
}
.status.is-open { background: var(--ok-bg); color: var(--ok-fg); }
.status.is-soon { background: var(--warn-bg); color: var(--warn-fg); }
.status.is-closed { background: var(--off-bg); color: var(--off-fg); }

/* ── Licence details ─────────────────────────────────────── */

.licence {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2px 12px;
  margin: 4px 0 0;
  padding-top: 14px;
  border-top: 1px dashed var(--line-strong);
  font-size: 14px;
}
.licence dt { color: var(--label); }
.licence dd { margin: 0; color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
/* One click selects the whole number, ready to paste into the MOPH registry. */
.licence__no { user-select: all; }
.licence__verify { font-size: 14px; font-weight: 600; margin-left: 10px; white-space: nowrap; }
.licencecard .licence__verify { margin: 8px 0 0; display: inline-block; }

.licencegrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.licencecard {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.licencecard__name { font-size: 18px; font-weight: 600; color: var(--ink); line-height: 1.45; }
.licencecard__addr { font-size: 15px; color: var(--body-mute); line-height: 1.6; }
.licencecard .licence { margin-top: 8px; }

.pill {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--tint-mint);
  color: var(--teal-deep);
  font-size: 14px;
  font-weight: 600;
}

/* ── Buttons ─────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 52px;
  padding: 0 26px;
  border: 1.5px solid transparent;
  border-radius: 999px;
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
/* --on-accent flips with the accent: white on the dark teal in light mode,
   near-black on the light teal dark mode uses. */
.btn--primary { background: var(--teal-ink); color: var(--on-accent); }
.btn--primary:hover { background: var(--teal-hover); color: var(--on-accent); }

.btn--outline { border-color: var(--line-strong); color: var(--ink); background: transparent; }
.btn--outline:hover { border-color: var(--teal); color: var(--ink); }

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

.btn--onDark { border-color: var(--ink-line); color: var(--on-dark-soft); background: transparent; }
.btn--onDark:hover { border-color: var(--teal); color: #fff; }

.btn--xs { height: 42px; padding: 0 14px; font-size: 14px; border-radius: 10px; flex: 1; }
.btn--sm { height: 46px; padding: 0 20px; font-size: 15px; }
.btn--lg { height: 54px; padding: 0 28px; font-size: 17px; }
.btn--block { width: 100%; }

/* ── Utility bar + masthead ──────────────────────────────── */

.utility { background: var(--surface-inv); color: var(--on-dark-util); font-size: 13px; }
.utility__inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 10px var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.utility__facts { display: flex; gap: 24px; flex-wrap: wrap; }
.utility__lang {
  display: flex;
  gap: 4px;
  align-items: center;
  padding: 2px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .09);
}
.utility__lang span,
.utility__lang a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 46px;
  min-height: 28px;
  padding: 0 12px;
  border-radius: 999px;
  font-size: 13px;
  line-height: 1;
}
.utility__lang .is-on { background: var(--on-inv); color: var(--surface-inv); font-weight: 600; }
.utility__lang .is-off { color: #dff1ef; }
.utility__lang .is-off:hover { background: rgba(255, 255, 255, .14); color: #fff; }

/* Sticky, frosted. The point is the two call buttons staying reachable; the
   blur is what stops the bar reading as an opaque slab dropped on the content.
   z-index clears Leaflet, whose controls sit at 800-1000 inside the map. */
.masthead {
  position: sticky;
  top: 0;
  z-index: 1000;
  background: var(--surface-glass);
  -webkit-backdrop-filter: var(--glass);
  backdrop-filter: var(--glass);
  border-bottom: 1px solid var(--line-soft);
}
/* Firefox without the pref, and Safari before 9: an 85% wash with no blur is
   still legible, but be opaque rather than gamble on what shows through. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .masthead { background: var(--surface); }
}
@media print { .masthead { position: static; background: #fff; backdrop-filter: none; } }
.masthead__inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 18px var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.masthead__logo { display: block; flex: none; }
.masthead__logo picture { display: block; }
.masthead__logo img { height: 44px; width: auto; display: block; }

.masthead__toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 46px; height: 46px;
  padding: 0 11px;
  background: transparent;
  border: 1.5px solid var(--line-strong);
  border-radius: 10px;
  cursor: pointer;
}
.masthead__toggle span { display: block; height: 2px; background: var(--ink); border-radius: 2px; }

.nav { display: flex; gap: 32px; font-size: 16px; color: var(--text); font-weight: 500; }
.nav__link {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  color: inherit;
}
.nav__link:hover { color: var(--teal-ink); }
/* Teal text measures 4.98:1 on solid white -- too little headroom to survive
   being diluted by the frosted bar, where it drops to 3.72:1 over the darkest
   backdrop that scrolls under. Weight plus the rule below carry "current" here
   instead; the underline is a graphic, so 3.72:1 clears its 3:1 bar. */
.nav__link.is-active { color: var(--ink); font-weight: 600; }
.nav__link.is-active::after {
  content: '';
  height: 2px;
  align-self: stretch;
  background: var(--teal-ink);
}
.masthead__cta { display: flex; gap: 10px; flex: none; }
/* Same reason: an outlined button is transparent, so its teal label inherits
   whatever is behind the glass. Give it the page surface to sit on. */
.masthead .btn--ghost { background: var(--surface); }

/* An open mobile menu is a panel of links over live content -- readable only
   because it stops being translucent. Browsers without :has() keep the frosted
   bar, which still clears AA for the link text. */
.masthead:has(.nav.is-open) {
  background: var(--surface);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* ── Home hero ───────────────────────────────────────────── */

.hero {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: linear-gradient(180deg, var(--tint), var(--surface));
}
.hero__copy {
  padding: 72px var(--gutter);
  display: flex;
  flex-direction: column;
  gap: 22px;
  justify-content: center;
  max-width: calc(var(--maxw) / 2);
  margin-left: auto;
  width: 100%;
}
.hero__copy .lead { max-width: 520px; }
.hero__actions { display: flex; gap: 12px; padding-top: 6px; flex-wrap: wrap; }
/* Three columns, not a flex row. A flex row makes every label compete for one
   line: the moment one of them grows, a sibling is pushed onto a second row and
   the three facts read as 2 + 1. Equal columns let a long label wrap inside its
   own cell instead, which is also what keeps Thai and English in step -- the
   English labels are consistently wider. */
.hero__stats {
  display: grid;
  /* Explicit 3 up, 2 down. auto-fit was dropping to two columns around 1100px
     while the hero was still side-by-side, which put the three facts back into
     the 2 + 1 shape this grid exists to avoid. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px 28px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
  margin-top: 10px;
}
.hero__stats > * { min-width: 0; }
@media (max-width: 560px) {
  .hero__stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.stat { display: flex; flex-direction: column; gap: 4px; }
.stat__k {
  font-family: var(--display);
  /* Shrinks on narrow columns so a three-word label does not become three lines. */
  font-size: clamp(21px, 1.7vw, 28px);
  font-weight: 600;
  color: var(--teal-ink);
  line-height: 1.25;
  /* NOT `anywhere`: Thai has no word spaces, so `anywhere` broke มืออาชีพ into
     มือ / อาชีพ. `break-word` keeps Chrome's Thai dictionary breaking and only
     falls back to a hard break when a run genuinely cannot fit. */
  overflow-wrap: break-word;
}
.stat__v { font-size: 14px; color: var(--label); }

/* No background of its own — the photo sits on the same gradient as the copy
   column, so the two halves of the hero read as one surface. (The design gave
   this side its own radial gradient; changed at the client's request.) */
.hero__figure {
  /* Mirrors .hero__copy. The gradient is full-bleed, but the photo has to stay
     next to the words: without this the figure centres inside the whole right
     half, so the gap between copy and photo grew with the viewport -- 40px at
     1440, 1600px at 7680 (a 25% browser zoom on a wide screen). */
  max-width: calc(var(--maxw) / 2);
  margin-right: auto;
  width: 100%;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px var(--gutter) 48px 0;
}
.hero__figure img { width: 100%; max-width: 632px; height: auto; display: block; }

/* ── Hero branch mosaic ──────────────────────────────────────────
   Replaces a single stock photograph. The four shopfronts are the most
   persuasive images the clinic owns and were previously buried at the foot of
   the page at a quarter of this size, while the thing above the fold was a
   stock group shot that reads as AI-generated -- which in 2026 costs trust on
   a healthcare site rather than building it.

   It is also the primary task made visible: "which branch, is it open". Each
   tile is a link, and the badge is live. */
.heromosaic {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  width: 100%;
  max-width: 632px;
  align-self: center;
  position: relative;
}
/* The second column drops half a tile. Four equal boxes in a perfect square
   read as a contact sheet; the offset makes it a composition. */
.heromosaic__tile:nth-child(even) { transform: translateY(26px); }

.heromosaic__tile {
  position: relative;
  display: block;
  border-radius: 16px;
  overflow: hidden;
  background: var(--tint-mint);
  box-shadow: var(--shadow-md);
  color: var(--on-inv);
  isolation: isolate;
}
.heromosaic__tile img {
  width: 100%;
  height: auto;
  display: block;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform .5s var(--ease);
}
.heromosaic__tile:hover img,
.heromosaic__tile:focus-visible img { transform: scale(1.04); }

/* A scrim, not a flat overlay: the name has to clear AA against whatever the
   photograph happens to be doing at the bottom edge. */
.heromosaic__cap {
  position: absolute;
  inset: auto 0 0 0;
  padding: 26px 12px 10px;
  display: flex;
  align-items: center;
  gap: 8px;
  /* Held near-solid for the band the text sits in, then faded. A plain
     gradient measured 3.30:1 on the เครือสหพัฒน์ tile, whose shopfront sign
     is bright teal exactly where the name lands. */
  background: linear-gradient(
    to top,
    rgba(4, 18, 17, .95) 0,
    rgba(4, 18, 17, .93) 34px,
    rgba(4, 18, 17, 0) 100%
  );
}
.heromosaic__name {
  font-weight: 600;
  font-size: 14px;
  color: #fff;
  min-width: 0;
  overflow-wrap: anywhere;
}
.status--tile { font-size: 11px; padding: 2px 7px; flex: none; }

@media (max-width: 1002px) {
  .heromosaic { max-width: none; }
}
@media (max-width: 420px) {
  .heromosaic { gap: 10px; }
  .heromosaic__tile:nth-child(even) { transform: translateY(18px); }
}
@media (prefers-reduced-motion: reduce) {
  .heromosaic__tile img { transition: none; }
}

/* ── Home booking bar ────────────────────────────────────── */

.bookbar {
  max-width: var(--maxw);
  margin: -36px auto 0;
  padding: 0 var(--gutter);
  position: relative;
  z-index: 3;
}
.bookbar__form {
  background: var(--surface-inv);
  border-radius: var(--radius);
  padding: 24px 28px;
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr auto;
  gap: 16px;
  align-items: end;
  box-shadow: var(--shadow-lg);
}
.bookbar__form .btn { height: 46px; }

/* ── Form fields ─────────────────────────────────────────── */

.field { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.field--wide { grid-column: span 2; }
.field > label { font-size: 14px; color: var(--label); }
.field input,
.field select,
.field textarea {
  height: 46px;
  border-radius: 10px;
  background: var(--tint);
  border: 1px solid var(--line);
  padding: 0 14px;
  font-family: inherit;
  font-size: 15px;
  color: var(--ink);
  width: 100%;
}
.field textarea { height: auto; min-height: 96px; padding: 12px 14px; line-height: 1.6; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--teal); }

.field--dark > label { color: var(--on-dark-label); font-size: 13px; }
.field--dark input,
.field--dark select {
  background: var(--ink-raised);
  border-color: transparent;
  color: #fff;
}
.field--dark input::-webkit-calendar-picker-indicator { filter: invert(1); opacity: .7; }

.formcard {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 28px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  align-content: start;
}
.formcard .btn { grid-column: span 2; height: 52px; border-radius: 10px; font-size: 17px; }
.formnote {
  grid-column: span 2;
  margin: 0;
  padding: 12px 14px;
  border-radius: 10px;
  background: var(--tint-mint);
  color: var(--ink);
  font-size: 15px;
  line-height: 1.6;
}

/* ── Section scaffolding ─────────────────────────────────── */

.section {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 76px var(--gutter);
}

/* A ground for the shop window. The hero fades to --surface, the cards are
   --surface, and the next band is 1,500px further down: the top third of the
   page was white on white, which is why eight cards read as a list rather than
   as objects.

   .section is max-width constrained, so a plain background would be a tinted
   box floating in white. The spread shadow paints to both edges; the clip-path
   stops it creating horizontal overflow, which 100vw would by the width of the
   scrollbar. */
.section--tint {
  background: var(--tint);
  box-shadow: 0 0 0 100vmax var(--tint);
  clip-path: inset(0 -100vmax);
}
.section--tight { padding-top: 24px; }
.section--flush { padding-top: 0; padding-bottom: 64px; }
.section__head { display: flex; flex-direction: column; gap: 10px; margin-bottom: 32px; }
.section__head--row {
  flex-direction: row;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
}
.section__titles { display: flex; flex-direction: column; gap: 10px; }

/* Thai runs have no spaces, so a long address can set a min-content width the
   grid refuses to shrink below. Let items shrink and let long runs break. */
.grid { display: grid; gap: 20px; }
.grid > * { min-width: 0; }
.card__note, .contactcard__address, .branchrow__address, .minibranch__name {
  overflow-wrap: anywhere;
}
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
.grid--tight { gap: 14px; }

.band { padding: 72px var(--gutter); }
.band > * { max-width: var(--maxw); margin-inline: auto; }
.band--dark { background: var(--surface-inv); color: var(--on-inv); }
.band--tint { background: var(--tint); }
.band--split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: center;
  max-width: var(--maxw);
  margin-inline: auto;
}
.band--split > * { max-width: none; }
.band--split-even { align-items: start; }
.band--hero { grid-template-columns: 1.1fr .9fr; }
.band__copy { display: flex; flex-direction: column; gap: 20px; }
.band__actions { display: flex; gap: 12px; padding-top: 8px; flex-wrap: wrap; }

/* ── Cards ───────────────────────────────────────────────── */

.card {
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  color: inherit;
  background: var(--surface-2);
  box-shadow: var(--shadow-sm);
}
/* Icon-led service cards: the glyph is the headline, the words are the caption. */
.card--service {
  min-height: 158px;
  align-items: center;
  text-align: center;
  gap: 14px;
  padding: 28px 20px;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), transform .2s var(--ease);
}
.card--service:hover {
  border-color: var(--teal);
  box-shadow: var(--shadow-accent);
  transform: translateY(-3px);
  color: inherit;
}
.card--branch, .contactcard, .licencecard, .branchrow {
  border-radius: 18px;
  box-shadow: var(--shadow-sm);
  transition: box-shadow .2s var(--ease), transform .2s var(--ease);
}
.card--branch:hover, .branchrow:hover { box-shadow: var(--shadow-md); }
.minibranch__photo, .card__photo, .branchrow__photo { border-radius: 14px; overflow: hidden; }
.card--branch .card__photo { border-radius: 0; }
.minibranch img, .card--branch img, .branchrow__photo img {
  transition: transform .35s var(--ease);
}
.minibranch:hover img, .card--branch:hover img { transform: scale(1.03); }
.card__icon {
  width: 76px;
  height: 76px;
  border-radius: 22px;
  background: var(--tint-mint);
  color: var(--teal-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  transition: background-color .15s ease, color .15s ease;
}
.card__icon svg { width: 40px; height: 40px; display: block; }
.card--service:hover .card__icon { background: var(--teal-ink); color: var(--on-accent); }

/* ── Home shop window: one card carries weight ───────────────────
   Eight tiles of identical size, colour and weight gave the eye nowhere to
   land; the only thing distinguishing them was the price. The annual check is
   the highest-value service and the way in to the corporate offer, so it gets
   the room to say what it actually includes -- and the price caveat moves out
   of 15px fineprint into the grid, where the numbers it qualifies are. */
.grid--window { grid-auto-flow: row dense; }

.card--feature {
  /* Pinned to the top-left rather than left to auto-placement, which dropped
     it into the middle column and split the grid in two. */
  grid-column: 1 / span 2;
  grid-row: 1 / span 2;
  text-align: left;
  align-items: flex-start;
  /* Title block top, price bottom: the gap between them is the point, not an
     accident. Centring the group left a hole that read as a mistake. */
  justify-content: space-between;
  gap: 18px;
  padding: 32px;
  /* White like its neighbours. On a tinted section a mint card would read as
     recessed, which is backwards for the one card meant to lead. Its weight
     comes from size and from the 38px price. */
  background: var(--surface-2);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md);
}
.card--feature .card__icon { width: 72px; height: 72px; border-radius: 20px; }
.card--feature .card__icon svg { width: 44px; height: 44px; }
.card--feature .card__body { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.card--feature .card__title { font-size: 22px; }
.card--feature .card__note {
  font-size: 15px;
  color: var(--body);
  line-height: 1.6;
  overflow-wrap: anywhere;
}
.card--feature .card__prep {
  align-self: flex-start;
  padding: 7px 10px;
  border-radius: 9px;
  background: var(--warn-bg);
  color: var(--warn-fg);
  font-size: 13px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}
.card__price--lg { font-size: 38px; line-height: 1; }

/* Fills the one cell the feature card leaves, and gives the caveat the
   standing it deserves beside eight confident numbers. */
.card--note {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--body);
  background: transparent;
  border-style: dashed;
  box-shadow: none;
}

@media (max-width: 1002px) {
  /* Two columns: the feature spans the row but lies down, so it costs one row
     rather than two. The phone page is already long enough. */
  .card--feature {
    grid-column: 1 / span 2;
    grid-row: auto;
    flex-direction: row;
    align-items: center;
    gap: 16px;
    padding: 20px;
  }
  .card--feature .card__icon { width: 56px; height: 56px; flex: none; }
  .card--feature .card__icon svg { width: 34px; height: 34px; }
  .card--feature .card__title { font-size: 18px; }
  .card--feature .card__note { display: none; }
  .card__price--lg { font-size: 26px; flex: none; }
  .card--note { grid-column: span 2; min-height: 0; padding: 16px; }
}
@media (max-width: 560px) {
  .card--feature { flex-wrap: wrap; }
  .card--feature .card__prep { font-size: 12px; }
}
.card--service .card__title { font-size: 17px; }
.card--service .card__mono { font-size: 12px; letter-spacing: .01em; }
.card__title { font-size: 18px; font-weight: 600; color: var(--ink); line-height: 1.45; }
.card__title--lg { font-size: 19px; line-height: 1.4; }
.card__mono { font-size: 13px; color: var(--muted); line-height: 1.5; font-family: var(--mono); }
.card__note { font-size: 15px; color: var(--body-mute); line-height: 1.6; }

.card--onDark { background: var(--ink-raised); border: 0; border-radius: 14px; padding: 22px; gap: 8px; }
.card--onDark .card__title { color: #fff; font-size: 17px; }
.card--onDark .card__note { color: var(--on-dark-mute); font-size: 14px; line-height: 1.55; }

.card--branch { padding: 0; border-radius: var(--radius); overflow: hidden; gap: 0; }
.card__photo { height: 176px; background: var(--tint-sage); overflow: hidden; }
.card__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card__body { padding: 22px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.card__phone { font-size: 17px; font-weight: 600; color: var(--teal-ink); margin-top: auto; }
.card__actions { display: flex; gap: 8px; padding-top: 4px; }

/* ── Trust band + facts + steps ──────────────────────────── */

.band--tint .grid--3 { gap: 24px; }
/* The trust claims link to the evidence — licence numbers, prices — rather
   than asserting and dead-ending. */
.trust {
  display: flex;
  flex-direction: column;
  gap: 8px;
  color: inherit;
  padding: 20px;
  margin: -20px;
  border-radius: var(--radius);
  transition: background-color .15s ease;
}
.trust:hover { background: var(--surface-2); color: inherit; }
.trust__title { font-size: 20px; font-weight: 600; color: var(--ink); }
.trust__note { font-size: 16px; color: var(--body-mute); line-height: 1.65; }
.trust__more { font-size: 15px; font-weight: 600; color: var(--teal-ink); margin-top: 4px; }

/* ── Nearest-branch control ──────────────────────────────────── */

.nearest { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 6px; }
.nearest__btn { height: 46px; font-size: 15px; }
.nearest__msg { margin: 0; font-size: 15px; color: var(--body-mute); }
.distance {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--surface-inv);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
}
.branchrow.is-nearest { border-color: var(--teal-ink); box-shadow: 0 0 0 1px var(--teal-ink); }

.fact {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.fact__k { font-family: var(--display); font-size: 32px; font-weight: 600; color: var(--teal-ink); }
.fact__v { font-size: 16px; color: var(--body-mute); }

.step {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 20px;
  border-top: 2px solid var(--teal);
}
.step__no {
  font-family: var(--display);
  font-size: 15px;
  font-weight: 600;
  /* Was --teal-dim (#7ab8b3), 2.25:1 on white. A tinted counter chip keeps the
     number quiet without dropping it below AA. */
  color: var(--teal-ink);
  background: var(--tint-mint);
  width: 30px;
  height: 30px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-variant-numeric: tabular-nums;
}
.step__title { font-size: 19px; font-weight: 600; color: var(--ink); line-height: 1.45; }
.step__note { font-size: 15px; color: var(--body-mute); line-height: 1.65; }

/* ── Home CTA strip ──────────────────────────────────────── */

.cta {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 72px var(--gutter);
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 40px;
  align-items: center;
  border-bottom: 1px solid var(--line-soft);
}
.cta__copy { display: flex; flex-direction: column; gap: 12px; }
.cta__note { margin: 0; font-size: 18px; color: var(--body-mute); }
.cta__actions { display: flex; gap: 12px; flex-wrap: wrap; }
.band--cta {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 40px;
  align-items: center;
}

/* ── Page heroes (sub-pages) ─────────────────────────────── */

.pagehero {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 64px var(--gutter) 36px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: linear-gradient(180deg, var(--tint), var(--surface));
}
.pagehero--split {
  display: grid;
  grid-template-columns: 1.1fr .9fr;
  gap: 56px;
  align-items: center;
  padding: 72px var(--gutter) 56px;
}
.pagehero__copy { display: flex; flex-direction: column; gap: 22px; }
.pagehero__figure { height: 420px; background: var(--tint-sage); overflow: hidden; border-radius: var(--radius); }
.pagehero__figure img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── About: values + mini branches ───────────────────────── */

.valuelist { display: flex; flex-direction: column; }
.valuelist__row {
  padding: 18px 0;
  border-top: 1px solid var(--ink-line);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.valuelist__title { font-size: 19px; font-weight: 600; color: #fff; }
.valuelist__note { font-size: 15px; color: var(--on-dark-mute); }

.minibranch { display: flex; flex-direction: column; gap: 10px; color: inherit; }
.minibranch__photo { height: 150px; background: var(--tint-sage); border-radius: 12px; overflow: hidden; }
.minibranch__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.minibranch__name { font-size: 17px; font-weight: 600; color: var(--ink); line-height: 1.4; }
.minibranch__hours { font-size: 15px; color: var(--body-mute); }
.minibranch:hover .minibranch__name { color: var(--teal-ink); }

/* ── Services page ───────────────────────────────────────── */

.servicegroups { display: flex; flex-direction: column; gap: 40px; }
.servicegroup { display: grid; grid-template-columns: 300px 1fr; gap: 40px; align-items: start; }
.servicegroup__label { display: flex; flex-direction: column; gap: 6px; position: sticky; top: 24px; }
.servicegroup__title { font-family: var(--display); font-size: 26px; font-weight: 600; color: var(--ink); line-height: 1.35; }
.servicegroup__en { font-size: 14px; color: var(--muted); font-family: var(--mono); }
.servicegroup__items { display: flex; flex-direction: column; }

.servicerow {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 24px;
  align-items: center;
  padding: 22px 4px;
  border-top: 1px solid var(--line);
}
.servicerow:hover { background: var(--tint-pale); }
.servicerow__copy { display: flex; flex-direction: column; gap: 6px; }
.servicerow__title { font-size: 21px; font-weight: 600; color: var(--ink); }
.servicerow__note { font-size: 16px; color: var(--body-mute); line-height: 1.6; }
.servicerow .btn { height: 44px; font-size: 15px; }

/* ── Branches page ───────────────────────────────────────── */

.branchlist { display: flex; flex-direction: column; gap: 28px; }
.branchrow {
  display: grid;
  grid-template-columns: 340px 1fr 320px;
  gap: 32px;
  border: 1px solid var(--line);
  border-radius: 18px;
  overflow: hidden;
  align-items: stretch;
}
/* The photo must fill its column without its intrinsic height driving the row —
   the portrait branch shots would otherwise stretch the row and strand the
   phone number at the bottom. Absolute positioning takes the image out of the
   height calculation, matching the design's background-image behaviour. */
.branchrow__photo { background: var(--tint-sage); min-height: 230px; position: relative; }
.branchrow__photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.branchrow__body { padding: 28px 0; display: flex; flex-direction: column; gap: 12px; }
.branchrow__name { font-family: var(--display); font-size: 26px; font-weight: 600; color: var(--ink); line-height: 1.35; }
.branchrow__address { font-size: 17px; color: var(--body-mute); line-height: 1.7; max-width: 420px; }
.branchrow__phone { font-size: 22px; font-weight: 600; color: var(--teal-ink); margin-top: auto; }
.branchrow__actions { display: flex; gap: 10px; flex-wrap: wrap; }
.branchrow__actions .btn { height: 46px; padding: 0 24px; font-size: 15px; }
/* Live Google map with a pin on the branch. The iframe fills the panel and the
   "open in Maps" button floats over its bottom edge. */
.branchrow__map { position: relative; background: var(--tint-sage); min-height: 230px; }
.branchrow__maptoggle { display: none; }
.branchrow__mapwrap { position: absolute; inset: 0; }
.branchrow__mapframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
.branchrow__mapbtn {
  position: absolute;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  height: 42px;
  padding: 0 20px;
  font-size: 14px;
  background: var(--surface-2);
  box-shadow: var(--shadow-md);
  white-space: nowrap;
}
.branchrow__mapbtn:hover { background: var(--surface-2); }

/* ── Contact page ────────────────────────────────────────── */

.contactcard {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.contactcard__name { font-size: 18px; font-weight: 600; color: var(--ink); line-height: 1.4; }
.contactcard__address { font-size: 15px; color: var(--body-mute); line-height: 1.6; }
.contactcard__hours { font-size: 15px; color: var(--teal-deep); font-weight: 600; }
.contactcard__phone { font-size: 20px; font-weight: 600; color: var(--teal-ink); margin-top: auto; }
.contactcard .btn { height: 44px; border-radius: 10px; font-size: 15px; }

/* Overview map — every branch pinned on one large Leaflet map. */
.branchmap {
  height: 520px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  overflow: hidden;
  background: var(--tint-sage);
  z-index: 0; /* keep Leaflet's panes under the sticky header */
}
.branchmap .leaflet-container { font-family: var(--sans); }

.branchpin svg { display: block; filter: drop-shadow(0 2px 3px rgba(11, 43, 41, .3)); }

.leaflet-popup-content { margin: 14px 16px; display: flex; flex-direction: column; gap: 6px; }
.branchpin__name { font-size: 17px; font-weight: 600; color: var(--ink); }
.branchpin__hours { font-size: 14px; color: var(--teal-deep); font-weight: 600; }
.branchpin__addr { font-size: 14px; color: var(--body-mute); line-height: 1.6; }
.branchpin__tel { font-size: 17px; font-weight: 600; color: var(--teal-ink); }
.branchpin__map { font-size: 14px; font-weight: 600; }

/* ── Footer ──────────────────────────────────────────────── */

.footer { background: var(--surface-inv); color: var(--on-dark-mute); }
.footer__cols {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 56px var(--gutter) 36px;
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr 1.1fr;
  gap: 40px;
}
.footer__brand { display: flex; flex-direction: column; gap: 14px; }
/* The white logo is supplied as a square with wide transparent margins, so it
   is sized larger than the header mark and the slack is pulled back with
   negative margins — the visible wordmark then matches the header's 44px.
   No white plate behind it any more; it sits straight on the dark footer. */
.footer__brand img {
  /* 48px here matches the visible mark height the old 86px square produced
     once its transparent padding is gone -- same optical size, 44 KB less. */
  height: 48px;
  width: auto;
  align-self: flex-start;
}
.footer__name { font-size: 15px; line-height: 1.7; }
.footer__operator { font-size: 14px; line-height: 1.7; color: var(--on-dark-faint); }
.footer__col { display: flex; flex-direction: column; font-size: 15px; }
.footer__head {
  color: #fff;
  font-weight: 600;
  margin: 0 0 14px;
  padding: 0;
  font-family: inherit;
  font-size: 15px;
  text-align: left;
  background: none;
  border: 0;
  cursor: default;
}
.footer__links { display: flex; flex-direction: column; gap: 10px; }
.footer__col a { color: inherit; }
.footer__col a:hover { color: #fff; }

/* Sticky call/LINE bar — mobile only, shown via the media query below. */
.actionbar { display: none; }
.footer__bar {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gutter) 28px;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  color: var(--on-dark-legal);
  font-size: 13px;
}

/* ── Responsive (additions; the design specifies 1440 only) ─ */

@media (max-width: 1200px) {
  :root { --gutter: 40px; }
  .nav { gap: 22px; font-size: 15px; }
  .branchrow { grid-template-columns: 280px 1fr 260px; }
  .servicegroup { grid-template-columns: 240px 1fr; gap: 28px; }
}

@media (max-width: 1024px) {
  .masthead__cta { display: none; }
  .hero, .band--split, .band--hero, .pagehero--split { grid-template-columns: 1fr; }
  .hero__copy { max-width: none; padding-bottom: 40px; }
  .hero__figure { min-height: 0; }
  .band--split { gap: 36px; }
  .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .bookbar__form { grid-template-columns: 1fr 1fr; }
  .bookbar__form .btn { grid-column: span 2; }
  .branchrow { grid-template-columns: 260px 1fr; }
  .branchrow__map { grid-column: span 2; }
  .display--xl { font-size: 42px; }
  .display--lg { font-size: 38px; }
}

@media (max-width: 860px) {
  :root { --gutter: 24px; }
  .utility__facts span + span { display: none; }
  .masthead__toggle { display: flex; }
  .masthead__inner { flex-wrap: wrap; }
  .nav {
    display: none;
    width: 100%;
    flex-direction: column;
    gap: 0;
    padding-top: 8px;
  }
  .nav.is-open { display: flex; }
  .nav__link {
    align-items: flex-start;
    padding: 14px 2px;
    border-top: 1px solid var(--line-soft);
  }
  .nav__link.is-active::after { display: none; }
  .section, .cta, .band { padding-top: 48px; padding-bottom: 48px; }
  .section__head--row, .cta, .band--cta { grid-template-columns: 1fr; flex-direction: column; align-items: flex-start; }
  .grid--3, .servicegroup { grid-template-columns: 1fr; }
  .servicegroup__label { position: static; }
  /* One column from here down: the collapsible headings are full-width rows
     with a chevron pinned right, so a second column would put that chevron
     hard against the neighbouring heading's text. */
  .footer__cols { grid-template-columns: 1fr; gap: 28px; }
  .display--xl { font-size: 34px; }
  .display--lg { font-size: 32px; }
  .display, .display--sm { font-size: 28px; }
  .lead { font-size: 17px; }
}

/* ── Mobile compaction ───────────────────────────────────────────
   The design is desktop-only, and a naive stack ran the home page to nearly
   ten screens. These rules chunk long lists into scannable pairs (Miller),
   put the recurring actions in the thumb zone instead of at the end of a long
   scroll (Fitts), and hide secondary detail behind a tap (progressive
   disclosure) rather than making people scroll past it. */
@media (max-width: 860px) {
  /* Persistent call/LINE bar — the two things people come here to do. */
  .actionbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 50;
    display: flex;
    gap: 10px;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
    /* NOT a literal: this bar is the primary call-to-action on a phone and
       the label inside inherits --ink, which is near-white in dark mode.
       Hardcoded white gave 1.04:1 there. --surface-glass inverts. */
    background: var(--surface-glass);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    border-top: 1px solid var(--line);
  }
  .actionbar .btn { flex: 1; height: 48px; font-size: 15px; }
  body { padding-bottom: 74px; }

  /* Two-up beats a single column of identical cards: half the height, and the
     eye compares neighbours instead of scrolling through a queue. */
  .grid--4 { grid-template-columns: repeat(2, 1fr); gap: 14px; }
  /* The icon stays large on a phone and the English gloss goes — at this size
     the glyph plus the Thai label already says it, and dropping the third line
     is height the page does not have to spend. */
  .card--service { min-height: 0; padding: 20px 12px; gap: 12px; }
  .card--service .card__title { font-size: 15px; }
  /* Stack the qualifier above the number rather than wrapping mid-phrase. */
  .card__price { font-size: 20px; line-height: 1.25; }
  .card__price .price__from { display: block; margin: 0 0 2px; font-size: 12px; }
  .servicerow__price .price__from { display: block; margin: 0 0 2px; font-size: 12px; }
  .card--service .card__mono { display: none; }
  .card__icon { width: 64px; height: 64px; border-radius: 18px; }
  .card__icon svg { width: 34px; height: 34px; }

  /* Branch cards scroll sideways; the peeking next card says "there's more"
     without spending vertical space on it. */
  .grid--carousel {
    display: flex;
    gap: 14px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    padding-bottom: 8px;
    -webkit-overflow-scrolling: touch;
  }
  .grid--carousel > * { flex: 0 0 78%; scroll-snap-align: start; }

  /* Footer columns collapse; nav.js closes them and marks the buttons. */
  .footer__head {
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    margin: 0;
    padding: 14px 0;
    border-top: 1px solid var(--ink-line);
  }
  .footer__head::after {
    content: '';
    width: 8px;
    height: 8px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform .15s ease;
  }
  .footer__head[aria-expanded='true']::after { transform: rotate(-135deg); }
  .footer__links { padding-bottom: 14px; }
  .footer__cols { grid-template-columns: 1fr; gap: 0; padding-bottom: 20px; }
  .footer__brand { margin-bottom: 12px; }

  /* Same disclosure pattern for the branch maps — and it stops the embedded
     map from swallowing swipes meant for the page. */
  /* "ดูแผนที่" and "เปิดใน Google Maps" share one row; the map opens beneath. */
  .branchrow__map {
    min-height: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 0 0 14px;
    background: none;
  }
  .branchrow__maptoggle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    padding: 0 20px;
    height: 46px;
    border-radius: 999px;
    background: var(--tint-mint);
    color: var(--teal-deep);
    border: 0;
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
  }
  .branchrow__mapwrap {
    position: relative;
    flex: 1 1 100%;
    order: 3;
    height: 220px;
    border-radius: 12px;
    overflow: hidden;
  }
  .branchrow__mapbtn {
    position: static;
    transform: none;
    margin: 0;
    flex: 1 1 auto;
    min-width: 0;
    height: 46px;
    padding: 0 12px;
    box-shadow: none;
  }

  /* One "สอบถาม / นัดหมาย" per row is redundant when the bar is always there,
     but the price must stay — it is the reason people opened this page. */
  .servicerow .btn { display: none; }
  .servicerow { grid-template-columns: 1fr auto; padding: 16px 4px; gap: 14px; }
  .servicerow__price { font-size: 20px; }
  .servicerow__price--ask { font-size: 13px; max-width: 110px; text-align: right; }
  .licencegrid { grid-template-columns: 1fr; }
  .servicerow__title { font-size: 18px; }
  .servicerow__note { font-size: 15px; }

  .section, .cta, .band, .pagehero { padding-top: 36px; padding-bottom: 36px; }
  .section__head { margin-bottom: 20px; }
  .hero__copy { padding-top: 36px; padding-bottom: 28px; }
}

@media (max-width: 620px) {
  /* Stacked CTAs become full-width so each is an easy thumb target. */
  .hero__actions .btn,
  .cta__actions .btn,
  .band__actions .btn { flex: 1 1 100%; }
  /* Only two of these, and both are short — they share a row rather than
     costing a second one. */
  .branchrow__actions .btn { flex: 1 1 0; padding: 0 12px; font-size: 14px; }
  .branchmap { height: 340px; }

  /* A full address at half-width is too cramped to scan on a phone —
     these go back to full width while the icon cards stay two-up. */
  .contactcard { grid-column: 1 / -1; }

  .grid--2, .formcard, .bookbar__form { grid-template-columns: 1fr; }
  .field--wide, .formcard .btn, .formnote { grid-column: span 1; }
  .bookbar__form .btn { grid-column: span 1; }
  .branchrow, .servicerow { grid-template-columns: 1fr; }
  .branchrow__map { grid-column: span 1; }
  .branchrow__photo, .branchrow__photo img { min-height: 200px; }
  .branchrow__body { padding: 22px 0; }
  .hero__stats { gap: 20px; }
  .card__actions { flex-wrap: wrap; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* ── Print ───────────────────────────────────────────────────────
   People print price lists and directions at the counter. Drop the
   furniture, keep the facts, and spell out link targets. */
@media print {
  .utility, .masthead, .actionbar, .footer, .bookbar,
  .branchrow__map, .branchmap, .hero__figure, .nearest,
  .card__actions, .branchrow__actions, .skip-link { display: none !important; }

  :root { --gutter: 0; }

  body { background: #fff; color: #000; font-size: 11pt; padding: 0; }
  .hero { grid-template-columns: 1fr; }
  .section, .band, .cta, .pagehero { padding: 12pt 0; break-inside: avoid; }
  .band--dark { background: #fff !important; color: #000 !important; }
  .band--dark .display, .band--dark .card__title, .valuelist__title { color: #000 !important; }
  .card, .branchrow, .licencecard, .contactcard { border-color: #999; break-inside: avoid; }
  .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .grid--carousel { display: grid; overflow: visible; margin: 0; padding: 0; }

  /* A printed page cannot be clicked — say where the links went. */
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; word-break: break-all; }
  a[href^="tel:"]::after { content: ""; }

  /* Collapsed panels must print open. */
  .footer__links[hidden], .branchrow__mapwrap[hidden] { display: block !important; }
}

/* Confirmation shown after the verify button copies a licence number. */
.licence__copied {
  grid-column: 1 / -1;
  margin: 10px 0 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--tint-mint);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.6;
}
.licencecard .licence__copied { margin-top: 8px; }

/* ── Scroll reveal ───────────────────────────────────────────────
   Sections settle in as they enter the viewport. Done with CSS scroll-driven
   animations, so there is no JavaScript and no observer: browsers without
   `animation-timeline` simply show the content, which is the correct fallback.
   `@supports` keeps the starting opacity from ever applying where the
   animation cannot run — otherwise the page would stay blank. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes reveal {
      from { opacity: 0; transform: translateY(14px); }
      to   { opacity: 1; transform: none; }
    }
    main > section > .section__head,
    main > section > .grid > *,
    main > section > .branchlist > *,
    main > section > .servicegroups > *,
    main > section > .licencegrid > * {
      animation: reveal linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 22%;
    }
  }
}

/* Motion is opt-out everywhere, not just here. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
