/* =============================================================================
   Saksit 789 — ศักดิ์สิทธิ์ เบอร์มงคล  ·  styles.css
   Design foundation extracted from .claude/DESIGN.md (single source of truth).

   This file is the CSS half of the token system; the inline `tailwind.config`
   in index.html mirrors the same values so utilities and custom CSS agree.

   TABLE OF CONTENTS
     0. Fonts
     1. Design tokens (:root)              — DESIGN.md §12
     2. Base / reset                       — body, typography defaults
     3. Utilities & helpers                — gold-text, tnum, focus ring
     4. Gradients & gold effects           — DESIGN.md §4
     5. Buttons                            — DESIGN.md §9.1
     6. Product card                       — DESIGN.md §9.2
     7. Badges & tags                      — DESIGN.md §9.3
     8. Inputs & forms                     — DESIGN.md §9.4
     9. Number chips (0–9)                 — DESIGN.md §9.5
    10. Category selector tiles            — DESIGN.md §9.6
    11. Navigation bar                     — DESIGN.md §9.7
   11a. Category bottom sheet              — mobile-only quick-nav from bottomnav
    12. Trust badge strip                  — DESIGN.md §9.8
    13. Section header                     — DESIGN.md §9.9
    14. Hero                               — DESIGN.md §9.10
    15. Banner slider                      — full-width + multi-item ad carousel
    16. Footer                             — dark authority surface
    17. Article card                       — บทความ / blog teaser
    18. Review card                        — customer testimonial
    19. Video card                         — portrait video teaser (extends .article-card)
    20. CTA banner                         — closing call-to-action
    21. Service card                       — บริการจากเรา feature grid
    22. Motion & reduced-motion            — DESIGN.md §10
    23. CMS content                        — bare rich-text HTML from the CMS
    29. Videos page                        — filter pills, video-grid card, social
                                              stats, news list, dark CTA banner
    30. Blog page                          — featured article, teaser grid with
                                              tag + meta row, pagination
    31. Blog detail page                   — breadcrumb, article header, share
                                              buttons, related grid
    32. Reviews page                       — dark testimonial carousel, chat
                                              review card, in-page jump nav
    33. Search / listing page              — sidebar filter box, listing
                                              toolbar (count + sort); grid
                                              reuses .card (§6), pagination
                                              reuses .pagination (§30)
   ========================================================================== */

/* ------------------------------------------------------------------ *
 * 0. FONTS  — Noto Sans Thai (display + body). Load first.
 * ------------------------------------------------------------------ */
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Thai:wght@300;400;500;600;700;800&display=swap');

/* ------------------------------------------------------------------ *
 * 1. DESIGN TOKENS  (DESIGN.md §12) — the single source of truth.
 * ------------------------------------------------------------------ */
:root {
  /* Gold scale --------------------------------------------------- */
  --gold-50:  #FBF3D9;
  --gold-100: #F9EEC1;
  --gold-200: #F5D98B;
  --gold-300: #EFD07F;
  --gold-400: #E4BD5F;   /* mid gold — core brand value */
  --gold-500: #D2A247;
  --gold-600: #C49332;
  --gold-700: #B68438;   /* bronze — price text on light bg */
  --gold-800: #8A6520;

  /* Neutrals (canvas & ink) ------------------------------------- */
  --ink-900: #0A0A0A;
  --ink-800: #141414;
  --ink-700: #2A2724;
  --ink-500: #53504B;
  --ink-400: #7A756D;
  --ink-300: #999690;
  --line-200: #EAE0CE;
  --line-100: #EFEAE1;
  --surface-card:  #FFFFFF;
  --surface-panel: #F9F8F7;
  --surface-tile:  #FDFAF5;   /* category selector tile fill (DESIGN.md §9.6) */
  --bg-base: #FAF8F3;    /* warm cream — page background */
  --bg-alt:  #F1EDE6;

  /* Semantic / state -------------------------------------------- */
  --success:    #E4BD5F;
  --success-bg: #EAF9F0;
  --danger:     #E23B3B;
  --danger-bg:  #FBEAEA;
  --favorite:   #B68438;
  --focus-ring: #E4BD5F;
  --nav-link:   #CCA16E;   /* desktop nav menu link text (on --ink-900 bar) */

  /* "โทรสอบถาม" CTA — the deep cut of the one allowed green (DESIGN.md §3.3).
     Kept apart from LINE's brand green, which is too loud beside gold. */
  --call:       #1E6B34;
  --call-hover: #175428;
  --call-bg:       #EAF9F0;   /* light-green fill, same tint as --success-bg */
  --call-bg-hover: #D9F2E3;   /* one step deeper on hover/active */

  /* Ink for text sitting on gold (AA-safe, DESIGN.md §11) -------- */
  --on-gold: #3A2A08;

  /* Cream text for surfaces sitting on ink (predict field, footer) */
  --on-ink: #F3EAD0;
  --on-ink-muted: #B9AE8C;

  /* Neutral light-grey text — footer body copy/links (cooler than --on-ink) */
  --footer-text: #ECECEC;

  /* Gradients & gold effects (DESIGN.md §4) --------------------- */
  --grad-gold:       linear-gradient(135deg, #F5D98B 0%, #E4BD5F 45%, #C49332 78%, #B68438 100%);
  --grad-gold-diagonal: linear-gradient(135deg, #F5D98B 0%, #E4BD5F 45%, #C49332 78%, #B68438 100%);
  --grad-gold-hero:  linear-gradient(180deg, #dfc888 0%, #BD8D22 100%);
  --grad-gold-text:  linear-gradient(180deg, #F3D98A 0%, #D2A247 55%, #A9782B 100%);
  --grad-gold-sheen: linear-gradient(105deg, rgba(255,255,255,0) 35%, rgba(243, 242, 234, 0.55) 50%, rgba(255,255,255,0) 65%);
  --grad-hero:       radial-gradient(120% 80% at 50% 0%, #FFFDF8 0%, #F7F1E6 55%, #F1E9D8 100%);
  --grad-ribbon:     linear-gradient(120deg, #F9E9BE 0%, #E4BD5F 40%, #B68438 100%);

  /* Radius ------------------------------------------------------ */
  --radius-sm:   8px;
  --radius-md:   12px;
  --radius-lg:   16px;
  --radius-xl:   24px;
  --radius-pill: 999px;

  /* Shadows (warm-tinted, DESIGN.md §7) ------------------------- */
  --shadow-xs:  0 1px 2px rgba(90,70,20,.06);
  --shadow-sm:  0 2px 6px rgba(90,70,20,.08);
  --shadow-card: 0 6px 18px rgba(120,90,30,.10);
  --shadow-lg:  0 12px 32px rgba(120,90,30,.14);
  --shadow-gold: 0 8px 20px rgba(198,150,50,.35);
  --shadow-inset-input: inset 0 1px 3px rgba(0,0,0,.35);

  /* Typography -------------------------------------------------- */
  --font-display: "Noto Sans Thai", system-ui, sans-serif;
  --font-body:    "Noto Sans Thai", "IBM Plex Sans Thai", "Sarabun", system-ui, sans-serif;
  --font-num:     "Noto Sans Thai", ui-sans-serif;

  /* Motion ------------------------------------------------------ */
  --ease-standard: cubic-bezier(.4, 0, .2, 1);
  --ease-out-soft: cubic-bezier(.22, 1, .36, 1);
  --dur-fast: 120ms;
  --dur-base: 200ms;
  --dur-slow: 320ms;

  /* Layout ------------------------------------------------------ */
  --container-max: 1280px;
}

/* ------------------------------------------------------------------ *
 * 2. BASE / RESET  — sits on top of Tailwind's preflight.
 * ------------------------------------------------------------------ */
body {
  background-color: var(--bg-base);
  color: var(--ink-700);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Thai needs a taller line-height; never below 1.5 on body text. */
h1, h2, h3, h4 { font-family: var(--font-display); line-height: 1.25; }
p, li { line-height: 1.6; }

/* Selection uses the brand gold wash. */
::selection { background: var(--gold-200); color: var(--on-gold); }

/* ------------------------------------------------------------------ *
 * 3. UTILITIES & HELPERS
 * ------------------------------------------------------------------ */

/* Page container width: use Tailwind's `max-w-container mx-auto` utility
   (registered in tailwind.config from --container-max) — not a CSS class,
   so there's one source of truth instead of two competing mechanisms. */

/* Tabular numerals — required on every price / phone / counter. */
.tnum {  font-feature-settings: "tnum" 1; font-variant-numeric: tabular-nums; }

/* Gold gradient text (hero title, large prices). DESIGN.md §4 recipe. */
.gold-text {
  background: var(--grad-gold-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 1px 0 rgba(0, 0, 0, .04);
}

/* Warm hairline divider (replaces hard black borders). */
.hairline { border-color: var(--line-200); }

/* Global focus ring — always visible, WCAG AA (DESIGN.md §11). */
:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Hide scrollbar on mobile sliders (carried over from wireframe). */
.hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
.hide-scrollbar::-webkit-scrollbar { display: none; }

/* ------------------------------------------------------------------ *
 * 4. GRADIENTS & GOLD EFFECTS  (DESIGN.md §4)
 * ------------------------------------------------------------------ */

/* Polished gold surface — apply to CTAs, prices, active fills. */
.bg-grad-gold  { background-image: var(--grad-gold); }
.bg-grad-hero  { background-image: var(--grad-hero); }
.bg-grad-ribbon { background-image: var(--grad-ribbon); }

/* Foil sheen overlay: an element that sweeps a highlight on hover.
   Add `.foil` to a positioned element; the ::after runs the sweep. */
.foil { position: relative; overflow: hidden; isolation: isolate; }
.foil::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--grad-gold-sheen);
  transform: translateX(-120%);
  pointer-events: none;
}
.foil:hover::after {
  animation: sheen-sweep var(--dur-slow) var(--ease-out-soft) 1;
}

@keyframes sheen-sweep {
  from { transform: translateX(-120%); }
  to   { transform: translateX(120%); }
}

/* ------------------------------------------------------------------ *
 * 5. BUTTONS  (DESIGN.md §9.1)
 * ------------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  font-family: var(--font-body);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  border-radius: var(--radius-md);
  padding: 0 1.5rem;
  min-height: 48px;
  cursor: pointer;
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              background-color var(--dur-base) var(--ease-standard);
}
.btn:disabled,
.btn[aria-disabled="true"] { cursor: not-allowed; }

/* Primary — polished gold bar with foil highlight + bronze keyline. */
.btn--gold {
  background-image: var(--grad-gold);
  color: var(--on-gold);
  box-shadow: var(--shadow-gold),
              inset 0 1px 0 rgba(255, 255, 255, .6),
              inset 0 -1px 0 var(--gold-800);
}
.btn--gold:hover  { transform: translateY(-1px); box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255,255,255,.6), inset 0 -1px 0 var(--gold-800); }
.btn--gold:active { transform: translateY(0);    box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255,255,255,.4), inset 0 -1px 0 var(--gold-800); }
.btn--gold:disabled,
.btn--gold[aria-disabled="true"] {
  background-image: none;
  background-color: #E7DFC9;
  color: #B7AE97;
  box-shadow: none;
  transform: none;
}

/* Diagonal modifier — same gold stops as --grad-gold, angled 135deg. */
.btn--gold.btn--diagonal { background-image: var(--grad-gold-diagonal); }

/* Buy CTA (สั่งซื้อ) — product-card gradient button. Oversized background
   so hover can slide the gold/champagne stops sideways (foil-catching-light
   feel) instead of just a flat color swap. */
.btn--buy {
  background-size: 200% 100%;
  background-position: 0% 0%;
  box-shadow: var(--shadow-gold), inset 0 1px 0 rgba(255,255,255,.6), inset 0 -1px 0 var(--gold-500);
  transition: background-position var(--dur-slow) var(--ease-standard),
              transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
  color: var(--on-gold);
}
.btn--buy:hover  { background-position: 100% 0%; transform: translateY(-1px); box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255,255,255,.6), inset 0 -1px 0 var(--gold-800); }
.btn--buy:active { transform: translateY(0); box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255,255,255,.4), inset 0 -1px 0 var(--gold-800); }

/* Buy CTA disabled (booked cards) — the buy button stays visible with its
   normal cart icon + label, just goes generic-disabled like any other
   primary CTA (DESIGN.md §9.1 "disabled"). The "จองแล้ว" status itself now
   lives on .card__price.is-booked instead of replacing this button. */
.btn--buy:disabled,
.btn--buy[aria-disabled="true"],
.btn--buy:disabled:hover,
.btn--buy[aria-disabled="true"]:hover {
  background-image: none;
  background-color: #E7DFC9;
  color: #B7AE97;
  box-shadow: none;
  transform: none;
  cursor: not-allowed;
}

/* Secondary — outline; gold border + gold-700 text, gold-50 hover fill. */
.btn--outline {
  background-color: var(--surface-card);
  color: var(--gold-700);
  border: 1.5px solid var(--gold-500);
}
.btn--outline:hover { background-color: var(--gold-50); }

/* Ink — near-black authority button (nav CTAs, some actions). */
.btn--ink {
  background-color: var(--ink-800);
  color: var(--on-ink);
}
.btn--ink:hover { background-color: var(--ink-900); }

/* LINE — one-off brand-color exception (official LINE green) for the
   LINE OA CTA only. Not part of the gold/neutral/success palette;
   do not reuse this color elsewhere. */
.btn--line {
  background-color: #42AB27;
  color: #FFFFFF;
}
.btn--line:hover { background-color: #398F21; }

/* Call — light-green `tel:` CTA that sits beside a gold "สั่งซื้อ" button
   (DESIGN.md §9.1). --call label/icon on --call-bg is ~9.8:1 → AA. */
.btn--call {
  background-color: var(--call-bg);
  color: var(--call);
  border: 1.5px solid var(--call);
  box-shadow: var(--shadow-sm);
}
.btn--call:hover  { background-color: var(--call-bg-hover); border-color: var(--call-hover); color: var(--call-hover); transform: translateY(-1px); box-shadow: var(--shadow-card); }
.btn--call:active { background-color: var(--call-bg-hover); border-color: var(--call-hover); color: var(--call-hover); transform: translateY(0);    box-shadow: var(--shadow-xs); }

/* Icon button — 44px circle, gold icon. */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-pill);
  color: var(--gold-700);
  background: transparent;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard),
              transform var(--dur-fast) var(--ease-standard);
}
/* .btn-icon:hover { background-color: var(--gold-50); } */
.btn-icon.is-active { transform: scale(1.1); color: var(--favorite); }
.btn-icon.is-active svg { fill: currentColor; }

/* Favorite heart (DESIGN.md §9.1) — a saved number has to be spottable in
   a grid of twenty, so the heart rests as a muted outline and only turns
   gold once it is saved. It used to rest on --gold-700, which is the same
   hex as --favorite, so saving changed nothing but the 1.1 pop. The state
   is never color alone: the heart also goes outline → filled, and
   aria-pressed flips for screen readers. */
[data-fav-toggle] { color: var(--ink-300); }
[data-fav-toggle]:hover { color: var(--gold-700); }

/* Desktop — favorite icon reads too small at the base 16px once there's
   room in the 44px button; mobile keeps the HTML width/height=16 as-is. */
@media (min-width: 1024px) {
  .btn-icon svg { width: 26px; height: 26px; }
}

/* Card fav-toggle — 26x26px button on tablet/desktop (paired with the
   36px mobile override below), vs. the 44px base .btn-icon elsewhere. */
@media (min-width: 640px) {
  .card .btn-icon { width: 26px; height: 26px; }
}

/* Size modifier — larger CTA for hero-level prominence.
   Combined selector (.btn.btn--lg) beats the base .btn rule on specificity
   alone, so it's safe regardless of Tailwind's CDN injection order. */
.btn.btn--lg { padding: 0 2rem; min-height: 56px; font-size: 1.0625rem; }
@media (max-width: 639px) { .btn.btn--lg { min-height: 44px; font-size: .9rem; } }

/* Size modifier — compact chrome: in-page back links, breadcrumb-replacement
   buttons, anywhere a full 48px CTA reads too heavy (DESIGN.md §9.1). */
.btn.btn--sm { padding: 0 14px; min-height: 36px; font-size: .8125rem; gap: 6px; }
.btn.btn--sm svg { width: 14px; height: 14px; }

/* ------------------------------------------------------------------ *
 * 6. PRODUCT CARD  (DESIGN.md §9.2) — core component.
 * ------------------------------------------------------------------ */
.card {
  position: relative;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 8px;
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard);
}
.card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
  border-color: var(--gold-200);
}

/* Selected / compare state — green means "chosen" (DESIGN.md §2). */
.card.is-selected {
  border: 2px solid var(--success);
  background-color: var(--success-bg);
}

/* Phone number — tabular, ink-700, centered. */
.card__number {
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 1.625rem;      /* 26px */
  line-height: 1.1;
  letter-spacing: .5px;     /* Latin digits only — safe, no Thai here */
  color: var(--ink-700);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* The number doubles as the link to /number/<msisdn> — a crawlable anchor
   whose text is the number itself. It opens the detail lightbox on click
   (assets/js/number-modal.js) but stays a real destination without JS. */
a.card__number {
  display: block;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-standard);
}
/* a.card__number:hover { color: var(--gold-700); text-decoration: none;} */
a.card__number:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-sm); }

/* Desktop — product number reads as the hero metric of the card, so it
   gets a bump beyond the base/mobile size once there's room for it. */
@media (min-width: 1024px) {
  .card__number { font-size: 1.875rem; }  /* 30px */
}

/* Price — gold-700, tabular, centered. */
.card__price {
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 1.375rem;      /* 22px */
  color: var(--gold-700);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Booked status — replaces the price on a reserved card. Keeps the
   danger token (red = "unavailable") that used to live on the buy CTA
   itself before that status moved here. */
.card__price.is-booked {
  color: var(--danger);
}

/* Price also opens the detail lightbox — same trigger as card__number and
   the buy button (assets/js/number-modal.js). */
a.card__price {
  display: block;
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: background-color var(--dur-fast) var(--ease-standard);
}
a.card__price:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }

/* Attribute row — 3 equal cells with warm hairline separators.
   min-width: 0 overrides the flex default of min-width: auto — without it,
   a wide operator wordmark (e.g. TrueMove H) refuses to shrink below its
   intrinsic width and blows out the row on narrow (2-up mobile) cards. */
.card__attrs { display: flex; }
.card__attrs > * { flex: 1; min-width: 0; text-align: center; }
.card__attrs > * + * { border-left: 1px solid var(--line-200); }
.card__attrs img { max-width: 100%; }
.card__attr-value { font-family: var(--font-num); font-weight: 700; color: var(--gold-700); line-height: 1; }
.card__attr-value.text-lg { font-size: 1.24rem; }
.card__attr-label { font-size: .75625rem; color: var(--ink-400); margin-top: 4px; }

/* Attribute row also opens the detail lightbox — same trigger as
   card__number and the buy button. */
a.card__attrs {
  color: inherit;
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: background-color var(--dur-fast) var(--ease-standard);
}
a.card__attrs:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }

/* ------------------------------------------------------------------ *
 * 7. BADGES & TAGS  (DESIGN.md §9.3)
 * ------------------------------------------------------------------ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: .8125rem;
  font-weight: 700;
  line-height: 1;
  padding: 5px 10px;
  border-radius: var(--radius-sm);
}
/* NEW / RECOMMENDED — near-black chip, gold text. */
.badge--emblem { background-color: var(--ink-900); color: var(--gold-300); text-transform: uppercase; }

/* Recommended (product card) — green outline pill + checkmark, matches
   wireframes/thumbnail-recommend.png. Reuses the success token, not a new
   accent hue: "recommended" reads as the same positive/chosen signal as
   .tile.is-selected and .chip.is-like elsewhere in the system. */
.badge.badge--recommend {
  padding: 3px 10px 3px 3px;
  border-radius: var(--radius-pill);
  background-color: var(--success-bg);
  border: 1px solid var(--success);
  color: var(--success);
  font-size: .75rem;
}
.badge--recommend__icon {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  flex: none;
  border-radius: var(--radius-pill);
  background-color: var(--success);
  color: #fff;
}

/* Grade badge — gold numeral in a line-framed cell. */
.grade {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  padding: 0 6px;
  border-radius: var(--radius-pill);
  font-family: var(--font-num);
  font-weight: 800;
  font-size: 1.1rem;
  color: var(--gold-700);
}

/* Network type pill — neutral text ("เติมเงิน" / "รายเดือน"). */
.pill-network {
  display: inline-flex;
  align-items: center;
  font-size: .8125rem;
  color: var(--ink-500);
}

/* Compact card — mobile shows 2 per row (below sm breakpoint), so every
   metric shrinks together to stay legible without the card feeling cramped.
   Combined selectors (e.g. .card__number.mb-4) beat Tailwind's mb-4 utility
   on specificity alone, same trick as .btn.btn--lg above. */
@media (max-width: 639px) {
  .card { padding: 4px; border-radius: var(--radius-md); }
  .card__number { font-size: 1.260rem; letter-spacing: .3px; }
  .card__number.mb-4 { margin-bottom: 10px; }
  .card__attrs.mb-4 { margin-bottom: 10px; }
  .card__attr-value { font-size: .9625rem; }
  .card__attr-value.text-lg { font-size: .9625rem; }
  .card__attr-label { font-size: .6875rem; margin-top: 2px; }
  .card__attrs img { height: 16px; }
  .card__price { font-size: 1rem; }
  .card__price.mb-4 { margin-bottom: 10px; }
  .card .btn { min-height: 40px; font-size: .8125rem; padding: 0 1rem; }
  .card .btn-icon { width: 36px; height: 36px; }
  .badge.badge--recommend { font-size: .6875rem; padding: 2px 8px 2px 2px; }
  .badge--recommend__icon { width: 13px; height: 13px; }
  .grade { min-width: 24px; height: 24px; font-size: .825rem; }
}

/* ------------------------------------------------------------------ *
 * 8. INPUTS & FORMS  (DESIGN.md §9.4)
 * ------------------------------------------------------------------ */

/* Dark predict field — ink well with gold frame, gold CTA fused right. */
.field-dark {
  background-color: var(--ink-800);
  color: var(--on-ink);
  border: 2px solid var(--gold-500);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-inset-input);
}
.field-dark input {
  background: #ffffff;
  border: 0;
  border-radius: 10px;
  color: var(--ink-900);
  width: 100%;
  padding: 14px 18px;
  font-family: var(--font-num);
  font-size: 1.0625rem;
  font-variant-numeric: tabular-nums;
}
.field-dark input::placeholder { color: var(--ink-400); font-family: var(--font-body); font-size: .9375rem; }
.field-dark input:focus { outline: none; }

/* Radius modifier for the hero predict shell — combined selector for
   specificity so it wins regardless of Tailwind's CDN injection order. */
.field-dark.field-dark--lg { border-radius: var(--radius-xl); }
@media (min-width: 640px) { .field-dark input { padding: 16px 22px; font-size: 1.1875rem; } }

/* Digit position boxes — 44×52 white cells, warm border, gold on focus. */
.digit {
  width: 44px;
  height: 52px;
  text-align: center;
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 1.25rem;
  color: var(--ink-700);
  background-color: var(--surface-card);
  border: 1.5px solid var(--line-200);
  border-radius: var(--radius-sm);
  font-variant-numeric: tabular-nums;
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.digit:focus { outline: none; border-color: var(--gold-400); box-shadow: 0 0 0 3px var(--focus-ring); }
.digit[readonly] { background-color: var(--bg-alt); color: var(--ink-500); }

/* Size modifier for the 10-cell "search by position" row — the base
   44×52 spec overflows small phones (10 cells + separators), so this
   scales down below sm and grows back to spec at sm/lg. Combined
   selector for specificity, self-contained (no Tailwind race). */
/* Height/font grow in two steps; width is a fallback only — updated search
   pages drive cell width via `flex-1 min-w-0 max-w-[52px]` markup so all 10
   cells stay on one line without wrapping, and it overrides these widths. */
.digit.digit--pos { width: 22px; height: 42px; font-size: 1.125rem; }
@media (min-width: 640px)  { .digit.digit--pos { width: 36px; height: 48px; font-size: 1.25rem; } }
@media (min-width: 1024px) { .digit.digit--pos { width: 44px; } }

/* Select / dropdown — white, warm border, gold hover. */
.select {
  width: 100%;
  height: 44px;
  padding: 0 40px 0 12px;
  background-color: var(--surface-card);
  color: var(--ink-700);
  border: 1.5px solid var(--line-200);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  transition: border-color var(--dur-fast) var(--ease-standard);
  /* Reset native control chrome — Safari and Chrome render <select> very
     differently (arrow shape, inset padding) without this, so we supply
     one custom trailing chevron per DESIGN.md §9.x instead. */
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237A756D' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px 16px;
}
.select:hover { border-color: var(--gold-300); }
.select:focus { outline: none; border-color: var(--gold-400); box-shadow: 0 0 0 3px var(--focus-ring); }

/* Text input — same warm shell as select. */
.field {
  width: 100%;
  height: 44px;
  padding: 0 12px;
  background-color: var(--surface-card);
  color: var(--ink-700);
  border: 1.5px solid var(--line-200);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.field::placeholder { color: var(--ink-300); }
.field:hover { border-color: var(--gold-300); }
.field:focus { outline: none; border-color: var(--gold-400); box-shadow: 0 0 0 3px var(--focus-ring); }

/* Mobile search filters — shorter shell to fit more rows above the fold. */
@media (max-width: 639px) {
  .select, .field { height: 38px; font-size: .8rem; }
}

/* Text-input autosuggest combobox (ราคาต่ำสุด / ราคาสูงสุด) — same warm
   shell as .select, with a JS-driven menu instead of native <option>s. */
.combobox__input { padding-right: 40px; }
.combobox__toggle {
  position: absolute;
  top: 0;
  right: 0;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-400);
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  transition: color var(--dur-fast) var(--ease-standard);
}
.combobox__toggle:hover { color: var(--gold-700); }
.combobox__toggle:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }
@media (max-width: 639px) { .combobox__toggle { width: 38px; height: 38px; } }

.combobox__list {
  position: absolute;
  z-index: 20;
  top: calc(100% + 4px);
  left: 0;
  width: 100%;
  max-height: 240px;
  overflow: auto;
  background-color: var(--surface-card);
  border: 1.5px solid var(--line-200);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 6px;
  list-style: none;
}
.combobox__option {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 9px 10px;
  border-radius: 8px;
  font-family: var(--font-num);
  font-size: .875rem;
  color: var(--ink-700);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.combobox__option:hover,
.combobox__option.is-active { background-color: var(--gold-50); }
.combobox__option.is-selected { color: var(--gold-700); font-weight: 700; }
.combobox__option--empty { color: var(--ink-400); font-family: var(--font-body); cursor: default; }
.combobox__option--empty:hover { background-color: transparent; }
.combobox__option-check { flex: none; width: 14px; height: 14px; }

/* Filter label icon — plain gold glyph beside a field label (no circle). */
.filter-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  color: var(--gold-700);
}

/* ------------------------------------------------------------------ *
 * 9. NUMBER CHIPS (0–9)  (DESIGN.md §9.5)  — like / dislike.
 * ------------------------------------------------------------------ */
/* Mobile default is smaller so all 10 digits fit one row without
   wrapping inside the card's px-4 gutters at a 360px viewport; the
   full 38px size returns from the sm breakpoint up where there's room. */
.chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-pill);
  background-color: var(--surface-card);
  border: 1px solid var(--line-200);
  font-family: var(--font-num);
  font-weight: 700;
  font-size: .8125rem;
  color: var(--ink-700);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: transform var(--dur-fast) var(--ease-standard),
              background-color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
@media (min-width: 640px) {
  .chip { width: 38px; height: 38px; border-width: 1.5px; font-size: .875rem; }
}
.chip:hover { border-color: var(--gold-300); }
/* Like (chosen) → gold fill, ink text. */
.chip.is-like {
  background-image: var(--grad-gold);
  border-color: var(--gold-500);
  color: var(--on-gold);
  box-shadow: var(--shadow-sm);
}
/* Dislike (chosen) → ink fill, gold text. */
.chip.is-dislike {
  background-color: var(--ink-800);
  border-color: var(--ink-800);
  color: var(--gold-300);
}

/* Mode tab — "เลขที่ชอบ" / "เลขที่ไม่ชอบ" toggle above the chip row.
   Active tab decides which state a chip tap applies. */
.mode-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  font-weight: 700;
  font-size: .875rem;
  color: var(--ink-400);
  background: transparent;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard),
              background-color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.mode-tab:hover { color: var(--gold-700); }
.mode-tab.is-active { color: var(--gold-700); background-color: var(--gold-50); border-color: var(--line-200); }
@media (max-width: 639px) { .mode-tab { font-size: .75rem; padding: 5px 10px; } }

/* ------------------------------------------------------------------ *
 * 10. CATEGORY SELECTOR TILES ("ด้านที่ต้องการเสริม")  (DESIGN.md §9.6)
 * ------------------------------------------------------------------ */
.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  aspect-ratio: 1 / 1;
  padding: 8px;
  background-color: var(--surface-tile);
  border: 1px solid var(--line-200);
  border-radius: var(--radius-md);
  color: var(--ink-700);
  cursor: pointer;
  text-align: center;
  transition: border-color var(--dur-base) var(--ease-standard),
              background-color var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.tile:hover { border-color: var(--gold-300); box-shadow: var(--shadow-sm); }
/* Icon fills whatever vertical space is left above the label, scaling
   with the square tile at every breakpoint instead of a fixed px size. */
.tile__icon {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  object-fit: contain;
  color: var(--gold-700);
}
.tile__label { flex-shrink: 0; line-height: 1.15; font-size: .8125rem; font-weight: 700; }
/* Emphasis modifier — the "lucky number" tiles (789/289/639) read a
   size up from the regular category tiles. */
.tile__label.tile__label--lg { font-size: .875rem; font-weight: 800; }
@media (max-width: 639px) {
  .tile__label { font-size: .5000rem; }
  .tile__label.tile__label--lg { font-size: .5000rem; }
}

/* Selected — green border + tint + ✓ chip (meaning not by color alone). */
.tile.is-selected { 
  border: 2px solid var(--success);
  /* background-color: var(--success-bg);  */
}
.tile.is-selected::after {
  content: "✓";
  position: absolute;
  bottom: 6px;
  right: 6px;
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  font-size: .75rem;
  font-weight: 700;
  color: #fff;
  background-color: var(--success);
  border-radius: var(--radius-pill);
}

/* ------------------------------------------------------------------ *
 * 11. NAVIGATION BAR  (DESIGN.md §9.7)
 * ------------------------------------------------------------------ */
.nav {
  position: static;
  z-index: 50;
  background-color: var(--ink-900);          /* near-black bar */
  border-bottom: 1px solid var(--gold-800);  /* warm bronze seam, not hard black — matches .footer */
  transition: box-shadow var(--dur-base) var(--ease-standard);
}
/* Lifts a soft warm shadow once the page scrolls (JS toggles .is-stuck). */
.nav.is-stuck { box-shadow: var(--shadow-sm); }

/* Brand logo image — square gold mark, scaled to the bar. */
.nav__logo { height: 52px; width: auto; display: block; }
@media (min-width: 640px) { .nav__logo { height: 60px; } }

/* Desktop link — quiet ink, gold on hover, gold underline when active. */
.nav__link {
  position: relative;
  color: var(--nav-link);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: .975rem;
  white-space: nowrap;
  padding: 6px 2px;
  border-bottom: 2px solid transparent;
  transition: color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.nav__link:hover { color: var(--gold-300); }
.nav__link.is-active {
  color: var(--nav-link);
  border-bottom-color: var(--nav-link);
}

/* Hamburger / search icon buttons in the bar. */
.nav__icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-pill);
  color: var(--nav-link);
  border: 1px solid var(--nav-link);
  /* background-color: #FFFFFF; */
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.nav__icon-btn:hover { background-color: var(--gold-50); color: var(--gold-700); border-color: var(--gold-300); }

/* --- Mobile slide-over drawer ------------------------------------- */
.drawer { position: fixed; inset: 0; z-index: 60; visibility: hidden; }
.drawer.is-open { visibility: visible; }

.drawer__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 16, 8, .45);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.drawer.is-open .drawer__backdrop { opacity: 1; }

/* .nav__icon-btn defaults to a pale gold (right for the near-black nav bar),
   but the drawer panel sits on the light cream --bg-base — darken it there
   so the close (X) button stays readable. */
.drawer__panel .nav__icon-btn { color: var(--ink-700); }

.drawer__panel {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: min(84vw, 320px);
  background-color: var(--bg-base);          /* warm cream drawer */
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  padding: 20px;
  transform: translateX(100%);
  transition: transform var(--dur-slow) var(--ease-out-soft);
  overflow-y: auto;
}
.drawer.is-open .drawer__panel { transform: translateX(0); }

.drawer__link {
  display: block;
  padding: 14px 12px;
  border-radius: var(--radius-md);
  color: var(--ink-700);
  font-weight: 500;
  border-left: 3px solid transparent;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.drawer__link:hover { background-color: var(--gold-50); color: var(--gold-700); }
.drawer__link.is-active {
  color: var(--gold-700);
  background-color: var(--gold-50);
  border-left-color: var(--gold-500);
  font-weight: 600;
}

/* Lock page scroll while the drawer is open (JS adds this to <body>). */
body.is-drawer-open { overflow: hidden; }

/* --- Mobile bottom tab bar ---------------------------------------- */
.bottomnav {
  background-color: #FFFFFF;
  border-top: 1px solid var(--line-200);
  box-shadow: 0 -4px 18px rgba(120, 90, 30, .06);
}
.bottomnav__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px 0;
  color: var(--ink-400);                      /* resting = quiet */
  transition: color var(--dur-fast) var(--ease-standard);
}
.bottomnav__item:hover { color: var(--gold-700); }
.bottomnav__item .bottomnav__label { font-size: .625rem; font-weight: 700; }
/* Active tab = gold, same language as the top nav's active link. */
.bottomnav__item.is-active { color: var(--gold-700); }

/* --- Category quick-nav bottom sheet (mobile only, from bottomnav) -
   Same open/close/backdrop/focus-trap recipe as .drawer (§9.7 above),
   but the panel slides up from the bottom instead of in from the side. */
.sheet { position: fixed; inset: 0; z-index: 60; visibility: hidden; }
.sheet.is-open { visibility: visible; }

.sheet__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 16, 8, .45);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.sheet.is-open .sheet__backdrop { opacity: 1; }

.sheet__panel {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: min(88vh, 720px);
  background-color: var(--bg-base);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  transform: translateY(100%);
  transition: transform var(--dur-slow) var(--ease-out-soft);
}
.sheet.is-open .sheet__panel { transform: translateY(0); }
.sheet__panel .nav__icon-btn { color: var(--ink-700); }

.sheet__handle {
  flex-shrink: 0;
  width: 40px;
  height: 4px;
  border-radius: var(--radius-pill);
  /* background-color: var(--line-200); */
  margin: 10px auto 2px;
}

.sheet__header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 20px 14px;
  border-bottom: 1px solid var(--line-200);
}
.sheet__title { font-family: var(--font-display); font-weight: 700; font-size: 1.125rem; color: var(--ink-700); }

.sheet__body {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 20px;
  padding-bottom: max(24px, env(safe-area-inset-bottom));
}

.sheet__section + .sheet__section { margin-top: 28px; }
.sheet__section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  color: var(--ink-700);
  margin-bottom: 14px;
}
.sheet__section-title svg { color: var(--gold-600); flex-shrink: 0; }
/* Lock page scroll while the sheet is open (JS adds this to <body>). */
body.is-sheet-open { overflow: hidden; }

/* ยอดนิยม — horizontal scroll row of dark "medallion" tiles. */
.promo-row {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding: 2px 2px 4px;
  margin: -2px -2px 0;
}
.promo-tile {
  flex: 0 0 108px;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 14px 8px 12px;
  background-color: var(--ink-900);
  border-radius: var(--radius-lg);
  text-align: center;
  transition: transform var(--dur-base) var(--ease-standard);
}
.promo-tile:hover { transform: translateY(-2px); }
.promo-tile__media {
  width: 60px;
  height: 60px;
  border-radius: var(--radius-pill);
  overflow: hidden;
  box-shadow: inset 0 0 0 2px rgba(228, 189, 95, .35);
}
.promo-tile__media img { width: 100%; height: 100%; object-fit: cover; }
.promo-tile__label { font-size: .75rem; font-weight: 700; line-height: 1.3; color: var(--gold-300); }

/* ช่วงราคา — static price-range link chips (same shell as .select/.field). */
.price-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  padding: 0 10px;
  background-color: var(--surface-card);
  border: 1.5px solid var(--line-200);
  border-radius: var(--radius-md);
  color: var(--ink-700);
  font-weight: 600;
  font-size: .8125rem;
  text-align: center;
  transition: border-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              background-color var(--dur-fast) var(--ease-standard);
}
.price-chip:hover { border-color: var(--gold-400); color: var(--gold-700); background-color: var(--gold-50); }

/* ปรึกษาผู้เชี่ยวชาญฟรี — compact dark CTA bar closing the sheet. */
.consult-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 28px;
  background-color: var(--ink-900);
  border: 1px solid var(--gold-600);
  border-radius: var(--radius-pill);
  padding: 8px 8px 8px 14px;
  transition: transform var(--dur-base) var(--ease-standard);
}
.consult-bar:hover { transform: translateY(-1px); }
.consult-bar__icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--gold-500);
  color: var(--gold-400);
}
.consult-bar__text { flex: 1 1 auto; min-width: 0; color: var(--gold-200); font-size: .8125rem; font-weight: 600; line-height: 1.3; }
.consult-bar__cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  height: 38px;
  padding: 0 16px;
  border-radius: var(--radius-pill);
  background-image: var(--grad-gold);
  color: #3A2A08;
  font-weight: 700;
  font-size: .8125rem;
  box-shadow: var(--shadow-gold);
}

/* 789 gold emblem — round gold badge (fallback lockup / other uses). */
.emblem {
  display: inline-grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background-image: var(--grad-gold);
  color: var(--on-gold);
  font-family: var(--font-display);
  font-weight: 800;
  box-shadow: var(--shadow-gold), inset 0 1px 0 rgba(255,255,255,.6);
}

/* ------------------------------------------------------------------ *
 * 12. TRUST BADGE STRIP  (DESIGN.md §9.8)
 * ------------------------------------------------------------------ */
.trust-badge { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center;}
.trust-badge__circle {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: var(--radius-pill);
  background-color: var(--ink-900);
  color: var(--gold-300);
  box-shadow: inset 0 0 0 2px rgba(228,189,95,.25);
}
.trust-badge__label { font-size: .75rem; line-height: 1.3; color: var(--ink-500); font-weight: 500; }
@media (min-width: 640px) { .trust-badge__label { font-size: 1.05rem; } }

/* Pre-rendered badge artwork (ink circle + gold icon baked into the PNG)
   — used in place of .trust-badge__circle where real assets exist. */
.trust-badge__img {
  box-sizing: border-box;
  width: 58px;
  height: 58px;
  padding: 1px;                        /* ring thickness */
  border-radius: var(--radius-pill);
  background-image: var(--grad-gold);  /* gold gradient ring (DESIGN.md §9.8) */
  object-fit: contain;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-standard),
              box-shadow var(--dur-fast) var(--ease-standard);
}
@media (min-width: 640px) { .trust-badge__img { width: 64px; height: 64px; padding: 1px; } }
.trust-badge:hover .trust-badge__img { transform: translateY(-2px) scale(1.04); box-shadow: var(--shadow-gold); }

/* ------------------------------------------------------------------ *
 * 13. SECTION HEADER  (DESIGN.md §9.9)
 * ------------------------------------------------------------------ */
.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 12px;
  margin-bottom: 24px;
  border-bottom: 2px solid var(--line-200);
}
.section-head__title { font-family: var(--font-display); font-weight: 700; font-size: 1.65rem; color: var(--ink-700); line-height: 1.3; }
.section-head__eyebrow { display: block; font-size: .95rem; font-weight: 500; color: var(--ink-400); }
.section-head__link { display: inline-flex; align-items: center; gap: 4px; color: var(--gold-700); font-weight: 600; font-size: .875rem; white-space: nowrap; }
.section-head__link:hover { text-decoration: underline; }

/* Circular emblem beside the section title — pre-rendered gold badge
   artwork (ink circle + icon baked into the PNG, transparent corners),
   same cream-tile treatment as .category-tile (DESIGN.md §9.6). */
.section-head__emblem {
  display: inline-grid;
  place-items: center;
  box-sizing: border-box;
  width: 48px;
  height: 48px;
  padding: 2px;
  background-color: var(--surface-tile);
  border: 1px solid var(--line-200);
  border-radius: var(--radius-md);
  flex: none;
}
.section-head__emblem img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ------------------------------------------------------------------ *
 * 14. HERO  (DESIGN.md §9.10)
 * ------------------------------------------------------------------ */
/* .page-hero-light is the compact-page pair to .page-hero-dark below —
   same cream gradient bg as the home hero, just without the photo variant. */
.hero, .page-hero-light { position: relative; background-color: var(--bg-base); background-image: var(--grad-hero); overflow: hidden; }

/* Photo variant — fades the hero photograph into the page bg at its foot,
   so the section ends softly instead of on a hard rule. */
.hero--photo::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 56px;              /* sized to sit within the section's own
                                 bottom padding gutter, never over content */
  background: linear-gradient(to bottom, rgba(250,248,243,0) 0%, var(--bg-base) 100%);
  pointer-events: none;
}

/* Decorative flowing "silk ribbon" — aria-hidden in markup. */
.hero__ribbon {
  position: absolute;
  inset: 0;
  background-image: var(--grad-ribbon);
  opacity: .10;
  filter: blur(2px);
  pointer-events: none;
}
.hero__title {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.15;
  font-size: clamp(2.125rem, 6vw, 3.5rem);   /* 34 → 56px */
}
/* Gold portion of the hero H1 only — DESIGN.md §4: --grad-gold-hero is
   reserved for this element, don't reuse it on .gold-text elsewhere. */
.hero__title-gold {
  background-image: var(--grad-gold-hero);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.hero__subtitle {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.2;
  font-size: clamp(1.5rem, 4vw, 2.125rem);   /* 24 → 34px */
}

/* Ornamental gold divider — tapered line + center gem, between hero
   title and subtitle. Decorative only (aria-hidden in markup). */
.hero__divider {
  display: flex;
  align-items: center;
  gap: 10px;
  width: min(220px, 60%);
  margin: 6px auto 14px;
}
.hero__divider-line {
  flex: 1 1 auto;
  height: 1px;
  background-image: linear-gradient(90deg, transparent, var(--gold-500) 50%, transparent);
}
.hero__divider-gem {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  background-color: var(--gold-500);
  box-shadow: var(--shadow-gold);
  transform: rotate(45deg);
}

/* ------------------------------------------------------------------ *
 * 15. BANNER SLIDER — full-width promo carousel
 * ------------------------------------------------------------------ */
.banner-slider { position: relative; }

.banner-slider__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
}

.banner-slider__slide {
  flex-shrink: 0;
  width: 100%;
  scroll-snap-align: center;
  background-color: var(--bg-alt);   /* shows while the image loads */
}
.banner-slider__slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Prev/next — solid white circle floating on the image, gold on hover. */
.banner-slider__arrow {
  display: none;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  border-radius: var(--radius-pill);
  background-color: var(--surface-card);
  color: var(--gold-700);
  border: 1px solid var(--line-200);
  box-shadow: var(--shadow-lg);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              transform var(--dur-fast) var(--ease-standard);
}
.banner-slider__arrow:hover { background-color: var(--gold-700); color: #fff; }
.banner-slider__arrow--prev { left: 16px; }
.banner-slider__arrow--next { right: 16px; }
@media (min-width: 640px) {
  .banner-slider__arrow { display: flex; }
}

/* Position dots — muted line color at rest, gold pill when active. */
.banner-slider__dots {
  position: absolute;
  bottom: 14px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 8px;
}
.banner-slider__dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background-color: rgba(255,255,255,.55);
  border: 1px solid rgba(255,255,255,.8);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard),
              width var(--dur-fast) var(--ease-standard);
}
.banner-slider__dot.is-active { width: 22px; background-color: var(--gold-400); border-color: var(--gold-400); }

/* Ad slider — multi-item promo carousel (3-up desktop / 1-up mobile).
   The tiles are pre-designed square graphics, so the frame stays quiet:
   a soft gold hairline + lift on hover, nothing competing with the art. */
.ad-slider__tile {
  display: block;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--gold-200);
  background-color: var(--surface-panel);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard);
}
.ad-slider__tile:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--gold-400); }
.ad-slider__tile img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Prev/next — same white-circle language as .banner-slider__arrow, but
   always visible (this carousel has no dots to lean on for orientation). */
.ad-slider__arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-pill);
  background-color: var(--surface-card);
  color: var(--gold-700);
  border: 1px solid var(--line-200);
  box-shadow: var(--shadow-lg);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.ad-slider__arrow:hover { background-color: var(--gold-700); color: #fff; }

/* ------------------------------------------------------------------ *
 * 16. FOOTER — dark authority surface (DESIGN.md §2 "Dark for authority")
 * ------------------------------------------------------------------ */
.footer {
  background-color: var(--ink-900);
  color: var(--footer-text);
  border-top: 1px solid var(--gold-800);   /* warm bronze seam, not black */
}

.footer__logo { height: 40px; width: auto; }

.footer__tagline { color: var(--nav-link); line-height: 1.6; }

/* Social icon buttons — gold circle outline around the gold brand glyph. */
.footer__social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--gold-800);
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.footer__social-link:hover { border-color: var(--gold-500); }

.footer__heading {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--nav-link);
  margin-bottom: 16px;
}

.footer__link { color: var(--footer-text); transition: color var(--dur-fast) var(--ease-standard); }
.footer__link:hover { color: var(--gold-300); text-decoration: underline; text-underline-offset: 3px; }

.footer__contact-item { display: flex; align-items: flex-start; gap: 10px; }
.footer__contact-icon { flex: none; width: 18px; height: 18px; margin-top: 2px; color: var(--footer-text); }

.footer__divider { border-color: rgba(228, 189, 95, .16); }   /* faint gold hairline, not gray-300 */

.footer__bottom { color: var(--ink-300); }

/* ------------------------------------------------------------------ *
 * 17. ARTICLE CARD — บทความ / blog teaser
 * ------------------------------------------------------------------ */
.article-card {
  display: flex;
  flex-direction: column;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard);
}
.article-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--gold-200); }

.article-card__img-wrap { aspect-ratio: 2 / 1; overflow: hidden; background-color: var(--bg-alt); }
.article-card__img-wrap img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out-soft);
}
.article-card:hover .article-card__img-wrap img { transform: scale(1.04); }

.article-card__body { padding: 16px 20px 20px; display: flex; flex-direction: column; flex: 1; }
.article-card__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.35;
  color: var(--ink-800);
  margin-bottom: 8px;
}
.article-card__excerpt { font-size: .875rem; color: var(--ink-500); line-height: 1.6; margin-bottom: 16px; }
.article-card__link {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
  font-size: .875rem;
  color: var(--gold-700);
}
.article-card__link:hover { text-decoration: underline; text-underline-offset: 3px; }
.article-card__link svg { transition: transform var(--dur-fast) var(--ease-standard); }
.article-card__link:hover svg { transform: translateX(2px); }

/* ------------------------------------------------------------------ *
 * 18. REVIEW CARD — customer testimonial
 * ------------------------------------------------------------------ */
.review-card {
  position: relative;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  padding: 32px 24px 24px;
  /* box-shadow: var(--shadow-card); */
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard);
}
.review-card:hover { transform: translateY(-2px); 
  /* box-shadow: var(--shadow-lg);  */
  border-color: var(--gold-200); }

/* Decorative oversized quotation mark — quiet, gold-100, behind the text. */
.review-card__quote-mark {
  position: absolute;
  top: 6px;
  left: 20px;
  font-family: var(--font-display);
  font-size: 3.5rem;
  line-height: 1;
  color: var(--gold-100);
  font-weight: 800;
  pointer-events: none;
  user-select: none;
}

.review-card__stars { position: relative; display: flex; gap: 2px; color: var(--gold-500); margin-bottom: 12px; }

.review-card__text {
  position: relative;
  font-size: .9375rem;
  font-style: italic;
  color: var(--ink-500);
  line-height: 1.7;
  margin-bottom: 20px;
}

.review-card__author { display: flex; align-items: center; gap: 12px; }

/* Avatar ring — same gold-padding trick as .trust-badge__img. */
.review-card__avatar {
  box-sizing: border-box;
  width: 48px;
  height: 48px;
  padding: 2px;
  border-radius: var(--radius-pill);
  background-image: var(--grad-gold);
  object-fit: cover;
}

.review-card__name { font-weight: 700; font-size: .875rem; color: var(--ink-800); }
.review-card__role { font-size: .75rem; color: var(--ink-400); }

/* ------------------------------------------------------------------ *
 * 19. VIDEO CARD — portrait video teaser.
 * Reuses .article-card / __body / __title / __excerpt / __link for the
 * card shell and text (same rhythm); only the portrait thumbnail and
 * play badge are new.
 * ------------------------------------------------------------------ */
.video-card__img-wrap {
  position: relative;
  aspect-ratio: 9 / 16;
  overflow: hidden;
  background-color: var(--bg-alt);
}
.video-card__img-wrap img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out-soft);
}
.article-card:hover .video-card__img-wrap img { transform: scale(1.04); }

/* Small gold "video" badge — a content-type marker, not a duplicate
   play button (the source thumbnails already carry their own). */
.video-card__badge {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background-image: var(--grad-gold);
  color: var(--on-gold);
  box-shadow: var(--shadow-sm);
}

/* ------------------------------------------------------------------ *
 * 20. CTA BANNER — closing call-to-action. Deliberate exception to the
 * "gold is a spice" rule, but dialed back to a warm gold wash (capped at
 * gold-400, not the full --grad-gold-diagonal bronze) so the closing
 * CTA reads as a soft foil tint rather than a heavy plaque. Text uses
 * --on-gold (#3A2A08), the token DESIGN.md verifies for AA contrast on
 * the gold scale.
 * ------------------------------------------------------------------ */
.cta-banner {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-xl);
  background-image: linear-gradient(135deg, var(--gold-50) 0%, var(--gold-200) 45%, var(--gold-400) 100%);
  border: 1px solid var(--gold-200);
  box-shadow: var(--shadow-card), inset 0 1px 0 rgba(255,255,255,.55);
  padding: 48px 24px;
  text-align: center;
}
.cta-banner::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--grad-gold-sheen);
  pointer-events: none;
}
.cta-banner__icon {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-pill);
  background-color: var(--ink-900);
  color: var(--gold-300);
  margin-bottom: 16px;
  box-shadow: var(--shadow-sm), 0 0 0 3px rgba(255,255,255,.35);
}
.cta-banner__title {
  position: relative;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.375rem, 3vw, 1.75rem);
  color: var(--on-gold);
  margin-bottom: 8px;
}
.cta-banner__text {
  position: relative;
  color: var(--on-gold);
  margin-bottom: 24px;
  font-size: .9375rem;
}
.cta-banner > .flex { position: relative; }

/* ------------------------------------------------------------------ *
 * 21. SERVICE CARD — บริการจากเรา feature grid.
 * Same ink-circle + gold-icon language as the hero trust badges and
 * section-head emblems, reused here for a third feature-highlight spot.
 * ------------------------------------------------------------------ */
.service-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  padding: 32px 24px;
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard);
}
.service-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--gold-200); }

.service-card__icon {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  border-radius: var(--radius-pill);
  background-color: var(--ink-900);
  color: var(--gold-300);
  margin-bottom: 16px;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-standard);
}
.service-card:hover .service-card__icon { transform: scale(1.06); }

.service-card__title { font-family: var(--font-display); font-weight: 700; font-size: 1rem; color: var(--ink-800); margin-bottom: 8px; }
.service-card__text { font-size: .875rem; color: var(--ink-500); line-height: 1.6; }

/* ------------------------------------------------------------------ *
 * 22. MOTION & REDUCED-MOTION  (DESIGN.md §10)
 * ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------------------------------------------------------ *
 * 23. CMS CONTENT — long-form body copy fetched from the CMS.
 * The rich-text editor outputs bare h2/h3/p/ol/ul/a/strong with no
 * classes, so everything is styled off the .cms-content wrapper. Keep
 * these rules limited to what an editor can actually produce.
 * ------------------------------------------------------------------ */
.cms-content { color: var(--ink-500);}
.cms-content > * + * { margin-top: 1rem; }

.cms-content h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.375rem;
  color: var(--ink-700);
  margin-top: 2.5rem;
}
.cms-content h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.125rem;
  color: var(--ink-700);
  margin-top: 2rem;
}
.cms-content p { line-height: 1.4; }
.cms-content strong { color: var(--ink-700); font-weight: 600; }

.cms-content a { color: var(--gold-700); font-weight: 600; }
.cms-content a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Quill editor output (admin CMS pages) uses these alignment classes. */
.cms-content .ql-align-center { text-align: center; }
.cms-content .ql-align-right { text-align: right; }
.cms-content .ql-align-justify { text-align: justify; }

/* Lists — native browser markers (Tailwind's preflight strips them,
   so restore decimal/disc + indent here). */
.cms-content ol { list-style: decimal; padding-left: 1.5rem; }
.cms-content ul { list-style: disc; padding-left: 1.5rem; }
.cms-content li + li { margin-top: .5rem; }
.cms-content li::marker {font-weight: 600; }

/* Quill renders bulleted AND numbered lists inside a shared <ol>, marking
   the item type with data-list rather than switching the wrapper tag — so
   the marker style has to be driven off that attribute, not the tag name.
   Nesting is flattened the same way: Tab-indented items stay siblings in
   the same <ol> and get a ql-indent-N class instead of a real nested list. */
.cms-content ol li[data-list="bullet"] { list-style-type: disc; }
.cms-content ol li[data-list="ordered"] { list-style-type: decimal; }

.cms-content li.ql-indent-1 { padding-left: 1.5rem; }
.cms-content li.ql-indent-2 { padding-left: 3rem; }
.cms-content li.ql-indent-3 { padding-left: 4.5rem; }
.cms-content ol li[data-list="bullet"].ql-indent-1 { list-style-type: circle; }
.cms-content ol li[data-list="bullet"].ql-indent-2,
.cms-content ol li[data-list="bullet"].ql-indent-3 { list-style-type: square; }

/* Single images — Tailwind's preflight renders <img> as a block, so the
   editor's text-align can never move it; position it with auto margins
   instead. Quill puts the alignment class on the wrapping <p>, but pasted
   markup sometimes carries it on the <img> (or drops the <p> entirely), so
   all three shapes are covered. The multi-image paragraph is excluded — the
   gallery grid below owns it. */
.cms-content img { display: block; max-width: 100%; height: auto; }

.cms-content img.ql-align-center,
.cms-content .ql-align-center:not(:has(img ~ img)) img { margin-inline: auto; }

.cms-content img.ql-align-right,
.cms-content .ql-align-right:not(:has(img ~ img)) img { margin-inline: auto 0; }

/* Image gallery — a <p> wrapping 2+ <img> (rich-text editors emit multiple
   photos as sibling <img> inside one paragraph). Stacks on mobile, 3-up
   from the lg breakpoint so it reads as a gallery, not a stray column. */
.cms-content p:has(> img + img) {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}
.cms-content p:has(> img + img) img {
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}
@media (min-width: 640px) {
  .cms-content p:has(> img + img) { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .cms-content p:has(> img + img) { grid-template-columns: repeat(3, 1fr); }
}

/* Contact map — the CMS embed code (pasted via Quill's "embed" button) carries
   its own fixed width/height attributes, so force it to fill the frame here
   instead of relying on the pasted markup. */
.contact-map { position: relative; }
.contact-map iframe {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 320px;
  border: 0;
}

/* Contact page — office location list. Scoped to this block only (not all
   .cms-content) so it always renders as a gold check-icon list. Quill 2.x
   also saves an empty <span class="ql-ui"> UI marker inside each <li> — hide it. */
.contact-location .ql-ui { display: none; }
.contact-location ol { list-style: none; padding-left: 0; }
.contact-location li[data-list="bullet"] {
  list-style: none;
  position: relative;
  padding-left: 1.5rem;
}
.contact-location li + li { margin-top: .375rem; }
.contact-location li[data-list="bullet"]::before {
  content: "";
  position: absolute;
  left: 0;
  top: .2em;
  width: 1rem;
  height: 1rem;
  background-color: var(--gold-600);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='black'%3E%3Cpath fill-rule='evenodd' d='M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='black'%3E%3Cpath fill-rule='evenodd' d='M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z' clip-rule='evenodd'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* ------------------------------------------------------------------ *
 * 24. TEAM PANEL — ทีมงานของเรา (About page).
 * Thin gold keyline frame (border only — "gold is a spice", no flat
 * fill) around a centered gallery of plain headshot photos. Photos wrap
 * via flexbox so the row count adapts to viewport width instead of a
 * fixed grid that would force awkward columns at 8 items.
 * ------------------------------------------------------------------ */
.team-panel {
  border: 1.5px solid var(--gold-300);
  border-radius: var(--radius-xl);
  background-color: var(--surface-card);
  padding: 32px 20px;
  text-align: center;
}
.team-panel__title { font-family: var(--font-display); font-weight: 800; font-size: 1.5rem; margin-bottom: 8px; }
.team-panel__subtitle { font-size: .9375rem; color: var(--ink-500); margin-bottom: 28px; }

/* Fixed column count so rows stay even; ramps 2 → 3 → 5 across breakpoints.
   max-width caps tile size on wide screens while keeping the row centered. */
.team-panel__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  justify-content: center;
  gap: 20px 16px;
  max-width: 420px;
  margin-inline: auto;
}

.team-panel__member { width: 100%; }

.team-panel__photo {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-standard), box-shadow var(--dur-base) var(--ease-standard);
}
.team-panel__member:hover .team-panel__photo { transform: translateY(-2px); box-shadow: var(--shadow-lg); }

/* Placeholder tile for members whose photo hasn't been added yet — soft gold
   wash + user silhouette, same footprint/radius as a real photo. */
.team-panel__photo--placeholder {
  display: grid;
  place-items: center;
  background: linear-gradient(160deg, var(--gold-100) 0%, var(--gold-200) 100%);
  border: 1px solid var(--gold-300);
}
.team-panel__photo--placeholder svg { width: 46%; height: auto; color: var(--gold-700); opacity: .85; }

.team-panel__name { margin-top: 10px; font-family: var(--font-display); font-weight: 700; font-size: .875rem; color: var(--ink-800); }
.team-panel__role { font-size: .75rem; color: var(--gold-700); font-weight: 600; margin-top: 2px; }

@media (min-width: 640px) {
  .team-panel { padding: 40px 32px; }
  .team-panel__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 560px; }
}
@media (min-width: 1024px) {
  .team-panel__grid { grid-template-columns: repeat(5, minmax(0, 1fr)); max-width: 900px; }
}

/* ------------------------------------------------------------------ *
 * 25. OFFICE GALLERY — หน้าร้าน / ออฟฟิศของเรา (About page).
 * Storefront + interior photos, uniform tiles (same radius/shadow
 * recipe as the CMS image gallery, DESIGN.md §23).
 * ------------------------------------------------------------------ */
.office-gallery__photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-standard), box-shadow var(--dur-base) var(--ease-standard);
}
.office-gallery__photo:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }

/* ------------------------------------------------------------------ *
 * 26. VALUE PANEL — แนวคิด พันธกิจ และคุณค่าของเรา (About page).
 * Soft cream panel, 3 columns split by a hairline on desktop (same
 * divider trick as .card__attrs), stacked with no divider on mobile.
 * ------------------------------------------------------------------ */
.value-panel {
  background-color: var(--surface-panel);
  border-radius: var(--radius-xl);
  padding: 32px 24px;
  box-shadow: var(--shadow-sm);
}
.value-panel__title {
  text-align: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.125rem;
  color: var(--ink-700);
  margin-bottom: 28px;
}

.value-panel__grid { display: flex; flex-direction: column; gap: 28px; }
.value-panel__col { min-width: 0; }
.value-panel__col--center { text-align: center; }

.value-panel__col-icon { display: grid; place-items: center; width: 32px; height: 32px; margin: 0 auto 8px; color: var(--gold-600); }
.value-panel__col-title { font-family: var(--font-display); font-weight: 700; font-size: .9375rem; color: var(--gold-700); margin-bottom: 10px; }
.value-panel__col-title--inline { display: flex; align-items: center; gap: 8px; }
.value-panel__col-text { font-size: .875rem; color: var(--ink-500); line-height: 1.7; }

.value-panel__list { font-size: .875rem; color: var(--ink-500); line-height: 1.6; padding-left: 1.125rem; list-style: disc; }
.value-panel__list li + li { margin-top: 6px; }
.value-panel__list li::marker { color: var(--gold-500); }

@media (min-width: 768px) {
  .value-panel { padding: 40px 32px; }
  .value-panel__grid { flex-direction: row; gap: 0; }
  .value-panel__col { flex: 1; }
  .value-panel__col + .value-panel__col { border-left: 1px solid var(--line-200); margin-left: 32px; padding-left: 32px; }
}

/* ------------------------------------------------------------------ *
 * 27. FAQ ACCORDION (FAQ page).
 * Each question is its own white card; the answer panel animates via
 * a 0fr → 1fr grid-template-rows track so it collapses/expands to its
 * natural content height without JS measuring or a max-height guess.
 * Items toggle independently (not a single-open accordion) so users
 * can compare answers side by side.
 * ------------------------------------------------------------------ */
.faq-accordion { display: flex; flex-direction: column; gap: 16px; }

.faq-item {
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.faq-item:hover { border-color: var(--gold-200); }
.faq-item.is-open { border-color: var(--gold-300); box-shadow: var(--shadow-card); }

.faq-item__heading { margin: 0; }

.faq-item__question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  min-height: 44px;
  padding: 20px 24px;
  background: transparent;
  border: 0;
  text-align: left;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.0625rem;
  line-height: 1.4;
  color: var(--ink-700);
  cursor: pointer;
}
.faq-item__question:hover { color: var(--gold-700); }
.faq-item__question:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: -3px;
  border-radius: var(--radius-lg);
}

.faq-item__icon {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--gold-600);
  transition: transform var(--dur-base) var(--ease-standard);
}
.faq-item.is-open .faq-item__icon { color: var(--gold-700); transform: rotate(180deg); }

.faq-item__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-standard);
}
.faq-item.is-open .faq-item__panel { grid-template-rows: 1fr; }

.faq-item__answer { overflow: hidden; min-height: 0; }
.faq-item__answer > p {
  padding: 0 24px 20px;
  color: var(--ink-500);
  line-height: 1.7;
}
.faq-item__answer a { color: var(--gold-700); font-weight: 600; }
.faq-item__answer a:hover { text-decoration: underline; text-underline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .faq-item__panel, .faq-item__icon { transition: none; }
}

/* ------------------------------------------------------------------ *
 * 28. TRACKING TABLE (ตรวจสอบพัสดุ page).
 * Near-black header (DESIGN.md "dark for authority") sitting on a
 * white card; rows zebra with --bg-alt for scannability across many
 * rows. One markup for every width: below md the table itself reflows
 * — each row becomes a card and each cell becomes a label/value line
 * via its `data-label` attribute — instead of shipping a second,
 * hand-duplicated mobile list alongside the table.
 * ------------------------------------------------------------------ */
.track-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: .9375rem; }
.track-table thead th {
  background-color: var(--ink-900);
  color: var(--nav-link);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: .8125rem;
  letter-spacing: .02em;
  text-align: left;
  padding: 14px 20px;
  white-space: nowrap;
}
.track-table tbody td {
  padding: 16px 20px;
  color: var(--ink-700);
  border-bottom: 1px solid var(--line-100);
  vertical-align: middle;
  white-space: nowrap;
}
.track-table tbody tr:nth-child(even) { background-color: var(--bg-alt); }
.track-table tbody tr:last-child td { border-bottom: 0; }

/* Carrier logotypes — plain text lockups (no artwork asset shipped for
   these), kept in each carrier's real brand color per DESIGN.md §3.4
   ("keep official logos in their real colors, don't recolor them
   gold") rather than folded into the gold/neutral/success palette. */
.carrier-mark { display: inline-flex; flex-direction: column; line-height: 1.1; }
.carrier-mark__name { font-family: var(--font-display); font-weight: 800; font-size: .9375rem; }
.carrier-mark__sub { font-family: var(--font-body); font-weight: 500; font-size: .625rem; color: var(--ink-400); }
.carrier-mark--ems .carrier-mark__name { color: #0B3B8C; }
.carrier-mark--kex {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border: 1.5px solid #F7941E;
  border-radius: var(--radius-sm);
}
.carrier-mark--kex .carrier-mark__name { color: #F7941E; font-size: .8125rem; letter-spacing: .01em; }

/* Responsive reflow — below md, table/thead/tbody/tr/td drop out of
   table layout so each <tr> can stack as its own card. The header
   row is kept for screen readers but visually hidden (off-screen,
   not display:none) since each cell now prints its own label via
   ::before + data-label instead. */
@media (max-width: 767px) {
  .track-table, .track-table thead, .track-table tbody,
  .track-table tr, .track-table td { display: block; width: 100%; }
  .track-table thead {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  .track-table tbody tr {
    padding: 14px 20px;
    border-bottom: 1px solid var(--line-100);
  }
  .track-table tbody tr:last-child { border-bottom: 0; }
  .track-table tbody td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 0;
    border-bottom: 0;
    white-space: normal;
  }
  .track-table tbody td::before {
    content: attr(data-label);
    flex: none;
    font-weight: 600;
    font-size: .75rem;
    color: var(--ink-400);
  }
}

@media (prefers-reduced-motion: reduce) {
  .track-refresh-icon.is-spinning { animation: none; }
}
.track-refresh-icon.is-spinning { animation: track-spin var(--dur-slow) var(--ease-standard); }
@keyframes track-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* ------------------------------------------------------------------ *
 * 29. VIDEOS PAGE (วิดีโอ page).
 * Filter pills, the portrait/4:3 video-grid card (extends .article-card
 * the same way .video-card does), social-channel stat rows, a compact
 * news list, and a dark ink-900 variant of .cta-banner — reusing
 * "dark for authority" (DESIGN.md §2) so the page bookends on the same
 * near-black tone as its hero banner-slider instead of a new hue.
 * ------------------------------------------------------------------ */

/* Category filter pills ("วิดีโอทั้งหมด / ความรู้เกี่ยวกับเบอร์ / …"). Unlike
   .mode-tab (transparent at rest, for the digit like/dislike toggle),
   these read as full pill buttons at rest so the row scans as filter
   chips, not a segmented control. */
.filter-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 12px 22px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--line-200);
  background-color: var(--surface-card);
  color: var(--ink-500);
  font-weight: 600;
  font-size: .9375rem;
  white-space: nowrap;
  cursor: pointer;
  /* transition: background-color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              box-shadow var(--dur-fast) var(--ease-standard); */
}
.filter-pill:hover { border-color: var(--gold-300); color: var(--gold-700); }
.filter-pill.is-active {
  background-image: var(--grad-gold);
  border-color: transparent;
  color: var(--on-gold);
  /* box-shadow: var(--shadow-gold); */
}

/* Center play button — thin ring + triangle, not a filled disc, so the
   thumbnail photo underneath stays legible (matches the reference). */
.vid-play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  border: 2px solid rgba(255, 255, 255, .85);
  background-color: rgba(10, 10, 10, .18);
  color: #fff;
  transition: transform var(--dur-base) var(--ease-standard);
}
.vid-play svg { fill: #fff; } /* pin the triangle to white regardless of currentColor inheritance */
.article-card:hover .vid-play { transform: translate(-50%, -50%) scale(1.08); }
@media (min-width: 1024px) { .vid-play { width: 60px; height: 60px; } }

/* Duration badge — bottom-right over the thumbnail. */
.vid-duration {
  position: absolute;
  right: 8px;
  bottom: 8px;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  background-color: rgba(10, 10, 10, .75);
  color: #fff;
  font-family: var(--font-num);
  font-weight: 700;
  font-size: .75rem;
  font-variant-numeric: tabular-nums;
}

/* Category tag pill under the video title — quiet gold wash, no border
   (distinct from .badge which is bolder/uppercase for NEW/RECOMMENDED). */
.vid-tag {
  /* display: inline-flex; */
  display: none;
  align-items: center;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background-color: var(--gold-50);
  color: var(--gold-700);
  font-size: .75rem;
  font-weight: 600;
}

/* Social channel stat row ("ติดตามเราได้ทุกช่องทาง"). Brand icon keeps its
   real color per DESIGN.md §3.4, same rule already applied to network
   logos and carrier marks. */
.social-stat {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 20px;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  transition: border-color var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard);
}
.social-stat:hover { border-color: var(--gold-200); box-shadow: var(--shadow-sm); }
.social-stat__icon {
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-pill);
  display: grid;
  place-items: center;
  color: #fff;
}
.social-stat__body { flex: 1 1 auto; min-width: 0; }
.social-stat__title { font-family: var(--font-display); font-weight: 700; font-size: .9375rem; color: var(--ink-800); }
.social-stat__desc { font-size: .8125rem; color: var(--ink-400); margin-top: 2px; }
.social-stat__count {
  flex: none;
  text-align: right;
  font-family: var(--font-num);
  font-weight: 800;
  font-size: 1.1875rem;
  color: var(--ink-800);
  font-variant-numeric: tabular-nums;
}
.social-stat__count-label { font-size: .75rem; color: var(--ink-400); }
.social-stat__arrow {
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-pill);
  display: grid;
  place-items: center;
  background-color: var(--gold-50);
  color: var(--gold-700);
  transition: background-color var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.social-stat:hover .social-stat__arrow { background-color: var(--gold-500); color: #fff; }

/* News list ("ข่าวสารและกิจกรรม") — compact rows, hairline-divided. */
.news-item { display: flex; gap: 14px; align-items: flex-start; padding: 14px 0; }
.news-item + .news-item { border-top: 1px solid var(--line-100); }
.news-item__thumb { flex: none; width: 72px; height: 72px; border-radius: var(--radius-md); object-fit: cover; background-color: var(--bg-alt); }
.news-item__title { font-weight: 600; font-size: .9375rem; line-height: 1.4; color: var(--ink-800); transition: color var(--dur-fast) var(--ease-standard); }
.news-item:hover .news-item__title { color: var(--gold-700); }
.news-item__date { font-size: .75rem; color: var(--ink-400); margin-top: 4px; }

/* Dark CTA banner — reuses .cta-banner's shell/rhythm but swaps the
   light gold-gradient fill for ink-900 + a faint gold glow, so this
   page's closing CTA echoes the dark hero banner-slider above it
   instead of introducing a second closing-CTA language. */
.cta-banner.cta-banner--dark {
  background-image: radial-gradient(120% 140% at 12% 15%, rgba(228, 189, 95, .18) 0%, rgba(10, 10, 10, 0) 55%);
  background-color: var(--ink-900);
  border-color: var(--gold-800);
}
.cta-banner--dark::before { display: none; } /* the sheen overlay is tuned for the light gold bg only */
.cta-banner--dark .cta-banner__title { color: var(--gold-300); }
.cta-banner--dark .cta-banner__text { color: var(--footer-text); }

.cta-checklist { display: flex; flex-direction: column; gap: 14px; }
.cta-checklist__item { display: flex; align-items: center; gap: 10px; color: var(--footer-text); font-size: .875rem; font-weight: 500; }
.cta-checklist__icon {
  flex: none;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background-color: var(--ink-800);
  color: var(--gold-400);
}

/* Compact page hero, dark variant — title + description only (no slider).
   Near-black photo bg (gold light-streaks, DESIGN.md "dark for authority")
   reads as one continuous surface with the nav bar above it; the ::after
   fade softens the bottom edge into --bg-base instead of a hard photo cut,
   same trick as .hero--photo::after. Reuses .hero__title/.hero__title-gold
   (DESIGN.md §4 — the 2-stop gold already tuned for legibility on a dark
   hero) rather than a new type style. Pair: .page-hero-light below. */
.page-hero-dark {
  position: relative;
  overflow: hidden;
  background-color: var(--ink-900); /* fallback while the photo loads */
  background-image: url("../img/hero/hero-bg-page.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.page-hero-dark::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 56px;
  /* background: linear-gradient(to bottom, rgba(10, 10, 10, 0) 0%, var(--bg-base) 100%); */
  pointer-events: none;
}
.page-hero-dark__text { color: var(--footer-text); }


/* ------------------------------------------------------------------ *
 * 29b. HORO PAGE (ทำนายเบอร์). Dark hero carrying the number-analysis
 *      input, then light "what you'll get after predicting" benefit
 *      cards. The hero sits flush under the nav like .hero--photo /
 *      .page-hero-dark — same near-black photo surface, its own bg. *
 * ------------------------------------------------------------------ */
.horo-hero {
  position: relative;
  overflow: hidden;
  background-color: var(--ink-900); /* fallback while the photo loads */
  background-image: url("../img/horo/horo-hero-bg.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
/* Gold "free!" call-out under the hero subtitle. */
.horo-hero__free {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.25rem, 3.5vw, 1.75rem);
  background-image: var(--grad-gold-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Benefit card — cream panel, round gold icon, title + supporting copy.
   Used in the "หลังทำนาย คุณจะได้รับอะไรบ้าง?" grid. */
.benefit-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  padding: 24px 18px;
  background-color: #fff;
  border: 1px solid var(--line-200);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  transition: transform .2s ease, box-shadow .2s ease;
}
.benefit-card:hover { transform: translateY(-3px); box-shadow: 0 12px 32px rgba(120,90,30,.14); }
.benefit-card__icon { width: 64px; height: 64px; object-fit: contain; }
@media (min-width: 640px) { .benefit-card__icon { width: 76px; height: 76px; } }
.benefit-card__title { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; color: var(--ink-700); line-height: 1.3; }
.benefit-card__text { font-size: .8125rem; line-height: 1.55; color: var(--ink-400); }
@media (min-width: 640px) { .benefit-card__text { font-size: .875rem; } }

/* Example-result panel — cream frame around the dark sample screenshot. */
.horo-example {
  background-color: var(--bg-panel, #F9F8F7);
  border: 1px solid var(--line-200);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
  padding: 16px;
}
@media (min-width: 640px) { .horo-example { padding: 22px; } }
.horo-example__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  text-align: center;
  color: var(--ink-700);
  margin-bottom: 14px;
}

/* Horo RESULT summary — safe / danger pair overview boxes shown in the
   result hero (left column). Reuses the .numlb__hero shell for layout. */
.horo-result-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  background: var(--grad-gold-text);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.pair-summary { border: 1.5px solid; border-radius: var(--radius-md); padding: 12px 14px; }
.pair-summary + .pair-summary { margin-top: 12px; }
.pair-summary--safe   { border-color: #BFE3C6; background-color: #F4FBF5; }
.pair-summary--danger { border-color: #F1C9C9; background-color: #FDF4F4; }
.pair-summary__head { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: .9375rem; margin-bottom: 10px; }
.pair-summary--safe   .pair-summary__head { color: #2E7D32; }
.pair-summary--danger .pair-summary__head { color: var(--danger); }
.pair-summary__head svg { flex: none; width: 20px; height: 20px; }
.pair-summary__chips { display: flex; flex-wrap: wrap; gap: 8px; }
.pair-summary__chip {
  min-width: 46px; text-align: center;
  padding: 6px 12px; border-radius: 8px;
  font-family: var(--font-num); font-variant-numeric: tabular-nums;
  font-weight: 700; font-size: 1rem; color: #fff;
}
.pair-summary__chip--safe   { background-color: #2E7D32; }
.pair-summary__chip--mixed  { background-color: var(--gold-600); }
.pair-summary__chip--danger { background-color: var(--danger); }
@media (max-width: 639px) { .pair-summary__chip { min-width: 38px;padding: 4px 4px;  } }
.pair-summary__note {
  margin-top: 10px; text-align: center;
  font-size: .8125rem; color: var(--ink-500);
  background-color: #fff; border-radius: 8px; padding: 8px 10px;
}
/* Result CTA row — inherits the hero's stacked-then-inline behaviour. */
.horo-result-cta { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; margin-top: 4px; }
.horo-result-cta .btn { width: 100%; gap: 8px; }
@media (min-width: 480px) { .horo-result-cta { grid-template-columns: 1fr 1fr; } }

/* Expert consultation banner — dark footer CTA on the result page. */
.horo-expert {
  position: relative; overflow: hidden;
  border-radius: var(--radius-xl);
  background: linear-gradient(120deg, var(--ink-900) 0%, #1E1A12 55%, var(--ink-800) 100%);
  border: 1px solid var(--gold-800);
  display: grid; gap: 20px;
  padding: 22px;
  align-items: center;
}
@media (min-width: 900px) { .horo-expert { grid-template-columns: 200px 1fr auto; padding: 28px 32px; } }
.horo-expert__portrait {
  justify-self: center;
  width: 160px; height: 160px; border-radius: var(--radius-pill);
  object-fit: cover; object-position: top center;
  border: 3px solid var(--gold-500);
  box-shadow: 0 0 0 6px rgba(228,189,95,.14);
}
.horo-expert__eyebrow { color: var(--gold-400); font-size: .8125rem; font-weight: 600; margin-bottom: 6px; }
.horo-expert__title {
  font-family: var(--font-display); font-weight: 800; line-height: 1.25;
  font-size: clamp(1.4rem, 3vw, 2rem); color: #fff; margin-bottom: 8px;
}
.horo-expert__title b {
  background: var(--grad-gold-text);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.horo-expert__text { color: rgba(255,255,255,.72); font-size: .9375rem; line-height: 1.7; }
.horo-expert__actions { display: grid; gap: 10px; justify-items: center; }
@media (min-width: 900px) { .horo-expert__actions { justify-items: stretch; } }
.horo-expert__note { color: rgba(255,255,255,.6); font-size: .8125rem; text-align: center; }


/* ------------------------------------------------------------------ *
 * 30. BLOG PAGE (บทความ page). Grid teaser cards reuse .article-card's
 * shell / img-wrap / title / excerpt (same rhythm as every other teaser
 * card on the site) — only the tag overlay and meta row are new, in
 * place of .article-card__link (grid cards here have no separate
 * "read more" link; the whole card is the click target).
 * ------------------------------------------------------------------ */

/* Outer soft panel that groups the featured article, teaser grid and
   pagination into one surface (DESIGN.md §6 "big container" radius-xl). */
.blog-panel {
  background-color: var(--surface-panel);
  border-radius: var(--radius-xl);
  padding: 20px;
}
@media (min-width: 768px) { .blog-panel { padding: 32px; } }

/* Featured article — horizontal split (image | content) on desktop,
   stacked on mobile. Always visible regardless of the active filter
   pill, same convention as the videos page's unfiltered "แนะนำ" row. */
.blog-featured {
  display: flex;
  flex-direction: column;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  margin-bottom: 24px;
}
@media (min-width: 768px) { .blog-featured { flex-direction: row; } }

.blog-featured__media { flex: none; background-color: var(--bg-alt); }
.blog-featured__media img { display: block; width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 3; }
@media (min-width: 768px) {
  .blog-featured__media { width: 42%; }
  .blog-featured__media img { aspect-ratio: auto; }
}

.blog-featured__body { flex: 1 1 auto; padding: 24px; display: flex; flex-direction: column; gap: 12px; }
@media (min-width: 768px) { .blog-featured__body { padding: 32px; } }

.blog-featured__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.375rem;
  line-height: 1.35;
  color: var(--ink-800);
}
@media (min-width: 768px) { .blog-featured__title { font-size: 1.75rem; } }

.blog-featured__excerpt { font-size: .9375rem; color: var(--ink-500); line-height: 1.7; }

.blog-featured__link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
  font-size: .9375rem;
  color: var(--gold-700);
  margin-top: 4px;
}
.blog-featured__link:hover { text-decoration: underline; text-underline-offset: 3px; }
.blog-featured__link svg { transition: transform var(--dur-fast) var(--ease-standard); }
.blog-featured__link:hover svg { transform: translateX(2px); }

/* Category tag — quiet gold wash pill (DESIGN.md §9.3 "network type"
   tone). Reused inline in the featured card and as an absolute overlay
   on grid-card thumbnails via .blog-card__tag. */
.blog-tag {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  padding: 5px 12px;
  border-radius: var(--radius-pill);
  background-color: var(--gold-50);
  color: var(--gold-700);
  font-size: .75rem;
  font-weight: 700;
}
.blog-card__tag {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1;
  background-color: rgba(255, 255, 255, .92);
  box-shadow: var(--shadow-sm);
}

/* Meta row — date + views (grid cards), plus read-time on the featured
   card. Icons are decorative; the number/label always carries the value. */
.blog-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; font-size: .8125rem; color: var(--ink-400); font-variant-numeric: tabular-nums; }
.blog-meta__item { display: inline-flex; align-items: center; gap: 5px; }
.blog-meta__item svg { flex: none; width: 14px; height: 14px; }
.blog-featured .blog-meta { padding-top: 12px; margin-top: 4px; border-top: 1px solid var(--line-100); }

/* Grid teaser card — meta row sits at the foot of .article-card__body. */
.blog-card .article-card__body { gap: 8px; }
.blog-card .blog-meta { margin-top: auto; padding-top: 4px; }

/* ---- Pagination ---- */
.pagination { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; margin-top: 32px; }
.pagination__arrow,
.pagination__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 40px;
  padding: 0 4px;
  border-radius: var(--radius-pill);
  font-weight: 600;
  font-size: .9375rem;
  color: var(--ink-500);
  border: 1.5px solid transparent;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.pagination__arrow { color: var(--gold-700); border-color: var(--line-200); background-color: var(--surface-card); }
.pagination__arrow:hover { border-color: var(--gold-300); background-color: var(--gold-50); }
.pagination__arrow[aria-disabled="true"] { color: var(--ink-300); pointer-events: none; }
.pagination__num:hover { background-color: var(--gold-50); color: var(--gold-700); }
.pagination__num.is-active { background-image: var(--grad-gold); color: var(--on-gold); }
.pagination__ellipsis { color: var(--ink-300); padding: 0 4px; }

/* ------------------------------------------------------------------ *
 * 31. BLOG DETAIL PAGE (บทความ detail). Article header reuses .blog-tag
 * and .blog-meta__item from §30 so the tag pill and meta icons stay
 * visually identical between the list and detail pages.
 * ------------------------------------------------------------------ */

/* Breadcrumb */
.breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: .8125rem; color: var(--ink-400); }
.breadcrumb__link { color: var(--ink-400); }
.breadcrumb__link:hover { color: var(--gold-700); text-decoration: underline; text-underline-offset: 3px; }
.breadcrumb__sep { display: inline-flex; color: var(--ink-300); }
.breadcrumb__sep svg { width: 14px; height: 14px; }
.breadcrumb__current { color: var(--ink-700); font-weight: 600; }

/* Article title + meta row */
.article-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.625rem;
  line-height: 1.35;
  color: var(--ink-800);
}
@media (min-width: 768px) { .article-title { font-size: 2rem; } }

.article-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--line-100);
}

/* Share buttons */
.share-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--line-200);
  background-color: var(--surface-card);
  color: var(--ink-500);
  transition: border-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              background-color var(--dur-fast) var(--ease-standard);
}
.share-btn:hover { border-color: var(--gold-300); color: var(--gold-700); background-color: var(--gold-50); }
.share-btn--facebook { background-color: #1877F2; border-color: #1877F2; color: #fff; }
.share-btn--facebook:hover { background-color: #1877F2; color: #fff; opacity: .88; }
.share-btn--line { background-color: #06C755; border-color: #06C755; color: #fff; }
.share-btn--line:hover { background-color: #06C755; color: #fff; opacity: .88; }
.share-btn.is-copied { border-color: var(--success); color: var(--success); background-color: var(--success-bg); }

/* Related-article card ("บทความแนะนำ") — compact image + title + date,
   no tag/excerpt/views (lighter rhythm than .blog-card since these are
   secondary reading suggestions, not the primary listing grid). */
.related-card { display: block; }
.related-card__img { aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius-md); background-color: var(--bg-alt); }
.related-card__img img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out-soft);
}
.related-card:hover .related-card__img img { transform: scale(1.04); }
.related-card__title {
  margin-top: 10px;
  font-weight: 600;
  font-size: .9375rem;
  line-height: 1.4;
  color: var(--ink-800);
  transition: color var(--dur-fast) var(--ease-standard);
}
.related-card:hover .related-card__title { color: var(--gold-700); }
.related-card__date { display: block; margin-top: 4px; font-size: .75rem; color: var(--ink-400); }

/* ------------------------------------------------------------------ *
 * 30. LIGHTBOX — full-screen image viewer (global component).
 * Injected once by app.js and reused for every clickable image on the
 * page (CMS content photos, office gallery, …). Same overlay recipe as
 * the mobile drawer (§ mobile slide-over): backdrop fade + panel
 * transition, focus trap, Esc to close.
 * ------------------------------------------------------------------ */
.lightbox { position: fixed; inset: 0; z-index: 80; visibility: hidden; }
.lightbox.is-open { visibility: visible; }

.lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 8, 4, .88);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.lightbox.is-open .lightbox__backdrop { opacity: 1; }

.lightbox__dialog {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 64px 16px;
}

.lightbox__figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  max-width: min(92vw, 1100px);
  opacity: 0;
  transform: scale(.96);
  transition: opacity var(--dur-slow) var(--ease-out-soft),
              transform var(--dur-slow) var(--ease-out-soft);
}
.lightbox.is-open .lightbox__figure { opacity: 1; transform: scale(1); }

.lightbox__img {
  display: block;
  max-width: 100%;
  max-height: 76vh;
  width: auto;
  height: auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  background-color: var(--surface-card);
  object-fit: contain;
}

.lightbox__caption {
  max-width: 62ch;
  color: var(--on-ink);
  font-size: .875rem;
  text-align: center;
  line-height: 1.5;
}

.lightbox__close,
.lightbox__prev,
.lightbox__next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-pill);
  color: var(--on-ink);
  background-color: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .28);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.lightbox__close:hover,
.lightbox__prev:hover,
.lightbox__next:hover { background-color: var(--gold-400); color: var(--on-gold); border-color: var(--gold-400); }
.lightbox__close:focus-visible,
.lightbox__prev:focus-visible,
.lightbox__next:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

.lightbox__close { position: absolute; top: 16px; right: 16px; }

.lightbox__prev,
.lightbox__next { position: absolute; top: 50%; transform: translateY(-50%); }
.lightbox__prev { left: 8px; }
.lightbox__next { right: 8px; }

/* JS sets `hidden` on prev/next/counter when the group has one photo, but
   the `display: inline-flex` above outranks the UA `[hidden]{display:none}`
   — the buttons stayed visible (and did nothing). Restore `hidden`. */
.lightbox__prev[hidden],
.lightbox__next[hidden],
.lightbox__counter[hidden] { display: none !important; }

.lightbox__counter {
  position: absolute;
  top: 18px;
  left: 20px;
  color: var(--on-ink-muted);
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .02em;
}

/* Lock page scroll while the lightbox is open (JS adds this to <body>). */
body.is-lightbox-open { overflow: hidden; }

/* Clickable images opened by the lightbox get a hint cursor + gentle hover lift. */
.js-lightbox-img { cursor: zoom-in; }
.js-lightbox-img:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

@media (min-width: 640px) {
  .lightbox__close { top: 20px; right: 20px; }
  .lightbox__prev { left: 20px; }
  .lightbox__next { right: 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .lightbox__backdrop,
  .lightbox__figure,
  .lightbox__close,
  .lightbox__prev,
  .lightbox__next { transition: none; }
}

/* ------------------------------------------------------------------ *
 * 32. REVIEWS PAGE (รีวิว page).
 * Dark testimonial carousel (private-banking mood: near-black card,
 * gold quote + name, English-caps role label), the in-page jump nav
 * (reuses .filter-pill as anchor links), and a chat-style review card
 * for "ลูกค้าที่เปลี่ยนเบอร์" voice testimonials — a small LINE-style
 * two-bubble conversation. The customer's own bubble borrows --grad-gold
 * (kept to a small area, read as UI chrome being depicted, not a new
 * brand accent — same allowance DESIGN.md gives real network logos).
 * ------------------------------------------------------------------ */

/* In-page jump nav — active pill tracks scroll position via JS. */
.review-jumpnav { scroll-padding-left: 16px; }

/* Dark testimonial card — the center slide (2nd of 3 on desktop) reads
   as "featured": full scale + lift, flanking cards sit smaller/quieter
   so the eye lands in the middle first, like the reference mockup. */
.testimonial-card {
  position: relative;
  height: 100%;
  background-color: var(--ink-900);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: var(--radius-lg);
  padding: 40px 24px 28px;
  text-align: center;
  transform: scale(.94);
  transition: transform var(--dur-slow) var(--ease-out-soft),
              opacity var(--dur-slow) var(--ease-out-soft),
              box-shadow var(--dur-slow) var(--ease-out-soft);
}
@media (min-width: 768px) {
  .testimonial-card:nth-child(2) {
    transform: scale(1);
    box-shadow: var(--shadow-lg);
    z-index: 1;
  }
}
.testimonial-card__avatar {
  box-sizing: border-box;
  width: 64px;
  height: 64px;
  padding: 2px;
  margin: 0 auto 16px;
  border-radius: var(--radius-pill);
  background-image: var(--grad-gold);
  object-fit: cover;
}
.testimonial-card__quote-mark {
  display: block;
  font-family: var(--font-display);
  font-size: 2.5rem;
  line-height: 1;
  color: var(--gold-600);
  font-weight: 800;
  margin-bottom: 4px;
}
.testimonial-card__text { color: var(--on-ink); font-size: .9375rem; line-height: 1.7; margin-bottom: 20px; }
.testimonial-card__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: .03em;
  color: var(--gold-400);
  text-transform: uppercase;
}
.testimonial-card__role {
  font-size: .75rem;
  color: var(--on-ink-muted);
  margin-top: 2px;
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* Chat review card — wraps a real chat-screenshot thumbnail (object-contain,
   so the customer's highlighted message never gets cropped) + a caption. */
.chat-review {
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard);
}
.chat-review:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--gold-200); }

.chat-review__foot { padding: 14px 16px; border-top: 1px solid var(--line-100); }
.chat-review__foot-title { font-weight: 600; font-size: .875rem; color: var(--ink-800); line-height: 1.4; }

/* "All reviews" detail page (reviews-all.html) — box-style category
   switcher. Unlike .filter-pill (single-line rounded chip), each tab
   here carries a 2-line label (category + description), so it needs a
   taller box shape; .review-tab's flex-column + items-stretch on the
   parent row keeps every box the same height regardless of 1 or 2 lines. */
.review-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 150px;
  padding: 12px 18px;
  border-radius: var(--radius-md);
  border: 1.5px solid var(--line-200);
  background-color: var(--surface-card);
  color: var(--ink-500);
  font-size: .8125rem;
  line-height: 1.45;
  font-weight: 600;
  text-align: center;
}
.review-tab:hover { border-color: var(--gold-300); color: var(--gold-700); }
.review-tab.is-active {
  background-image: var(--grad-gold);
  border-color: transparent;
  color: var(--on-gold);
  box-shadow: var(--shadow-gold);
}

/* ------------------------------------------------------------------ *
 * 33. SEARCH / LISTING PAGE (เบอร์ทั้งหมด page). Left rail of dark-header
 * filter boxes ("dark for authority", DESIGN.md §2) + a dark listing
 * toolbar (result count / sort) above the product grid, which reuses
 * .card (§6) unchanged. Pagination reuses .pagination (§30) as-is.
 * ------------------------------------------------------------------ */

/* Sidebar filter box — dark header, white link list. */
.filter-box {
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.filter-box__header {
  position: relative;
  overflow: hidden;
  background-color: var(--ink-900);
  background-image: url("../img/search/sidebar-title-bg.png");
  background-repeat: no-repeat;
  background-position: right bottom;
  background-size: cover;
  padding: 14px 20px;
  border-bottom: 2px solid var(--gold-500);
}
.filter-box__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  color: var(--gold-300);
  text-align: center;
}
.filter-box__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 20px;
  color: var(--ink-700);
  font-size: .9375rem;
  font-weight: 500;
  line-height: 1.4;
  border-top: 1px solid var(--line-100);
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.filter-box__list li:first-child .filter-box__item { border-top: none; }
.filter-box__item:hover { background-color: var(--gold-50); color: var(--gold-700); }
.filter-box__item:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.filter-box__item svg { flex: none; width: 16px; height: 16px; color: var(--gold-600); }
.filter-box__item-sub { display: block; font-size: .75rem; font-weight: 400; color: var(--ink-400); margin-top: 2px; }
.filter-box__list--network .filter-box__item span { text-transform: uppercase; letter-spacing: .03em; }

/* CTA variant — "เบอร์ฝากขาย" box: short pitch + button instead of a list. */
.filter-box__cta-body { padding: 20px; text-align: center; }
.filter-box__cta-text { font-size: .875rem; color: var(--ink-500); line-height: 1.6; margin-bottom: 14px; }

/* Listing toolbar — dark pill bar: result count (left) + sort (right). */
.listing-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background-image: linear-gradient(90deg, var(--ink-900) 0%, var(--ink-700) 100%);
  border: 1.5px solid var(--gold-400);
  border-radius: var(--radius-pill);
  padding: 8px 8px 8px 20px;
}
.listing-toolbar__title {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  color: #fff;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .9375rem;
}
.listing-toolbar__title-text { min-width: 0; }
.listing-toolbar__count {
  display: inline-flex;
  align-items: center;
  background-image: var(--grad-gold);
  color: var(--on-gold);
  font-weight: 700;
  font-size: .8125rem;
  padding: 5px 14px;
  border-radius: var(--radius-pill);
  font-variant-numeric: tabular-nums;
}

/* Sort select — white pill, custom chevron (same recipe as .select §8). */
.sort-select-wrap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background-color: var(--surface-card);
  border-radius: var(--radius-pill);
  padding: 8px 16px;
  flex: none;
}
.sort-select-wrap:focus-within { box-shadow: 0 0 0 3px var(--focus-ring); }
.sort-select-wrap label { font-size: .8125rem; color: var(--ink-400); white-space: nowrap; }
.sort-select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-color: transparent;
  border: 0;
  color: var(--ink-800);
  font-weight: 600;
  font-size: .875rem;
  padding-right: 20px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23B68438' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right center;
  background-size: 14px 14px;
}
.sort-select:focus { outline: none; }

/* Below 480px: keep the toolbar a single row (matches desktop layout) —
   shrink type/padding and hide the redundant "เรียงตาม:" label instead of
   letting the sort control drop to its own full-width row. */
@media (max-width: 499px) {
  .listing-toolbar { flex-wrap: nowrap; padding: 8px 8px 8px 12px; gap: 8px; border-radius: var(--radius-lg); }
  .listing-toolbar__title { flex: 1 1 auto; min-width: 0; gap: 6px; font-size: .8125rem; }
  .listing-toolbar__title-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .listing-toolbar__count { flex: none; padding: 4px 10px; font-size: .75rem; }
  .sort-select-wrap { flex: none; width: auto; padding: 6px 10px; gap: 4px; }
  .sort-select-wrap label {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
  }
  .sort-select { font-size: .8125rem; padding-right: 16px; background-size: 12px 12px; }
}

/* ------------------------------------------------------------------ *
 * MOBILE SEARCH PANEL TOGGLE  (search.html — advanced search card)
 * Below 640px the detailed filter form collapses behind a single
 * "ค้นหาเบอร์มงคล" button so the card opens compact; the panel expands
 * in place when tapped. Same 0fr → 1fr grid trick as .faq-item__panel
 * so height animates without JS measuring content. Tablet/desktop
 * always show the full form and hide the toggle button entirely.
 * ------------------------------------------------------------------ */
.search-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-standard);
}
.search-panel.is-open { grid-template-rows: 1fr; }
.search-panel__inner { overflow: hidden; min-height: 0; }

.search-toggle { display: flex; }

/* Open state — the gold button (needed to invite a tap on a collapsed
   card) steps back to plain text once the full form + real ค้นหา/
   ล้างค่า buttons are already on screen, so it reads as "close this"
   rather than competing with them. */
.search-toggle.is-open {
  background-image: none;
  background-color: transparent;
  box-shadow: none;
  color: var(--ink-400);
  min-height: auto;
  padding: 4px 0 0;
  font-size: 0.875rem;
  margin: 8px 0px;
}
.search-toggle.is-open:hover  { transform: none; box-shadow: none; color: var(--gold-700); text-decoration: underline; text-underline-offset: 3px; }
.search-toggle.is-open:active { transform: none; box-shadow: none; }
.search-toggle.is-open svg { display: none; }

@media (min-width: 640px) {
  .search-panel { grid-template-rows: 1fr; }
  .search-toggle { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .search-panel { transition: none; }
}

/* ------------------------------------------------------------------ *
 * Number detail lightbox (.numlb) — DESIGN.md §9.11 overlay recipe
 * Injected by assets/js/number-modal.js; opened from any
 * <a href="/number/…" data-number-open>. Same scrim/scale-in motion as
 * the nav drawer and image lightbox so the whole site feels like one
 * surface opening, not three different ones.
 * ------------------------------------------------------------------ */
.numlb { position: fixed; inset: 0; z-index: 90; visibility: hidden; }
.numlb.is-open { visibility: visible; }
body.is-numlb-open { overflow: hidden; }

.numlb__backdrop {
  position: absolute; inset: 0;
  background-color: rgba(10, 8, 4, .72);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out-soft);
}
.numlb.is-open .numlb__backdrop { opacity: 1; }

.numlb__dialog {
  position: absolute; inset: 0;
  display: flex; align-items: flex-start; justify-content: center;
  padding: 0;
  pointer-events: none;
}

/* The scrolling sheet. Full-bleed on mobile, an inset card from md up. */
.numlb__scroll {
  pointer-events: auto;
  width: 100%; max-width: 960px; max-height: 100%;
  overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  background-color: var(--bg-base);
  opacity: 0; transform: translateY(16px) scale(.985);
  transition: opacity var(--dur-slow) var(--ease-out-soft),
              transform var(--dur-slow) var(--ease-out-soft);
}
.numlb.is-open .numlb__scroll { opacity: 1; transform: none; }
.numlb__scroll:focus { outline: none; }

.numlb__body { padding: 16px 12px 40px; display: grid; gap: 12px; }

.numlb__close {
  position: fixed; top: 12px; right: 12px; z-index: 2;
  pointer-events: auto;
  width: 44px; height: 44px; border-radius: var(--radius-pill);
  display: inline-flex; align-items: center; justify-content: center;
  background-color: rgba(20, 20, 20, .72);
  border: 1px solid rgba(255, 255, 255, .22);
  color: #fff;
  transition: background-color var(--dur-base) var(--ease-standard),
              color var(--dur-base) var(--ease-standard);
}
.numlb__close svg { width: 20px; height: 20px; }
.numlb__close:hover { background-color: var(--gold-400); color: var(--on-gold); border-color: var(--gold-400); }
.numlb__close:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }

/* Shared panel shell — white card, warm hairline, soft warm shadow. */
.numlb__panel {
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: 16px;
}
.numlb__panel-title {
  font-family: var(--font-display);
  font-weight: 600; font-size: 1.0625rem;
  color: var(--ink-700);
  margin-bottom: 12px;
}

/* ---- 1. Hero: number, price, CTAs + energy gauge ----------------- */
.numlb__hero {
  display: grid; gap: 12px;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 16px;
}
.numlb__hero-main { display: grid; gap: 10px; align-content: start; }
.numlb__tier {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 12px;
  border: 1px solid var(--gold-300);
  border-radius: var(--radius-pill);
  background-color: var(--gold-50);
  color: var(--gold-700);
  font-size: .75rem; font-weight: 500;
  justify-self: start;
}
.numlb__num-row { display: flex; align-items: center; gap: 8px; }
.numlb__num {
  font-family: var(--font-num);
  font-weight: 700; font-size: 2rem; line-height: 1.2;
  letter-spacing: .5px;
  color: var(--ink-700);
}
.numlb__fav { flex: none; }

.numlb__chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.numlb__chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 10px;
  border: 1px solid var(--line-200);
  border-radius: var(--radius-sm);
  background-color: var(--surface-panel);
  color: var(--ink-500);
  font-size: .8125rem;
}
.numlb__chip b { color: var(--ink-700); font-weight: 600; }
.numlb__chip--logo { padding: 3px 8px; background-color: #fff; }
.numlb__chip--logo img { height: 20px; width: auto; object-fit: contain; }

.numlb__note { font-size: .8125rem; color: var(--ink-400); }

/* Pulls the price up under its own label, out of the hero's 10px row gap. */
.numlb__price-label { font-size: .875rem; color: var(--ink-500); margin-bottom: -8px; }
.numlb__price {
  font-family: var(--font-num);
  font-weight: 700; font-size: 2.25rem; line-height: 1.15;
  color: var(--gold-700);
  /* background: var(--grad-gold-text);
  -webkit-background-clip: text; background-clip: text;
  color: transparent; */
}
.numlb__price-unit {
  font-size: 1rem; font-weight: 500;
  -webkit-text-fill-color: var(--ink-500); color: var(--ink-500);
}
.numlb__price.is-booked {
  background: none; color: var(--danger);
  -webkit-text-fill-color: var(--danger);
  font-size: 1.5rem;
}

/* Both CTA labels are `white-space: nowrap`, so side-by-side they demand more
   than a 360px sheet can give — stack them until there's room. */
.numlb__cta { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; }
.numlb__cta .btn { width: 100%; gap: 8px; }
.numlb__cta-buy[disabled] { opacity: .55; cursor: not-allowed; filter: saturate(.6); }
/* Lead with the gold "buy" action at every breakpoint; tel stays second
   (DOM order unchanged, reordered visually via flex/grid order). */
.numlb__cta-buy { order: -1; }

.numlb__contact { font-size: .8125rem; color: var(--ink-400); line-height: 1.7; }
.numlb__contact b { color: var(--gold-700); font-weight: 600; }
.numlb__contact a { color: var(--ink-500); }
.numlb__contact a:hover { color: var(--gold-700); text-decoration: underline; text-underline-offset: 2px; }

.numlb__views {
  display: flex; align-items: center; gap: 6px;
  font-size: .8125rem; color: var(--ink-400);
}
.numlb__views b { color: var(--ink-700); font-weight: 600; }

/* Energy gauge card — gold-framed, sits right of the hero on desktop. */
.numlb__energy {
  display: grid; justify-items: center; gap: 10px;
  padding: 16px;
  border: 1px solid var(--gold-300);
  border-radius: var(--radius-lg);
  background: linear-gradient(180deg, #FFFDF7 0%, var(--gold-50) 100%);
  text-align: center;
}
.numlb__energy-title {
  font-family: var(--font-display);
  font-weight: 600; font-size: .9375rem;
  color: var(--gold-700);
}
.numlb__gauge { width: 150px; height: 150px; }
.numlb__gauge-num {
  font-family: var(--font-num); font-size: 40px; font-weight: 700;
  fill: var(--gold-700);
}
.numlb__gauge-den { font-family: var(--font-num); font-size: 14px; fill: var(--ink-400); }
.numlb__energy-desc { font-size: .8125rem; color: var(--ink-500); line-height: 1.7; }

.numlb__grade {
  display: grid; justify-items: center; gap: 2px;
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--gold-200);
  border-radius: var(--radius-md);
  background-color: #FFFDF7;
}
.numlb__grade-label { font-size: .6875rem; color: var(--ink-400); }
.numlb__grade-value {
  font-family: var(--font-num); font-size: 1.75rem; font-weight: 700; line-height: 1.1;
  color: var(--gold-700);
}
.numlb__grade-tier { font-size: .75rem; color: var(--ink-500); }
.numlb__stars { display: inline-flex; gap: 1px; font-size: .75rem; color: var(--line-200); }
.numlb__star.is-on { color: var(--gold-400); }

/* ---- 2. Disclaimer ---------------------------------------------- */
.numlb__disclaimer {
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  padding: 14px 16px;
  font-size: .75rem; line-height: 1.8;
  color: var(--ink-400); text-align: center;
}

/* ---- 3. จุดเด่น / เหมาะสำหรับ ------------------------------------- */
.numlb__split { display: grid; gap: 12px; }

.numlb__highlights { display: grid; gap: 10px; }
.numlb__highlights li {
  display: grid; grid-template-columns: 20px 1fr; gap: 8px;
  font-size: .875rem; color: var(--ink-500); line-height: 1.7;
}
.numlb__check { width: 16px; height: 16px; margin-top: 5px; color: var(--gold-600); }

.numlb__jobs { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.numlb__job {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--line-100);
  border-radius: var(--radius-md);
  background-color: var(--surface-tile);
  font-size: .8125rem; color: var(--ink-500);
}
.numlb__job-icon {
  flex: none;
  width: 28px; height: 28px; border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background-color: var(--gold-50);
  color: var(--gold-700);
}

/* ---- 4. กราฟพลังงาน 8 ด้าน ---------------------------------------- */
.numlb__chart-title { display: flex; align-items: center; gap: 6px; }
.numlb__hint { color: var(--ink-300); display: inline-flex; }
.numlb__chart-grid { display: grid; gap: 20px; align-items: center; }

/* Radar. Labels are HTML positioned over the SVG so Thai renders in
   the page font and can wrap; the SVG itself is decorative because the
   bar list beside it carries the same numbers as text. */
.numlb__radar-wrap { position: relative; width: 100%; max-width: 340px; margin: 0 auto; aspect-ratio: 1; }
.numlb__radar { width: 100%; height: 100%; overflow: visible; }
.numlb__radar-ring { fill: none; stroke: var(--line-200); stroke-width: 1.2; }
.numlb__radar-spoke { stroke: var(--line-200); stroke-width: 1.2; }
.numlb__radar-shape { fill: url(#nmRadarFill); stroke: var(--gold-600); stroke-width: 2; }
.numlb__radar-dot { fill: var(--gold-600); }
.numlb__radar-center-label { font-family: var(--font-body); font-size: 13px; fill: var(--ink-400); }
.numlb__radar-center-num { font-family: var(--font-num); font-size: 31px; font-weight: 700; fill: var(--gold-700); }
.numlb__radar-center-den { font-family: var(--font-num); font-size: 13px; fill: var(--ink-400); }

.numlb__radar-labels { position: absolute; inset: 0; pointer-events: none; }
.numlb__radar-label {
  position: absolute; transform: translate(-50%, -50%);
  display: grid; justify-items: center; gap: 1px;
  width: 76px; text-align: center; line-height: 1.25;
}
.numlb__radar-label-icon { width: 13px; height: 13px; color: var(--gold-600); }
.numlb__radar-label-text { font-size: .6875rem; color: var(--ink-500); }
.numlb__radar-label-val { font-size: .6875rem; font-weight: 600; color: var(--gold-700); }

/* Bar list */
.numlb__bar-list { display: grid; gap: 9px; }
.numlb__bar-row {
  display: grid; align-items: center; gap: 8px;
  grid-template-columns: 24px 68px 1fr 38px;
}
.numlb__bar-icon {
  width: 24px; height: 24px; border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background-color: var(--gold-50); color: var(--gold-700);
}
.numlb__bar-label { font-size: .8125rem; color: var(--ink-500); }
.numlb__bar-track {
  height: 9px; border-radius: var(--radius-pill);
  background-color: var(--line-100);
  overflow: hidden;
}
.numlb__bar-fill {
  display: block; height: 100%;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--gold-300) 0%, var(--gold-500) 60%, var(--gold-700) 100%);
}
.numlb__bar-val { font-size: .75rem; font-weight: 600; color: var(--gold-700); text-align: right; }
.numlb__bar-axis {
  display: flex; justify-content: space-between;
  margin: 8px 38px 0 100px;
  font-size: .6875rem; color: var(--ink-300);
}

/* ---- 5. ความหมายของคู่เลข ----------------------------------------- */
.numlb__pairs {
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: 16px;
}
.numlb__pairs-title {
  font-family: var(--font-display);
  font-weight: 600; font-size: 1.125rem;
  background: var(--grad-gold-text);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.numlb__pairs-sub { font-size: .8125rem; color: var(--ink-400); margin: 4px 0 14px; }
.numlb__pair-list { display: grid; gap: 10px; }

/* Left rail colour is the classification; the tag repeats it in words so
   meaning is never carried by colour alone (DESIGN.md §11). */
/* Mobile lays the number + classification tag out as a header row; from 640px
   they move into a fixed left rail beside the copy (see the media query). */
.numlb__pair {
  display: grid; gap: 8px;
  padding: 12px;
  border: 1px solid var(--line-100);
  border-left: 4px solid var(--line-200);
  border-radius: var(--radius-md);
  background-color: var(--surface-panel);
}
.numlb__pair--good  { border-left-color: #2E7D32; background-color: #F4FBF5; }
.numlb__pair--bad   { border-left-color: var(--danger); background-color: var(--danger-bg); }
.numlb__pair--mixed { border-left-color: var(--gold-600); background-color: var(--gold-50); }

.numlb__pair-side {
  display: flex; align-items: center; gap: 10px;
}
.numlb__pair-value { font-family: var(--font-num); font-size: 2rem; font-weight: 700; line-height: 1; }
.numlb__pair--good  .numlb__pair-value { color: #2E7D32; }
.numlb__pair--bad   .numlb__pair-value { color: var(--danger); }
.numlb__pair--mixed .numlb__pair-value { color: var(--gold-700); }

.numlb__pair-tag {
  padding: 2px 8px; border-radius: var(--radius-pill);
  font-size: .625rem; white-space: nowrap; color: #fff;
}
.numlb__pair--good  .numlb__pair-tag { background-color: #2E7D32; }
.numlb__pair--bad   .numlb__pair-tag { background-color: var(--danger); }
.numlb__pair--mixed .numlb__pair-tag { background-color: var(--gold-700); }

.numlb__pair-eyebrow { font-size: .6875rem; color: var(--gold-700); }
.numlb__pair-number {
  font-family: var(--font-num); font-size: 1.125rem; font-weight: 600;
  color: var(--ink-300); letter-spacing: .5px; margin-bottom: 6px;
}
.numlb__pair-hit { color: var(--gold-700); font-weight: 700; }
.numlb__pair--good .numlb__pair-hit { color: #2E7D32; }
.numlb__pair--bad  .numlb__pair-hit { color: var(--danger); }
.numlb__pair-dash { color: var(--ink-300); }
.numlb__pair-text { font-size: .8125rem; color: var(--ink-500); line-height: 1.8; }

/* ---- 6. Credit + closing CTA ------------------------------------- */
/* Number-detail modal (number-modal.js): a single pre-composed banner
   (portrait + ตำรา credit copy baked into the image) replaces the old
   portrait-chip + gradient-text layout below, which horo-result.html's
   commented-out fallback still relies on — keep both rule sets. */
.numlb__credit {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.numlb__credit-banner { display: block; width: 100%; height: auto; }

/* Portrait of the ตำรา's author. The source is a square half-body shot, so a
   plain square-in-square crop would show the desk rather than the face —
   `object-position` can't help when both boxes share an aspect ratio. Instead
   the image is oversized inside a round window and offset so the face lands
   just above centre. Percentages are of the window, not the photo. */
.numlb__credit-portrait {
  flex: none; position: relative; overflow: hidden;
  width: 64px; height: 64px; border-radius: var(--radius-pill);
  border: 2px solid var(--gold-600);
  box-shadow: 0 0 0 4px rgba(228, 189, 95, .14);
  background-color: var(--ink-800);
}
.numlb__credit-photo {
  position: absolute;
  width: 160%; height: 160%;
  left: -1%; top: -3%;
  object-fit: cover;
}
.numlb__credit-text {
  font-family: var(--font-display);
  font-size: .9375rem; line-height: 1.7;
  background: var(--grad-gold-text);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.numlb__credit-text small { font-size: .75rem; }

.numlb__footer-cta { display: flex; justify-content: center; }
.numlb__footer-cta .btn { min-width: 260px; gap: 8px; }

/* ---- Responsive -------------------------------------------------- */
@media (min-width: 640px) {
  .numlb__dialog { padding: 24px 16px; align-items: center; }
  .numlb__scroll { border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); }
  .numlb__body { padding: 24px; gap: 16px; }
  .numlb__close { position: absolute; top: 20px; right: 20px; }
  .numlb__num { font-size: 2.5rem; }
  .numlb__price { font-size: 2.75rem; }
  .numlb__cta { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .numlb__credit-portrait { width: 84px; height: 84px; }
  .numlb__split { grid-template-columns: 1fr 1fr; }
  .numlb__pair { grid-template-columns: 88px 1fr; gap: 12px; padding: 14px 16px; }
  .numlb__pair-side { display: grid; justify-items: center; align-content: start; gap: 6px; }
  .numlb__pair-value { font-size: 2.5rem; }
}

@media (min-width: 900px) {
  .numlb__hero { grid-template-columns: minmax(0, 1fr) 300px; gap: 24px; align-items: start; }
  .numlb__hero-main { display: grid; gap: 10px; align-content: start; }
  .numlb__cta { grid-template-columns: auto auto; justify-content: start; }
  .numlb__cta .btn { width: auto; min-width: 190px; }
  .numlb__chart-grid { grid-template-columns: minmax(0, 380px) minmax(0, 1fr); gap: 28px; }
  .numlb__radar-wrap { max-width: 420px; }
  .numlb__bar-row { grid-template-columns: 26px 80px 1fr 42px; }
  .numlb__bar-axis { margin-left: 114px; }
}

@media (prefers-reduced-motion: reduce) {
  .numlb__backdrop,
  .numlb__scroll,
  .numlb__close { transition: none; }
  .numlb__scroll { transform: none; }
}

/* ------------------------------------------------------------------ *
 * Number detail as a standalone page (number.html)
 * The same .numlb__* blocks the lightbox renders, minus the sheet: no
 * scrim, no fixed dialog, no scroll container — just the content laid
 * into the page grid. This is the canonical, server-rendered target of
 * /number/<msisdn>; the lightbox is the in-page shortcut to it.
 * ------------------------------------------------------------------ */
.numlb-page { background-color: var(--bg-base); }

.numlb__body--page { padding: 0; gap: 12px; max-width: 960px; margin: 0 auto; }

/* On its own page the number is the document's h1, so it carries the
   weight the modal's h2 didn't need. */
.numlb__body--page .numlb__num { font-size: 2.25rem; }

.numlb-page__back { display: flex; justify-content: center; margin-top: 24px; }

@media (min-width: 640px) {
  .numlb__body--page { gap: 16px; }
  .numlb__body--page .numlb__num { font-size: 2.75rem; }
}

/* ------------------------------------------------------------------ *
 * Number page — order CTA banner + related-number sections (number.html)
 * The dark banner mirrors the author-credit strip so the page's two ink
 * surfaces read as one family; the card grids reuse the standard .card.
 * ------------------------------------------------------------------ */
.numlb-cta {
  position: relative; overflow: hidden;
  display: grid; gap: 16px;
  padding: 20px;
  border-radius: var(--radius-lg);
  background: linear-gradient(120deg, var(--ink-900) 0%, #1E1A12 55%, var(--ink-800) 100%);
  box-shadow: var(--shadow-card);
}
/* Decorative gold sweep in the far corner — purely visual. */
.numlb-cta::after {
  content: ""; position: absolute; right: -10%; top: -40%;
  width: 55%; height: 180%;
  background: radial-gradient(60% 50% at 70% 50%, rgba(228,189,95,.18), transparent 70%);
  transform: rotate(18deg); pointer-events: none;
}
.numlb-cta__text { position: relative; z-index: 1; }
.numlb-cta__eyebrow { font-size: .875rem; color: var(--on-ink-muted); }
.numlb-cta__number {
  font-family: var(--font-num); font-weight: 700;
  font-size: 1.75rem; line-height: 1.2; letter-spacing: .5px;
  background: var(--grad-gold-text);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.numlb-cta__actions { position: relative; z-index: 1; display: grid; gap: 10px; }
.numlb-cta__actions .btn { width: 100%; gap: 8px; }

/* Call button variant — dark on the dark banner, gold keyline + gold icon. */
.btn--ink-gold {
  background-color: rgba(255,255,255,.04);
  color: var(--on-ink);
  border: 1px solid var(--gold-700);
}
.btn--ink-gold:hover  { background-color: rgba(228,189,95,.12); border-color: var(--gold-500); transform: translateY(-1px); }
.btn--ink-gold:active { transform: translateY(0); }

/* Related-number sections — tighter top rhythm than the hero blocks above. */
.numlb-related { display: grid; gap: 12px; }
.numlb-related + .numlb-related { margin-top: 8px; }

@media (min-width: 768px) {
  .numlb-cta {
    grid-template-columns: 1fr auto; align-items: center;
    padding: 22px 28px;
  }
  .numlb-cta__number { font-size: 2.125rem; }
  .numlb-cta__actions { grid-auto-flow: column; gap: 12px; }
  .numlb-cta__actions .btn { width: auto; min-width: 200px; }
}

/* ------------------------------------------------------------------ *
 * Credit line — plain-text footnote crediting the คู่เลข 00–99 system.
 * Lighter cousin of .numlb__credit (the dark portrait banner on the
 * number detail page): no card, no background, just centered text with
 * a small seal mark. Drop wherever a page uses the pair-meaning system
 * without needing the full author banner.
 * ------------------------------------------------------------------ */
.credit-line {
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: 6px;
  text-align: center;
  font-size: .8125rem; line-height: 1.7;
  color: var(--ink-400);
}
.credit-line__icon { flex: none; width: 16px; height: 16px; color: var(--gold-600); }
.credit-line b { color: var(--ink-500); font-weight: 600; }
.credit-line__note { color: var(--ink-300); }

/* ------------------------------------------------------------------ *
 * 34. FAVORITES PAGE (favorites.html) — compact saved-number list.
 * Deliberately not the full .card (§6) grid: a favorites list is scanned
 * top-to-bottom, not compared side-by-side, so one dense row per number
 * (logo · number+price · sum/meaning · delete) beats a card's vertical
 * rhythm here. Rows reuse .card's data-* attributes so each row can still
 * open the shared number-detail lightbox (assets/js/number-modal.js).
 * ------------------------------------------------------------------ */
.fav-list {
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  overflow-x: hidden;
  overflow-y: auto;
  /* Roughly 5 rows tall (§ .fav-row height at this breakpoint) — a 6th+
     row scrolls instead of pushing the page down. */
  max-height: 290px;
  scrollbar-width: thin;
  scrollbar-color: var(--line-200) transparent;
}
.fav-list::-webkit-scrollbar { width: 6px; }
.fav-list::-webkit-scrollbar-track { background: transparent; }
.fav-list::-webkit-scrollbar-thumb { background-color: var(--line-200); border-radius: var(--radius-pill); }
.fav-list::-webkit-scrollbar-thumb:hover { background-color: var(--gold-300); }
.fav-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line-100);
  transition: background-color var(--dur-fast) var(--ease-standard),
              opacity var(--dur-base) var(--ease-standard),
              max-height var(--dur-base) var(--ease-standard),
              padding var(--dur-base) var(--ease-standard);
  max-height: 100px;
  overflow: hidden;
}
.fav-row:last-child { border-bottom: none; }
.fav-row:hover { background-color: var(--gold-50); }

/* Removal — collapse the row instead of an abrupt disappearance. */
.fav-row.is-removing {
  opacity: 0;
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  border-bottom-width: 0;
}

.fav-row__link {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  text-decoration: none;
  color: inherit;
  border-radius: var(--radius-sm);
}
.fav-row__link:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }

.fav-row__logo {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 5px;
  border-radius: var(--radius-sm);
  background-color: var(--surface-panel);
  border: 1px solid var(--line-100);
}
.fav-row__logo img { max-width: 100%; max-height: 100%; object-fit: contain; }
/* Fallback glyph — a saved number whose operator has no logo in the
   catalogue still keeps the row's rhythm instead of an empty chip. */
.fav-row__logo svg { width: 18px; height: 18px; color: var(--gold-600); }

.fav-row__body { min-width: 0; flex: 1; }
.fav-row__top { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px; }
.fav-row__number {
  font-family: var(--font-num);
  font-weight: 700;
  font-size: .9375rem;
  color: var(--ink-700);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fav-row__link:hover .fav-row__number { color: var(--gold-700); }
.fav-row__sep { color: var(--line-200); }
.fav-row__price {
  font-family: var(--font-num);
  font-weight: 700;
  font-size: .9375rem;
  color: var(--gold-700);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fav-row__price.is-booked { color: var(--danger); }
.fav-row__meta {
  margin-top: 1px;
  font-size: .75rem;
  line-height: 1.5;
  color: var(--ink-400);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fav-row__meta b { color: var(--gold-700); font-weight: 700; }

.fav-row__actions { flex: none; display: flex; align-items: center; gap: 2px; }

/* Shared icon-button box for the trailing row actions (compare, delete). */
.fav-row__action {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-pill);
  color: var(--ink-300);
  background-color: transparent;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.fav-row__action:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }

/* Compare — added to the compare tray; green means "chosen" (DESIGN.md §2),
   the same success token the product-card compare state uses (§9.2). */
.fav-row__action--compare:hover { background-color: var(--gold-50); color: var(--gold-700); }
.fav-row__action--compare.is-active { color: var(--success); background-color: var(--success-bg); }

/* Delete — removes the row; danger red only on hover/focus, never at rest. */
.fav-row__action--delete:hover { background-color: var(--danger-bg); color: var(--danger); }

@media (min-width: 640px) {
  .fav-list { max-height: 345px; }
  .fav-row { padding: 12px 16px; gap: 12px; }
  .fav-row__logo { width: 44px; height: 44px; padding: 7px; }
  .fav-row__number, .fav-row__price { font-size: 1.0625rem; }
  .fav-row__meta { font-size: .8125rem; }
}

/* "ลบทั้งหมด" (#favClearAll) asks once before it wipes the list — the
   armed state turns danger-red, and the label changes too so the warning
   isn't carried by color alone (DESIGN.md §11). */
.section-head__link.is-confirming { color: var(--danger); }

/* Empty state — no saved numbers yet. */
.fav-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 12px;
  padding: 56px 24px;
  background-color: var(--surface-panel);
  border: 1px dashed var(--line-200);
  border-radius: var(--radius-lg);
}
.fav-empty__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-pill);
  background-color: var(--gold-50);
  color: var(--gold-600);
}
.fav-empty__title { font-family: var(--font-display); font-weight: 600; font-size: 1.0625rem; color: var(--ink-700); }
.fav-empty__text { font-size: .875rem; color: var(--ink-400); max-width: 32ch; }

/* ------------------------------------------------------------------ *
 * 35. FAVORITES — COMPARE (favorites.html #compareSection).
 * Rendered by the inline script from up to 3 numbers marked with the
 * "เปรียบเทียบ" toggle (§34). Each number is ONE self-contained compact
 * card (chips, price, careers, all 8 axes, overall score) instead of
 * separate cards/bars/goals/jobs panels — the axes and the overall
 * score are fetched per number from /number/{n}/score, the same
 * NumberScoreService/NumberDimensionScoreService pair that draws the
 * radar on /horo/result, so this is that chart shown more densely.
 *
 * Mobile (<640px): a horizontal scroll-snap carousel sized so 2 cards
 * show on screen at once — swiping reveals the 3rd. Desktop/tablet: a
 * plain grid, column count driven by --cmp-cols (2 or 3), scrolling
 * turned back off. Card padding and type scale shrink on mobile so
 * two-up dense content stays legible.
 *
 * Deliberately no orange/gray/red per-slot hues (unlike the reference
 * mockups) — that would add a second/third accent beyond the system's
 * gold + neutral + green (DESIGN.md §14).
 * ------------------------------------------------------------------ */
:root { --cmp-cols: 3; }

.compare__head { text-align: center; margin-bottom: 24px; }
.compare__eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--gold-600); font-weight: 600; font-size: .8125rem;
}
.compare__eyebrow svg { color: var(--gold-400); }
.compare__title { font-family: var(--font-display); font-weight: 700; font-size: 1.5rem; color: var(--ink-700); margin-top: 4px; }
.compare__title #compareCount { color: var(--gold-700); }
.compare__sub { font-size: .875rem; color: var(--ink-400); margin-top: 4px; }
.compare__cap { color: var(--ink-300); }
.compare__hint {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 12px; padding: 6px 14px;
  border-radius: var(--radius-pill);
  background-color: var(--danger-bg); color: var(--danger);
  font-size: .8125rem; font-weight: 600;
}

.compare-body { display: grid; gap: 12px; }

/* ---- Cards / mobile 2-up carousel ----------------------------------- *
 * Mobile: horizontal scroll-snap, sized so exactly 2 cards sit in view
 * at a time — swipe to reveal the 3rd. Desktop: a plain grid, column
 * count driven by --cmp-cols, scrolling/snapping turned back off. */
.compare-cards {
  display: flex; gap: 8px;
  overflow-x: auto; scroll-snap-type: x mandatory;
  padding: 2px 2px 6px; margin: -2px -2px -6px;
  list-style: none;
  scrollbar-width: none;
  min-width: 0;
}
.compare-cards::-webkit-scrollbar { display: none; }
.compare-cards > .compare-card {
  flex: 0 0 calc(50% - 4px);
  scroll-snap-align: start;
  min-width: 0;
}
@media (min-width: 640px) {
  .compare-cards {
    display: grid; grid-template-columns: repeat(var(--cmp-cols, 3), 1fr);
    overflow: visible; padding: 0; margin: 0; gap: 14px;
  }
  .compare-cards > .compare-card { flex: unset; scroll-snap-align: none; }
}

.compare-card {
  position: relative;
  min-width: 0;
  display: flex; flex-direction: column; gap: 6px;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 10px;
  transition: transform var(--dur-base) var(--ease-standard), box-shadow var(--dur-base) var(--ease-standard);
}
.compare-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }

.compare-card__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.compare-card__remove {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border-radius: var(--radius-pill);
  color: var(--ink-300); background-color: transparent;
  transition: background-color var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.compare-card__remove:hover { background-color: var(--danger-bg); color: var(--danger); }
.compare-card__remove:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }

.compare-card__number {
  text-align: center; text-decoration: none; color: var(--ink-700);
  font-family: var(--font-num); font-weight: 700; font-size: 1rem;
  font-variant-numeric: tabular-nums;
}
.compare-card__number:hover { color: var(--gold-700); }
.compare-card__number:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-sm); }

.compare-card__chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.compare-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 9px;
  border: 1px solid var(--line-100);
  border-radius: var(--radius-pill);
  background-color: var(--surface-panel);
  font-size: .6875rem; color: var(--ink-500);
}
.compare-chip img { height: 13px; width: auto; }
.compare-chip b { color: var(--ink-700); font-weight: 700; }
.compare-chip--grade { border-color: var(--gold-300); background-color: var(--gold-50); }
.compare-chip--grade b { color: var(--gold-700); }

.compare-card__price { text-align: center; font-family: var(--font-num); font-weight: 700; font-size: 1.0625rem; color: var(--gold-700); }
.compare-card__price.is-booked { color: var(--danger); }

.compare-card__summary {
  font-size: .75rem; line-height: 1.6; color: var(--ink-400); text-align: center;
  padding-top: 6px; border-top: 1px solid var(--line-100);
}
.compare-card__summary b { color: var(--ink-500); font-weight: 700; }

/* ---- All 8 axes, embedded in the card ------------------------------ */
.compare-card__metrics { display: grid; gap: 6px; }
.cmp-metric { display: grid; gap: 3px; }
.cmp-metric__row { display: flex; align-items: center; gap: 6px; }
.cmp-metric__icon {
  flex: none; width: 18px; height: 18px;
  border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background-color: var(--gold-50); color: var(--gold-700);
}
.cmp-metric__label { flex: 1; min-width: 0; font-size: .75rem; color: var(--ink-500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmp-metric__value { flex: 0 0 auto; font-size: .75rem; color: var(--ink-700); text-align: right; }
.cmp-metric__track { height: 5px; border-radius: var(--radius-pill); background-color: var(--line-100); overflow: hidden; }
.cmp-metric__fill { display: block; height: 100%; border-radius: var(--radius-pill); background: linear-gradient(90deg, var(--gold-300) 0%, var(--gold-500) 60%, var(--gold-700) 100%); }

/* ---- Per-card loading / failed state --------------------------------
 * The 8 axes and the overall score are fetched per number from
 * /number/{n}/score — the same services /horo/result and the number
 * detail page render from — so a card can be waiting, or the request can
 * fail. A failed card says so and offers the real page: it must never
 * fall back to locally invented scores, which is exactly the bug this
 * section had when number-modal.js computed them in the browser. */
.compare-card__state {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 24px 8px;
  font-size: .75rem; line-height: 1.6; color: var(--ink-400); text-align: center;
}
.compare-card__state svg { width: 20px; height: 20px; color: var(--gold-500); }
.compare-card__state--loading svg { animation: vlb-spin 900ms linear infinite; }
.compare-card__state a { color: var(--gold-700); font-weight: 600; text-decoration: underline; }

/* ---- Footer: overall score + CTA -----------------------------------
 * Stacked (score above a full-width CTA) on the mobile 2-col grid — a
 * row layout has no room left for the nowrap "สั่งซื้อเบอร์นี้" button
 * once the card is only ~half the viewport wide. Desktop/tablet goes
 * back to the wider row layout (below, §640 block). */
.compare-card__footer {
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  margin-top: auto; padding-top: 8px;
  border-top: 1px solid var(--line-100);
}
.compare-card__power { flex: 1; min-width: 0; text-align: center; }
.compare-card__power-label { display: block; font-size: .625rem; color: var(--ink-400); }
.compare-card__power strong { font-family: var(--font-num); font-weight: 700; font-size: 1.375rem; line-height: 1; color: var(--gold-700); }
.compare-card__power strong small { font-size: .75rem; font-weight: 600; }
.compare-card__cta { flex: none; width: 100%; }

/* ---- Mobile carousel dots ------------------------------------------- */
.compare-dots { display: flex; justify-content: center; gap: 6px; margin-top: 2px; }
.compare-dots__dot {
  width: 7px; height: 7px; padding: 0; border: none;
  border-radius: var(--radius-pill);
  background-color: var(--line-200);
  transition: background-color var(--dur-fast) var(--ease-standard), width var(--dur-fast) var(--ease-standard);
}
.compare-dots__dot.is-active { background-color: var(--gold-500); width: 18px; }
.compare-dots__dot:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }
@media (min-width: 640px) {
  .compare-dots { display: none; }
}

@media (min-width: 640px) {
  .compare-card { padding: 18px; gap: 8px; }
  .compare-card__number { font-size: 1.375rem; }
  .compare-card__footer { flex-direction: row; align-items: center; gap: 10px; padding-top: 10px; }
  .compare-card__power { text-align: left; }
  .compare-card__cta { width: auto; }
}

/* ------------------------------------------------------------------ *
 * 36. VIDEO LIGHTBOX — Shorts player (global component, DESIGN.md §9.11
 * lineage). Injected once by assets/js/video-lightbox.js and reused for
 * every VDO thumbnail (index.html carousel, videos.html แนะนำ carousel
 * and the category grids). Same overlay recipe as .lightbox/.numlb:
 * near-black scrim, backdrop fade + panel scale-in, Esc/backdrop/× to
 * close, focus trap. The frame keeps the source thumbnails' 9:16 portrait
 * ratio so a Shorts clip plays true-to-format instead of pillarboxed.
 * ------------------------------------------------------------------ */
.vlb { position: fixed; inset: 0; z-index: 85; visibility: hidden; }
.vlb.is-open { visibility: visible; }

.vlb__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 8, 4, .88);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.vlb.is-open .vlb__backdrop { opacity: 1; }

.vlb__dialog {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 64px 16px;
}

.vlb__figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  max-width: min(92vw, 420px);
  opacity: 0;
  transform: scale(.96);
  transition: opacity var(--dur-slow) var(--ease-out-soft),
              transform var(--dur-slow) var(--ease-out-soft);
}
.vlb.is-open .vlb__figure { opacity: 1; transform: scale(1); }

.vlb__frame-wrap {
  position: relative;
  width: min(92vw, 420px);
  height: min(78vh, 746px);
  max-width: calc(min(78vh, 746px) * 9 / 16);
  aspect-ratio: 9 / 16;
  border-radius: var(--radius-md);
  overflow: hidden;
  background-color: var(--ink-900);
  box-shadow: var(--shadow-lg);
}

.vlb__iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-standard);
}
.vlb__frame-wrap.is-ready .vlb__iframe { opacity: 1; }

.vlb__loading {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--on-ink-muted);
  transition: opacity var(--dur-base) var(--ease-standard);
}
.vlb__frame-wrap.is-ready .vlb__loading { opacity: 0; pointer-events: none; }
.vlb__loading svg { animation: vlb-spin 900ms linear infinite; }

@keyframes vlb-spin { to { transform: rotate(360deg); } }

/* Lightbox body loading / failed states (number-modal.js fillBody) — same spin
   as the video lightbox above, just not absolutely-positioned since these
   replace .numlb__body's content outright instead of overlaying a fixed-aspect
   frame. */
.numlb__loading,
.numlb__notice {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 64px 16px;
  color: var(--on-ink-muted);
  text-align: center;
}
.numlb__loading svg { animation: vlb-spin 900ms linear infinite; }

.vlb__caption {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  max-width: 46ch;
  text-align: center;
}
.vlb__caption-title {
  color: var(--on-ink);
  font-size: .9375rem;
  font-weight: 600;
  line-height: 1.5;
}
.vlb__caption-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--gold-400);
  font-size: .8125rem;
  font-weight: 600;
  transition: color var(--dur-fast) var(--ease-standard);
}
.vlb__caption-link:hover { color: var(--gold-300); text-decoration: underline; text-underline-offset: 3px; }
.vlb__caption-link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-sm); }

.vlb__close,
.vlb__prev,
.vlb__next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-pill);
  color: var(--on-ink);
  background-color: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .28);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.vlb__close:hover,
.vlb__prev:hover,
.vlb__next:hover { background-color: var(--gold-400); color: var(--on-gold); border-color: var(--gold-400); }
.vlb__close:focus-visible,
.vlb__prev:focus-visible,
.vlb__next:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

.vlb__close { position: absolute; top: 16px; right: 16px; }

.vlb__prev,
.vlb__next { position: absolute; top: 50%; transform: translateY(-50%); }
.vlb__prev { left: 8px; }
.vlb__next { right: 8px; }

.vlb__counter {
  position: absolute;
  top: 18px;
  left: 20px;
  color: var(--on-ink-muted);
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .02em;
}

/* Lock page scroll while the video lightbox is open (JS adds this to <body>). */
body.is-vlb-open { overflow: hidden; }

/* VDO thumbnails opened by the lightbox get a hint cursor + focus ring —
   mirrors .js-lightbox-img (DESIGN.md §9.11) for the same affordance. */
.js-video-thumb { cursor: pointer; }
.js-video-thumb:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

@media (min-width: 640px) {
  .vlb__close { top: 20px; right: 20px; }
  .vlb__prev { left: 20px; }
  .vlb__next { right: 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .vlb__backdrop,
  .vlb__figure,
  .vlb__iframe,
  .vlb__loading,
  .vlb__close,
  .vlb__prev,
  .vlb__next { transition: none; }
  .vlb__loading svg,
  .numlb__loading svg,
  .compare-card__state--loading svg { animation: none; }
}

/* ------------------------------------------------------------------ *
 * 37. FAVORITE ALERT — "บันทึกเบอร์แล้ว" confirmation (global component).
 * Injected once by assets/js/app.js and shown whenever a heart
 * ([data-fav-toggle]) saves or removes a number, then it closes itself
 * after 3s (click or Esc closes it sooner).
 *
 * Same overlay recipe as .lightbox/.numlb (§30/§36) — backdrop fade +
 * card scale-in — with three deliberate differences, because this is a
 * transient confirmation rather than a viewer: a much lighter scrim so
 * the catalogue stays visible behind it, no scroll lock, and no focus
 * trap/focus move, so focus stays on the heart the user just pressed
 * and nothing is stolen while the alert fades back out. It sits above
 * .numlb (z-index 90) since the number-detail lightbox has a heart too.
 * ------------------------------------------------------------------ */
.fav-alert { position: fixed; inset: 0; z-index: 95; visibility: hidden; }
.fav-alert.is-open { visibility: visible; }

.fav-alert__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 8, 4, .45);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-standard);
}
.fav-alert.is-open .fav-alert__backdrop { opacity: 1; }

.fav-alert__dialog {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.fav-alert__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  width: min(100%, 288px);
  padding: 28px 24px;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transform: scale(.94);
  transition: opacity var(--dur-base) var(--ease-out-soft),
              transform var(--dur-base) var(--ease-out-soft);
}
.fav-alert.is-open .fav-alert__card { opacity: 1; transform: scale(1); }

/* Saved — the gold filled heart the card's own button just became, so the
   alert reads as the same action rather than a generic success toast.
   Removed (--removed) keeps the outline heart in muted ink instead: the
   two states differ by fill and wording, not by color alone (§11). */
.fav-alert__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-pill);
  background-color: var(--gold-50);
  color: var(--favorite);
}
.fav-alert__icon svg { width: 28px; height: 28px; fill: currentColor; }
.fav-alert--removed .fav-alert__icon { background-color: var(--surface-panel); color: var(--ink-300); }
.fav-alert--removed .fav-alert__icon svg { fill: none; stroke: currentColor; stroke-width: 1.6; }

.fav-alert__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.0625rem;
  color: var(--ink-700);
}
.fav-alert__number {
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 1.125rem;
  color: var(--gold-700);
  font-variant-numeric: tabular-nums;
}
.fav-alert__note { font-size: .8125rem; color: var(--ink-400); }
/* The "removed" variant drops the note, and a number is only shown when the
   heart knew one — neither should leave a gap behind. */
.fav-alert__number:empty,
.fav-alert__note:empty { display: none; }

@media (prefers-reduced-motion: reduce) {
  .fav-alert__backdrop,
  .fav-alert__card { transition: none; }
}

/* ------------------------------------------------------------------ *
 * 38. COOKIE CONSENT (PDPA) — banner + preferences modal.
 *
 * Feature spec: .claude/COOKIE_CONSENT.md §11.5.
 * All values come from the DESIGN.md tokens in :root above — no new colors,
 * radii or shadows are introduced here. Gold stays the "spice": the panel is
 * warm cream with a gold hairline, and only the accept CTA carries gradient
 * gold (.btn--gold from §5).
 *
 * z-index sits above every existing overlay because a consent dialog must
 * never end up behind content. Current stack: bottom-nav / back-to-top z-50,
 * .drawer + .sheet 60, .lightbox 80, .numlb 90, .fav-alert 95,
 * then .cookie-banner 100 and .cookie-modal 110.
 * ------------------------------------------------------------------ */

/* The `hidden` attribute is how JS and Blade toggle both of these, but
   `[hidden]{display:none}` lives in the UA stylesheet — so ANY author
   `display` rule (e.g. .cookie-modal's `display:flex`) outranks it and the
   element stays visible. These guards restore `hidden` as the authority.
   Keep them whenever a `display` is added to either block. */
.cookie-banner[hidden],
.cookie-modal[hidden] { display: none !important; }

.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  z-index: 100;
  padding: 0 .75rem;
  /* The theme reserves the bottom strip for the mobile bottom-nav (pb-20 on
     body), so lift the banner clear of it on small screens. */
  padding-bottom: calc(.75rem + env(safe-area-inset-bottom, 0px));
}

.cookie-banner--bottom { bottom: 5rem; }
.cookie-banner--top    { top: .75rem; }

.cookie-banner--center {
  top: 50%;
  bottom: auto;
  transform: translateY(-50%);
}

@media (min-width: 1024px) {
  /* No bottom-nav on desktop — sit closer to the edge. */
  .cookie-banner--bottom { bottom: 1.5rem; }
  .cookie-banner { padding: 0 1.5rem; }
}

.cookie-banner__inner {
  max-width: var(--container-max, 1280px);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.25rem;
  background-color: var(--surface-card);
  border: 1px solid var(--line-200);
  /* Gold keyline along the top edge — the "foil" cue, not a gold fill. */
  border-top: 2px solid var(--gold-400);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
}

@media (min-width: 768px) {
  .cookie-banner__inner {
    flex-direction: row;
    align-items: center;
    gap: 1.5rem;
    padding: 1.25rem 1.5rem;
  }
}

.cookie-banner__body { flex: 1 1 auto; min-width: 0; }

.cookie-banner__title {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.0625rem;
  line-height: 1.35;
  color: var(--ink-700);
  margin: 0 0 .375rem;
}

.cookie-banner__icon {
  width: 22px;
  height: 22px;
  flex: 0 0 auto;
  color: var(--gold-700);
}

.cookie-banner__text {
  font-size: .875rem;
  line-height: 1.6;
  color: var(--ink-500);
  margin: 0;
}

.cookie-banner__policy-link,
.cookie-modal__policy-link {
  color: var(--gold-700);
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 500;
}
.cookie-banner__policy-link:hover,
.cookie-modal__policy-link:hover { color: var(--gold-800); }

.cookie-banner__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .625rem;
  flex: 0 0 auto;
}

/* Both CTAs share the row on mobile so neither reads as the only option. */
.cookie-banner__btn { flex: 1 1 auto; min-width: 8.5rem; }

@media (min-width: 768px) {
  .cookie-banner__btn { flex: 0 0 auto; }
}

/* "ตั้งค่าคุกกี้" is a quieter third action — text + icon, no fill. */
.cookie-banner__customize {
  background-color: transparent;
  color: var(--gold-700);
  border: 1px solid transparent;
  order: 3;
  width: 100%;
}
.cookie-banner__customize:hover {
  background-color: var(--gold-50);
  border-color: var(--line-200);
}
.cookie-banner__customize svg { width: 16px; height: 16px; }

@media (min-width: 768px) {
  .cookie-banner__customize { order: 0; width: auto; }
}

/* Dark theme variant — gold on ink, per DESIGN.md §3.2 "dark for authority". */
.cookie-banner--dark .cookie-banner__inner {
  background-color: var(--ink-800);
  border-color: var(--gold-800);
  border-top-color: var(--gold-400);
}
.cookie-banner--dark .cookie-banner__title { color: var(--on-ink); }
.cookie-banner--dark .cookie-banner__text  { color: var(--on-ink-muted); }
.cookie-banner--dark .cookie-banner__policy-link { color: var(--gold-300); }
.cookie-banner--dark .cookie-banner__customize   { color: var(--gold-300); }
.cookie-banner--dark .cookie-banner__customize:hover {
  background-color: rgba(228, 189, 95, .12);
  border-color: var(--gold-800);
}
.cookie-banner--dark .btn--outline {
  background-color: transparent;
  color: var(--gold-300);
  border-color: var(--gold-500);
}
.cookie-banner--dark .btn--outline:hover { background-color: rgba(228, 189, 95, .12); }

/* ---- Preferences modal ------------------------------------------- */

.cookie-modal {
  position: fixed;
  inset: 0;
  z-index: 110;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.cookie-modal__overlay {
  position: absolute;
  inset: 0;
  background-color: rgba(20, 20, 20, .55);
  backdrop-filter: blur(2px);
}

body.cookie-modal-open { overflow: hidden; }

.cookie-modal__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 34rem;
  max-height: calc(100vh - 2rem);
  background-color: var(--bg-base);
  border: 1px solid var(--line-200);
  border-top: 3px solid var(--gold-400);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.cookie-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.125rem 1.25rem;
  border-bottom: 1px solid var(--line-100);
}

.cookie-modal__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.125rem;
  color: var(--ink-700);
  margin: 0;
}

.cookie-modal__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  border-radius: var(--radius-pill);
  color: var(--ink-400);
  background-color: transparent;
  cursor: pointer;
  transition: background-color var(--dur-base) var(--ease-standard),
              color var(--dur-base) var(--ease-standard);
}
.cookie-modal__close:hover { background-color: var(--gold-50); color: var(--gold-700); }
.cookie-modal__close svg { width: 18px; height: 18px; }

.cookie-modal__scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 1.25rem;
}

.cookie-modal__intro {
  font-size: .875rem;
  line-height: 1.6;
  color: var(--ink-500);
  margin: 0 0 1.25rem;
}

.cookie-modal__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .75rem;
}

.cookie-item {
  padding: 1rem;
  background-color: var(--surface-card);
  border: 1px solid var(--line-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}

.cookie-item__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.cookie-item__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: .9375rem;
  color: var(--ink-700);
}

.cookie-item__desc {
  font-size: .8125rem;
  line-height: 1.55;
  color: var(--ink-400);
  margin: .5rem 0 0;
}

/* Required categories get a locked chip instead of an inert switch. */
.cookie-item__locked {
  display: inline-flex;
  align-items: center;
  gap: .3125rem;
  flex: 0 0 auto;
  padding: .3125rem .625rem;
  font-size: .75rem;
  font-weight: 500;
  color: var(--gold-700);
  background-color: var(--gold-50);
  border: 1px solid var(--line-200);
  border-radius: var(--radius-pill);
}
.cookie-item__locked svg { width: 13px; height: 13px; }

/* ---- Switch ------------------------------------------------------- *
 * The "on" state is gold (the brand's active state — same as the §9.5
 * number chips), never a second accent hue. State is carried by knob
 * position AND the adjacent เปิด/ปิด label, not by color alone.
 * ------------------------------------------------------------------- */

.cookie-switch {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  flex: 0 0 auto;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.cookie-switch__track {
  position: relative;
  display: block;
  width: 46px;
  height: 26px;
  border-radius: var(--radius-pill);
  background-color: #E7E2D6;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .12);
  transition: background-color var(--dur-base) var(--ease-standard),
              background-image var(--dur-base) var(--ease-standard);
}

.cookie-switch__knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: var(--radius-pill);
  background-color: var(--surface-card);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-out-soft);
}

.cookie-switch[aria-checked="true"] .cookie-switch__track {
  background-image: var(--grad-gold);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5),
              inset 0 -1px 0 var(--gold-800);
}
.cookie-switch[aria-checked="true"] .cookie-switch__knob { transform: translateX(20px); }

.cookie-switch__state {
  font-size: .75rem;
  font-weight: 500;
  color: var(--ink-400);
  min-width: 1.75rem;
}
.cookie-switch[aria-checked="true"] .cookie-switch__state { color: var(--gold-700); }

.cookie-modal__footer {
  flex: 0 0 auto;
  padding: 1rem 1.25rem;
  border-top: 1px solid var(--line-100);
  background-color: var(--surface-panel);
}

.cookie-modal__error {
  margin: 0 0 .75rem;
  padding: .625rem .75rem;
  font-size: .8125rem;
  color: var(--danger);
  background-color: var(--danger-bg);
  border-radius: var(--radius-sm);
}

.cookie-modal__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .625rem;
}
.cookie-modal__btn { flex: 1 1 10rem; }

/* Footer "ตั้งค่าคุกกี้" trigger — matches .footer__link exactly so it reads
   as one of the list's links despite being a <button>. */
.footer__link-button {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* Disabled while a save is in flight (§7.2). */
.cookie-banner__btn:disabled,
.cookie-modal__btn:disabled,
.cookie-banner__customize:disabled { opacity: .6; cursor: progress; }

/* Focus rings — the theme's standard 3px gold outline. */
.cookie-switch:focus-visible,
.cookie-modal__close:focus-visible,
.footer__link-button:focus-visible,
.cookie-banner__customize:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

@media (prefers-reduced-motion: reduce) {
  .cookie-switch__track,
  .cookie-switch__knob,
  .cookie-modal__close { transition: none; }
}
