/* theme4 overrides — โหลดหลัง style.css ของต้นแบบเสมอ
 *
 * ไฟล์นี้มีไว้แก้เฉพาะจุดที่ "asset ของเราสัดส่วนไม่เท่าต้นแบบ" เท่านั้น
 * เจตนา: คง geometry ของต้นแบบไว้เป๊ะ แต่ให้รูปจาก API แสดงได้โดยไม่ถูก crop
 * ห้ามแก้ style.css ที่ mirror มา — จะได้ diff กับต้นแบบได้ตลอด
 */

/* ── โลโก้ header ──────────────────────────────────────────────────────────
 * ต้นแบบ: โลโก้ 639×627 (เกือบจัตุรัส) + `width:120px` → สูง 117.7px → .header สูง 139.7px
 * ของเรา: โลโก้จาก API 1040×461 (แนวนอน) → สูงแค่ 53.2px → header เตี้ยลง 64.5px
 * แก้: ล็อกกล่องโลโก้ให้สูงเท่าต้นแบบ แล้ว contain รูปไว้ข้างใน (ไม่ crop ไม่ยืด)
 */
.header .logo {
  /* อัตราส่วนไฟล์โลโก้ต้นแบบจริง (639×627) — ให้ browser คำนวณสูงเอง
     จะได้ตรงกับต้นแบบเป๊ะ ไม่ต้องฝังเลขปัดเศษ */
  aspect-ratio: 639 / 627;
  height: auto;
  object-fit: contain;
  object-position: center;
}

/* ── โลโก้กลาง bottom nav ──────────────────────────────────────────────────
 * ต้นแบบใช้ inline style width:90px + position:absolute; top:-10px
 * รูปแนวนอนจะเตี้ยกว่าเดิมมาก ทำให้หลุดตำแหน่งเดิม — ล็อกความสูงให้เท่ากรอบเดิม
 */
.menuListNavBottom li a img[style*="position: absolute"] {
  height: 60px;
  object-fit: contain;
  object-position: center;
}

/* ── โลโก้ค่ายเกมใน rail ───────────────────────────────────────────────────
 * ต้นแบบ: โลโก้ค่ายเกือบจัตุรัส → สูง ~59.5px ต่อช่อง
 * ของเรา: รูปค่ายจาก API เป็นภาพแนวนอน → สูงแค่ ~21.5px จังหวะ rail เลยผิดไป
 * แก้: ล็อกอัตราส่วนช่องให้เท่าต้นแบบ แล้ว contain รูปไว้ (ไม่ crop โลโก้ค่าย)
 */
.partnerSlider .linkPartner img {
  /* ต้นแบบวัดได้ 59.5px พอดี (โลโก้ค่ายเกือบจัตุรัสที่กว้าง 60px) */
  height: 59.5px;
  object-fit: contain;
  object-position: center;
}

/* ── hamburger scroll ──────────────────────────────────────────────────────
 * ต้นแบบมีเมนู hamburger แค่ 6 ปุ่ม → พอดีจอ · ของเราดึงจาก getMenu.hamburger 17 ปุ่ม
 * → ล้นจอแต่ `.side-menu` เป็น overflow:visible เลย scroll ไม่ได้
 * แก้: ให้ header กับปุ่ม logout ค้างไว้ ส่วน .menu-options ตรงกลาง scroll เอง
 * (min-height:0 จำเป็นให้ flex child หดแล้ว scroll ได้)
 */
.side-menu {
  overflow: hidden; /* กัน bounce ของทั้ง panel — ให้ scroll เฉพาะข้างใน */
}
.side-menu .side-menu-header,
.side-menu .language-selector,
.side-menu .btn-logout {
  flex: 0 0 auto;
}
.side-menu .menu-options {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  margin: 0 -6px; /* กันสกอลบาร์เบียดไอคอน */
  padding: 0 6px;
  scrollbar-width: thin;
  scrollbar-color: gold transparent;
}
.side-menu .menu-options::-webkit-scrollbar {
  width: 6px;
}
.side-menu .menu-options::-webkit-scrollbar-thumb {
  background-color: gold;
  border-radius: 10px;
}

/* title ยาว (เช่น "รางวัลรายชั่วโมง") ไม่ให้ box สูงกว่าตัวอื่น:
 * ล็อกความสูงทุกช่องเท่ากัน + clamp เฉพาะ "ข้อความ" ไว้ 2 บรรทัด (ตัว flex ยังเป็น icon+text) */
.side-menu .menu-options > [class*="col-"] {
  display: flex;
}
.side-menu .menu-item {
  width: 100%;
  min-height: 86px; /* min-height (ไม่ใช่ height) → ป้ายยาวขยาย tile ได้ ไม่โดนตัด */
  justify-content: center;
  gap: 4px;
}
.side-menu .menu-item .menu-icon {
  flex: 0 0 auto;
}
.side-menu .menu-item-label {
  /* display:block (ไม่ใช่ -webkit-box) — ใน -webkit-box ตัว text-align:center ไม่มีผล
     ทำให้ป้ายหลายบรรทัดชิดซ้าย · block + width100% + text-align:center → กึ่งกลางทุกบรรทัด
     ไม่ clamp/ไม่ตัด → เห็นข้อความครบทุกบรรทัด (เช่น "รางวัลรายชั่วโมง" = 3 บรรทัด) */
  display: block;
  width: 100%;
  font-size: 0.78rem;
  line-height: 1.15;
  text-align: center;
  overflow-wrap: anywhere;
}

/* ── ป้ายเมนู grid หน้าหลัก (.menuDashboard .btnMenu) ──────────────────────────
 * .btnMenu เป็น flex + justify-content:center → จัด "กล่อง" span ให้กลาง
 * แต่ span ไม่มี text-align → ป้ายที่ห่อหลายบรรทัด (เช่น "รางวัลรายชั่วโมง")
 * บรรทัดในกล่องยังชิดซ้าย · เติม text-align:center + width100% → ทุกบรรทัดกึ่งกลาง */
/* ── หน้า account ทุก viewport ให้ดูเต็ม/สวย (ดีกว่าต้นฉบับที่แค่วางคอลัมน์มือถือกลางจอ) ──
 * ต้นฉบับ media ≤480 ซ้อนใน @media อื่น (CSS ซ้อนไม่ถูก) เลยตาย → tile สูงตาม content ไม่คุม
 * คุมเองใหม่ 2 breakpoint: mobile กระชับ · desktop ขยายคอลัมน์ + tile ใหญ่จัตุรัส
 *
 * ≥768: ขยายคอลัมน์เนื้อหา (header/balance/menu/lobby/bottomnav) จาก col-md-6 (~360-660px)
 *       → สูงสุด 840px จัดกลาง → เต็มจอขึ้น ไม่โล่งสองข้าง · tile กว้าง ~133px */
@media (min-width: 768px) {
  .acctWide {
    flex: 0 0 auto;
    width: 94%;
    max-width: 840px;
  }
  .menuDashboard .btnMenu {
    height: 120px; /* จัตุรัสกับ tile กว้าง ~133px */
    padding-top: 64px;
    padding-bottom: 10px;
  }
  .menuDashboard .btnMenu img {
    width: 64px;
    height: 64px;
  }
  .menuDashboard .btnMenu span {
    display: block;
    width: 100%;
    text-align: center;
    font-size: 0.9rem;
    line-height: 1.12;
  }
}
/* mobile (<768) — tile กว้าง ~52px → กระชับ ป้ายกึ่งกลาง */
@media (max-width: 767.98px) {
  .menuDashboard .btnMenu {
    height: 78px;
    padding-top: 42px;
    padding-bottom: 5px;
  }
  .menuDashboard .btnMenu img {
    width: 38px;
    height: 38px;
  }
  .menuDashboard .btnMenu span {
    display: block;
    width: 100%;
    text-align: center;
    font-size: 0.68rem;
    line-height: 1.08;
  }
}

/* ── Tab (.tabAff) ให้เข้าธีมทอง ────────────────────────────────
   style.css เดิม (mirror) ใช้ var(--Linear, ม่วง) เป็น fallback — เพราะ theme var --Linear
   ยังไม่ถูกตั้ง (ระบบ getColor พักไว้) → tab เลยออกม่วง. override เป็นทองให้เข้าธีม
   (เฉพาะ .tabAff เท่านั้น ไม่กระทบทั้งเว็บ). */
.tabAff {
  border-bottom: 3px solid #ffbd0c;
}
.tabAff .nav-link {
  color: #f4d488;
  background: rgba(16, 21, 42, 0.35) !important;
}
.tabAff .nav-link.active,
.tabAff .nav-item.show .nav-link {
  color: var(--gold-ink, #fff);
  background: var(--Linear) !important;
}

/* ── §1 reconcile: จุดธีมหลัก → token (ธีมทั้งเว็บสลับตาม data-theme) ── */
/* 🔴 หัวเว็บ · แถบล่าง · ลิ้นชัก · แถบชวนติดตั้ง = **โครงหน้า** ⇒ ใช้หมวด CHROME ชุดเดียวกัน
      (นิยาม token + เหตุผลเต็มอยู่ที่ theme-tokens.css ชั้น 2 หัวข้อ "หมวด CHROME")
      เดิมสามตัวแรกอ้าง `--Linear` ตรง ๆ ซึ่งเป็นตัวเดียวกับปุ่ม/แท็บทั้งเว็บ ⇒ ธีมไหนอยากได้
      หัวเว็บคนละสีกับปุ่ม (เช่น c18 หัวเว็บดำ ปุ่มทอง) ทำไม่ได้เลย
      ค่าตั้งต้นของ --chrome-grad = --Linear เป๊ะ ⇒ ธีมเดิมทุกตัวเรนเดอร์เหมือนเดิมทุกพิกเซล
   🔴 โมดัล/ป๊อปอัพ **ไม่ใช่โครงหน้า** (เป็นพื้นผิวลอย) ห้ามย้ายมาหมวดนี้ */
/* หัวเว็บ (แถบทอง) */
.header {
  background: var(--chrome-grad) !important;
  border-bottom-color: var(--edge) !important;
}
/* bottom nav — ทั้งแถบใช้สี CHROME สีเดียว (แถบนอก .fixedMenu เดิมเป็นทอง → ขอบทองโผล่รอบพื้นเขียว)
   ให้ .fixedMenu เป็น --chrome-grad + .bottomMenu โปร่ง (ไม่ทาซ้อน = ไม่มีขอบชนสี) */
.fixedMenu {
  background: var(--chrome-grad) !important;
}
/* ลิ้นชักเมนู (hamburger) — เดิม `background-color: var(--gold)` (style.css:1945)
   ซึ่งบังเอิญเท่ากับ --prim2 ใน maruay เท่านั้น ⇒ ธีมอื่นลิ้นชักหลุดไปอยู่ครอบครัวทอง
   คนละพวกกับหัวเว็บ · ย้ายมา --chrome-bg (= --prim2) ⇒ maruay ได้ #ffbd0c เท่าเดิมเป๊ะ
   ส่วนธีมอื่นลิ้นชักตามหัวเว็บไปเอง */
.side-menu {
  background-color: var(--chrome-bg);
}
.fixedMenu .bottomMenu,
.menuListNavBottom {
  background: transparent;
}
/* ระยะเผื่อท้ายหน้าให้พ้นแถบเมนูล่าง (fixed)
   วัดจริงบนมือถือ 390px: กล่อง .fixedMenu สูง 99px + โลโก้ตรงกลางยื่นขึ้นไปอีก 10px (top:-10)
   = สูงจริง 109px → เผื่อ 130px (109 + ที่หายใจ ~20) + safe-area ของ iPhone (home bar)

   ⚠️ ต้องใช้ `padding-bottom` ไม่ใช่ `margin-bottom` — ของต้นแบบตั้ง `.mgMenuBottom{margin-bottom:90px}`
   ซึ่ง **ไม่เคยทำงานเลย** เพราะ margin ท้าย body ถูก collapse ทิ้ง ไม่ขยายพื้นที่ scroll
   (วัดจริง: เลื่อนสุดแล้วเนื้อหาจบที่ขอบล่าง viewport พอดี = ไม่มีระยะเผื่อ) → เกมแถวล่างโดนแถบทับ
   padding ไม่ collapse จึงได้ระยะจริง (วัดหลังแก้: เหลือช่องว่าง +29px) */
body.mgMenuBottom {
  margin-bottom: 0;
  padding-bottom: calc(130px + env(safe-area-inset-bottom, 0px));
}
/* /theme-studio = หน้าเครื่องมือแอดมิน ไม่มี BottomNav (`<BottomNav/>` mount แค่ที่
   src/app/account/layout.tsx) และไม่มี footer (SiteFooter คืน null ที่พาธนี้) ⇒ ระยะเผื่อ 130px
   ข้างบนกลายเป็นพื้นที่ดำท้ายหน้าที่เลื่อนได้เปล่าๆ ทับกับแผงสตูดิโอที่สูง 100vh พอดีอยู่แล้ว
   ตัดทิ้งเฉพาะหน้านี้ด้วย `:has([data-studio-root])` — เกาะ marker ที่ทั้งแผงจริง (StudioApp.tsx)
   และ splash ตอนโหลด (page.tsx) มีเหมือนกัน
   🔴 ห้ามแก้ด้วยการ toggle class บน <body> ตอน runtime — className นั้น React ถือครองจาก
      layout.tsx (ดู CLAUDE.md §ห้ามลบ/ยุ่งกับ DOM node ที่ React ถือครอง) CSS ล้วนจึงปลอดภัยกว่า */
body.mgMenuBottom:has([data-studio-root]) {
  padding-bottom: 0;
}
/* พื้นหลังเว็บ (ไล่เฉดจาก bg1→bg2) — วางใต้ wallpaper */
body {
  background: var(--page-grad) fixed;
}
/* เงาเรืองแสง (glow) ของการ์ด/ปุ่ม */
.promotion img,
.cardNormal,
.btn-main {
  box-shadow: 0 0 14px 0 var(--glow);
}

/* ════════ §1b แสงเรืองของธีมสำเร็จรูป (2026-08-29) ════════
   เจ้าของงานทัก: "ทำไมสี preset เราได้มาไม่ฟุ้ง ๆ เหมือนตัว html ที่เอามาอะ"
   ต้นเหตุ: ไฟล์ธีมต้นฉบับทุกใบใช้ `radial-gradient(circle at 50% -10%, …)` เป็นพื้นของหน้า
   ⇒ ความฟุ้งมาจาก **เลเยอร์เรืองแสง** ไม่ได้มาจากค่าสี · ของเรามี radial-gradient 0 จุด

   🔴 **ทุกกฎในส่วนนี้ต้องกัน `maruay` ออก** — repo นี้ต่างจาก theme2 ตรงที่ `<html>` **มี
      `data-theme` เสมอ** (layout.tsx: `themeDataAttr(ssrTheme) ?? "maruay"`) ⇒ "ธีม default"
      ของที่นี่คือ `data-theme="maruay"` ซึ่งเป็นเว็บที่โคลนมาจากลูกค้า ห้ามขยับสักพิกเซล
      เขียน `html[data-theme] …` เฉย ๆ แบบ theme2 = โดน maruay เต็ม ๆ

   ⚠️ ข้อ B1 ของสเปก (แก้ fallback ของ --glow ให้ตกกลับเป็นสีธีมแทนสีขาว) **ข้าม** — ที่นี่
      ไม่มีชั้น `--glow-color` เลย โค้ดอ้าง `var(--glow)` ตรง ๆ และพรีเซตทั้ง 27 บล็อก
      ตั้ง `--glow` เองครบทุกตัว (`:root` ก็ตั้ง) ⇒ ไม่มี fallback สีขาวให้แก้ */

/* B2 · ชั้นแสงเรืองจากขอบบนของหน้า
   🔴 ห้ามยัดลงใน `background` shorthand ของ body — var() ซ้อนหลายชั้นใน shorthand หลายเลเยอร์
      ทำให้ทั้ง declaration invalid ⇒ พื้นหลังหายเกลี้ยง (เคยพังมาแล้วใน theme2)
      body ที่นี่ถือ `background: var(--page-grad) fixed` อยู่แล้ว ⇒ ยิ่งห้ามไปแตะ
   ✅ `body::before` และ `body::after` ว่างทั้งคู่ในโปรเจกต์นี้ (ตรวจแล้วทั้ง style.css /
      theme4-overrides.css / bootstrap / inline-account) — ภาพพื้นหลังของ studio ไปอยู่ที่
      `<div class="fixed-background">` ไม่ใช่ pseudo (ดู src/lib/server/wallpaper.ts)
   🔴 `z-index: -99` ไม่ใช่ `0` แบบสเปก — theme4 มี `.fixed-background` (position:fixed,
      z-index:-100) เป็นเลเยอร์พื้นหลังจริงอยู่แล้ว และ header/เนื้อหาส่วนใหญ่ **ไม่ได้ positioned**
      ⇒ ถ้าใช้ z-index:0 ชั้นนี้จะลอยทับหัวเว็บ/เนื้อหาแล้วซีดทั้งหน้า
      -99 = เหนือรูปพื้นหลัง (-100) แต่ยังอยู่ใต้เนื้อหาทุกชิ้น ตรงกับไฟล์ธีมต้นฉบับที่แสงฟุ้ง
      เป็น "พื้นของหน้า" ไม่ใช่ฟิล์มคลุมหน้า
   🔴 `pointer-events: none` ห้ามลืม (ชั้นนี้กินคลิกทั้งหน้าได้) */
html[data-theme]:not([data-theme="maruay"]) body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -99;
  pointer-events: none;
  background-image: radial-gradient(
    ellipse 120% 55% at 50% -10%,
    var(--glow),
    transparent 60%
  );
  opacity: 0.5;
}

/* B3 · เงาเรืองใต้แท็บที่ "กำลังเลือก" (ไฟล์ธีมต้นฉบับใส่ `box-shadow: 0 2px 10px -3px var(--g)`)
   ⚠️ ต้องพก inset เดิมของ `.nav-link` มาด้วย — box-shadow แทนที่ทั้งค่า ไม่ได้บวกเพิ่ม
      ทิ้งไว้จะเสียเงาในของแท็บที่ต้นแบบตั้งไว้
   specificity ที่นี่ = (0,5,1) ชนะ `.nav-tabs .nav-link.active` เดิม (0,3,0) ของ style.css
   หมายเหตุ: `.menuListNavBottom li a.active` ของต้นแบบไม่มีใครเซ็ตในโค้ดเรา (แถบล่างไม่มี
   สถานะ active) จึงไม่ใส่ selector ตายไว้ · ปุ่มสมัคร/ล็อกอินได้เงานี้ในก้อน C */
html[data-theme]:not([data-theme="maruay"]) .nav-tabs .nav-link.active,
html[data-theme]:not([data-theme="maruay"]) .nav-tabs .nav-item.show .nav-link {
  box-shadow:
    0 -6px 3px 0 rgba(16, 21, 42, 0.19) inset,
    0 2px 12px -4px var(--glow);
}

/* ════════ §1c ปุ่มสมัครสมาชิก / เข้าสู่ระบบ (2026-08-29) ════════
   ไฟล์ธีมต้นฉบับให้ปุ่มสมัคร (CTA เด่นสุด) เป็น "ชุดทอง 3 เฉด" ส่วนปุ่มล็อกอินเป็นสีหลักของธีม
   ของเดิมสลับกัน + ปุ่มสมัครยังผูกกับ `--danger` (สีสถานะคงที่) ⇒ เปลี่ยนจานสี 27 ครั้ง
   ปุ่มสมัครก็ยังแดงเท่าเดิมทุกครั้ง · นิยาม token + ค่า pin ของ maruay อยู่ที่ theme-tokens.css

   🔴 **ทำเป็น token ไม่ใช่ `:not([data-theme="maruay"])`** ต่างจาก §1b ด้านบนโดยตั้งใจ:
      ถ้ากันด้วย :not() กฎจะได้ specificity (0,3,1) ซึ่ง
        ก) ทับ `.btn-signup:hover` (0,2,0) ของ style.css ⇒ เงาตอน hover หายไป
        ข) สูงกว่ากฎเฉพาะธีมของ c18 (`html[data-theme="c18"] .btn-signup` = 0,2,1)
           ⇒ ปุ่มขอบทองของ c18 จะไม่ติด
      เขียนเป็น `.btn-signup` เปล่า ๆ (0,1,0) ในไฟล์ที่โหลดท้ายสุด = ชนะ style.css ที่ specificity
      เท่ากันด้วยลำดับไฟล์ แต่ยังแพ้ทั้ง `:hover` และกฎรายธีมตามที่ควรเป็น

   ⚠️ `.btn-login` ถูกใช้กับปุ่ม "ติดต่อเรา" ในหน้า login/register ด้วย (คลาสเดียวกัน อยู่แถวเดียวกัน
      กับปุ่มล็อกอินในหัวเว็บ) ⇒ มันเปลี่ยนสีตามไปด้วยโดยตั้งใจ ให้ทั้งแถวเป็นภาษาเดียวกัน
      ส่วน `id="btn-login"` ที่ปุ่มส่งฟอร์มหน้า login เป็น **id ไม่ใช่คลาส** กฎนี้ไม่โดน */
.btn-signup {
  background: var(--btn-reg-bg);
  color: var(--btn-reg-ink);
  border-color: var(--btn-reg-edge);
  box-shadow: var(--btn-auth-glow);
}
.btn-login {
  background: var(--btn-login-bg);
  color: var(--btn-login-ink);
  border-color: var(--btn-login-edge);
  box-shadow: var(--btn-auth-glow);
}
/* hover — ต้นฉบับใช้ `filter: brightness()` ไล่ความสว่างขึ้นทั้งปุ่ม (ได้ผลกับทั้งไล่เฉดทองและ
   ไล่เฉดสีหลัก โดยไม่ต้องคิดสี hover แยกต่อธีม) · maruay ตั้ง token เป็น `none` = ไม่ขยับ
   🔴 ประกาศแค่ `filter` เท่านั้น — เงาขาว `box-shadow` ตอน hover ของ style.css:1815/1831
      เป็นคนละ property จึงยังทำงานคู่กันได้ครบทุกธีม (เขียนทับทั้งกฎจะลบเงานั้นทิ้ง) */
.btn-signup:hover,
.btn-login:hover {
  filter: var(--btn-auth-hover-filter);
}

/* ════════ §1d ธีม c18 "ดำ & ทอง (แนว luxkywin)" — กฎเฉพาะธีมนี้ธีมเดียว ════════
   🔴 ทุกกฎในส่วนนี้ขึ้นต้นด้วย `html[data-theme="c18"]` **ห้ามผ่อนเป็น html[data-theme]**
      — 25 ธีมที่เหลือเจ้าของงานดูและอนุมัติไปแล้ว เปลี่ยนหมดจะกลายเป็นคนละหน้าตากับที่ตกลงกัน
   ที่ต้องมีกฎเฉพาะเพราะธีมนี้ตัวเดียวที่ **สีหลัก = ทองอ่อน (#fffe97)** ไม่ใช่สีเข้ม/สด
   ⇒ ของที่นั่งบนสีหลักด้วยตัวอักษรสว่างจะอ่านไม่ออกหมด (ที่อื่นสีหลักเข้มพอเลยไม่มีปัญหา)
   นิยาม token (--chrome-* ดำ + hover 1.25) อยู่ที่ theme-tokens.css ชั้น 3 ท้ายไฟล์ */

/* D2 · ปุ่มสมัคร/ล็อกอิน = "ไส้ดำ ขอบไล่ทอง" ตามเว็บอ้างอิง
   🔴 background-clip ต้องเป็น **padding-box** ไม่ใช่ content-box — ต้นฉบับ luxkywin ใช้
      content-box ได้เพราะปุ่มเขา padding น้อย แต่ปุ่มเรามี padding ซ้าย-ขวา (5px 10px / 5px 20px)
      content-box จะครอปไส้ดำเหลือแค่ช่วงตัวอักษร ทองโผล่เป็นแถบหนารอบ ๆ และเพราะข้อความ
      2 ปุ่มยาวไม่เท่ากัน มันจะดู "ได้ทองไม่เหมือนกัน" ทั้งที่ CSS ชุดเดียวกัน
   🔴 กฎนี้ specificity (0,2,1) สูงกว่า `.btn-signup` ของ §1c (0,1,0) ⇒ ชนะแน่นอนไม่ว่าลำดับไหน
      แต่ยังต่ำกว่า `.btn-signup:hover` (0,2,0)+ลำดับไฟล์ ซึ่งประกาศแค่ box-shadow/filter ⇒ ไม่ชนกัน
   หมายเหตุ: §1c ตั้ง background ด้วย shorthand ⇒ background-color ถูกรีเซ็ตเป็น transparent
      อยู่แล้ว ที่นี่จึงเขียนเฉพาะ background-image/origin/clip พอ ไม่ต้องล้างสีพื้นซ้ำ */
html[data-theme="c18"] .btn-signup,
html[data-theme="c18"] .btn-login {
  border: 2px solid transparent;
  background-image: linear-gradient(var(--surf), #101010), linear-gradient(var(--gold-hi), #151515);
  background-origin: border-box, border-box;
  background-clip: padding-box, border-box;
  color: var(--txt);
}

/* D1 · ตัวอักษรบน "สีหลัก/ทอง" ต้องเป็นหมึกเข้ม
   theme2 แก้จุดนี้ที่ token กลาง --primary-foreground ตัวเดียว แต่ **ที่นี่ไม่มี token นั้น** —
   ของที่นั่งบนสีหลักอ้าง `color` ที่สืบทอดมาจาก body (= var(--main-color) = var(--prim))
   หรือ var(--txt) ตรง ๆ ⇒ ธีมนี้จะได้ "ทองอ่อนบนทองอ่อน" กับ "ขาวบนทองอ่อน" = หายไปเลย
   ⇒ ไล่ทีละชิ้นแทน · เกณฑ์คัด: พื้นเป็น --Linear (prim→prim2) หรือไล่เฉดทอง **และมีตัวอักษร**
     .grad_color01/02 (style.css:241/246) · .btn-danger2/3 (158/168) · .btn-ok (1425)
     .btn-main (140 — ไล่เฉด gold-lo→gold-hi ปุ่มที่ใช้เยอะสุดในเว็บ) · .btn-reward/2 (1118/1133)
     .bankSelect__opt.is-active (ไฟล์นี้ §BankSelect)
   ⚠️ `:not(.disable)` ที่ .btn-reward — สถานะ disable ตั้ง `color: var(--surf)` ไว้เองที่ (0,2,0)
      กฎนี้ (0,3,1) จะทับทิ้งถ้าไม่กัน แล้วปุ่มที่กดไม่ได้จะดูเหมือนกดได้
   🔴 หมึกที่ใช้คือ --gold-ink ซึ่ง repo นี้นิยามไว้แล้วว่า "ตัวอักษรบนปุ่มทอง" — ไม่ประดิษฐ์สีใหม่ */
html[data-theme="c18"] .grad_color01,
html[data-theme="c18"] .grad_color02,
html[data-theme="c18"] .btn-danger2,
html[data-theme="c18"] .btn-danger3,
html[data-theme="c18"] .btn-ok,
html[data-theme="c18"] .btn-main,
html[data-theme="c18"] .btn-reward:not(.disable),
html[data-theme="c18"] .btn-reward2:not(.disable),
html[data-theme="c18"] .bankSelect__opt.is-active {
  color: var(--gold-ink);
}

/* D1 (ต่อ) · แถบชวนติดตั้ง PWA — พื้นเป็น --chrome-grad ซึ่งธีมนี้ถูก override เป็น **ดำ**
   แต่ข้อความในแถบตั้งไว้เป็น var(--gold-ink) (หมึกเข้ม เพราะธีมอื่นแถบนี้เป็นสีหลักสว่าง)
   ⇒ ธีมนี้จะได้ดำบนดำ · ปุ่ม .pwa-cta ไม่ต้องแก้ (พื้น --gold-ink ตัวอักษร --gold = ยังตัดกันดี) */
html[data-theme="c18"] .pwa-install-banner .pwa-x,
html[data-theme="c18"] .pwa-install-banner .pwa-text {
  color: var(--txt);
}

/* ════════ D4 · ไทล์เมนู + แถบ sidebar = "ไส้ดำ ขอบไล่ทอง" (2026-08-29 รอบ 2) ════════
   เจ้าของงานทัก: "พวกที่เป็น sidebar หรือ ปุ่ม มันไม่ควรเป็นสีดำตาม nav หรอ มันดูหลุดจากธีมไหม"

   วัดเทียบธีมในโปรเจกต์เดียวกันก่อนลงมือ (dev server จริง):
     maruay (ต้นฉบับ) · c6 · c17 → หัวเว็บทอง · แถบล่างทอง · ไทล์ทอง = เข้าชุดกัน
     c18                          → หัวเว็บดำ  · แถบล่างดำ  · ไทล์ทอง = ลอยอยู่ธีมเดียว
   ⇒ ไทล์ทอง **ไม่ใช่การแมพผิด** ธีมต้นฉบับก็ทอง · ต้นเหตุคืองานของเราเอง: c18 เป็นธีมเดียว
     ที่ override โครงหน้าให้เป็นดำ (ชั้น 3 ใน theme-tokens.css) แต่ไทล์กับ sidebar ไม่ได้
     ตามไปด้วย ⇒ ของที่เคยเข้าชุดกันขาดออกจากกันเฉพาะธีมนี้

   ซ้ำอีกชั้น: --gold ของ c18 (#e8da9b) **สว่างที่สุดในตระกูล** (relative luminance 0.849
   เทียบ 0.746-0.793 ของธีมอื่น) ซีดจนอ่านเป็น "ครีม/กระดาษ" ไม่ใช่ "ทองโลหะ" — พอถมเป็น
   พื้นกว้างทั้งหน้าจึงดูเป็นเบจ · และเว็บอ้างอิง luxkywinv2.pro **ไม่เคยถมทองเป็นพื้นกว้างเลย**
   ทองโผล่เฉพาะ ขอบ / เมนูที่เลือก / หัวข้อ เท่านั้น

   ⇒ ใช้สูตรเดียวกับปุ่ม auth ใน D2 เป๊ะ (ไส้ --surf→#101010 · ขอบไล่ --gold-hi→#151515)
     ไม่ประดิษฐ์สูตรใหม่ ทั้งหน้าจะได้พูดภาษาเดียวกัน
   🔴 background-clip ต้องเป็น **padding-box** ไม่ใช่ content-box ด้วยเหตุผลเดียวกับ D2 —
      ไทล์พวกนี้ padding หนากว่าปุ่ม auth อีก (.btnMenu = 57px 0 8px) content-box จะครอปไส้ดำ
      เหลือแค่ช่วงตัวอักษร แล้วทองจะโผล่เป็นแถบหนารอบ ๆ
   🔴 ทุกกฎในก้อนนี้ต้องขึ้นต้น `html[data-theme="c18"]` **ห้ามผ่อนเป็น html[data-theme]** —
      อีก 26 ธีม (maruay + g1-g8 + c1-c17) ไทล์ทองเข้าชุดกับโครงหน้าทองอยู่แล้ว ถูกต้องแล้ว
      (tests/theme-c18-scope.test.mjs เฝ้ากฎข้อนี้ไว้ให้ ไม่ต้องพึ่งคอมเมนต์อย่างเดียว)
   ⚠️ bootstrap ตั้ง `box-sizing: border-box` ให้ทุก element ⇒ ขอบ 2px กินเข้าข้างใน
      ไม่ดันกล่องให้ใหญ่ขึ้น (ไทล์มือถือที่ล็อก height: 82px ไว้ก็ยังสูงเท่าเดิมเป๊ะ) */

/* ไทล์เมนู 9 ช่อง (โปรโมชั่น/รับทรัพย์/คืนยอดเสีย/แลกพ้อยต์/…/ออกจากระบบ) + ไทล์หมวดเกมในล็อบบี้
   โค้ดเราเรียก `.btnMenu btnMenu08` ตัวเดียวทุกจุด (AuthedAccount / GuestAccount / GameLobby)
   — `.btnMenu01`-`.btnMenu07` ของต้นแบบไม่มีใครเรียกเลยสักที่ จึงไม่เขียนกฎเผื่อไว้ให้ตายเปล่า
   ⚠️ style.css:624 ตั้งพื้นด้วย shorthand `background:` ⇒ background-color ถูกรีเซ็ตเป็น
      transparent ให้แล้ว ที่นี่จึงเขียนแค่ background-image/origin/clip เหมือน D2
   🔴 specificity (0,2,1) สูงกว่าทั้ง `.btnMenu08` (0,1,0) และ `.btnMenu08:hover` (0,2,0)
      ⇒ ขอบทอง 1px ตอน hover (style.css:632) ไม่กลับมาแทนที่ขอบไล่เฉด
      ส่วน `.btnMenu:hover` (ตัวอักษร→--main-color + เงาลึกขึ้น + ไอคอนเด้งขึ้น 10px) เป็นคนละ
      property ทั้งหมด ⇒ ยังทำงานครบ ไม่ต้องประดิษฐ์ hover ใหม่ให้ธีมนี้
   ⚠️ `.btnMenu08::after` ถูกตั้งเป็น transparent อยู่แล้ว (style.css:628) ไม่มีฟิล์มทองทับ
      ส่วน `.btnMenu::before` เป็น gradient โปร่งทั้งเส้น (mix-blend-mode: overlay) = ไม่มีผล */
html[data-theme="c18"] .btnMenu08 {
  border: 2px solid transparent;
  background-image: linear-gradient(var(--surf), #101010), linear-gradient(var(--gold-hi), #151515);
  background-origin: border-box, border-box;
  background-clip: padding-box, border-box;
}

/* แถบ sidebar ค่ายเกมด้านซ้าย (.slidePartner) — style.css:1597 ถมทองเต็มแถบสูง 600px
   = ก้อนทองใหญ่ที่สุดในหน้า · และแถบตั้ง `color: var(--secondary-color)` (= --sub เทาอ่อน
   #c9c9c9) ⇒ เดิมเป็นเทาอ่อนบนทองซีด แทบอ่านไม่ออก — ไส้ดำแก้ทั้งสองเรื่องพร้อมกัน
   แถบนี้ position:absolute + max-width:80px + height:600px ตายตัว ⇒ ขนาดนอกเท่าเดิมเป๊ะ */
html[data-theme="c18"] .slidePartner {
  border: 2px solid transparent;
  background-image: linear-gradient(var(--surf), #101010), linear-gradient(var(--gold-hi), #151515);
  background-origin: border-box, border-box;
  background-clip: padding-box, border-box;
}

/* โลโก้ค่ายในแถบ — 🔴 style.css:1522 ฝังคีย์เวิร์ด `gold` (#ffd700) ไว้ตาย ไม่ผูกกับธีมเลย
   ทุกธีมได้เหลืองสดดวงเดียวกันหมด · บนแถบที่กลายเป็นดำแล้ว #ffd700 กระโดดออกจากจานสีชัดสุด
   เว็บอ้างอิงให้ "เมนูที่เลือก" เป็นทองได้อยู่แล้ว ⇒ คงพฤติกรรมเดิมไว้ เปลี่ยนแค่ให้เป็นทองของธีม
   🔴 แก้ **เฉพาะ c18** ตามกติกางาน — อีก 26 ธีมห้ามขยับ ค่าตายตัวนั้นจึงยังอยู่ที่เดิมสำหรับธีมอื่น
   ⚠️ ต้องเกาะ `.partSlide` ไม่ใช่ `.linkPartner` — สองคลาสนี้อยู่บน element เดียวกัน (ดู
      GameLobby.tsx / CategoryBrowse.tsx) และ `.partSlide:hover` (style.css:1521) อยู่ล่างกว่า
      `.linkPartner:hover` (1512) ที่ specificity เท่ากัน ⇒ ตัวที่ชนะจริงคือ .partSlide */
html[data-theme="c18"] .partSlide:hover {
  background: var(--gold);
}

/* สกอลบาร์ของแถบค่าย — style.css:1620/1626 ฝัง var(--info) (น้ำเงิน, Firefox) กับ `gold`
   (#ffd700, WebKit) ไว้ตาย บนแถบที่เป็นดำแล้วหลุดจากธีมทั้งคู่ ⇒ ดึงกลับมาเป็นชุดทองของธีม
   ใช้ --gold-lo (เข้มสุดในชุด) เพื่อไม่ให้สกอลบาร์แย่งสายตาไปจากโลโก้ค่าย */
html[data-theme="c18"] .partnerSlider {
  scrollbar-color: var(--gold-lo) transparent;
}
html[data-theme="c18"] .partnerSlider::-webkit-scrollbar-thumb {
  background-color: var(--gold-lo);
}

/* ป้าย "ประกาศ" มุมขวาบนแถบข่าววิ่ง — style.css:1784 พื้น var(--gold) + ตัวอักษร white
   ธีมนี้ทองซีด (#e8da9b) กับขาว contrast ~1.3:1 = อ่านแทบไม่ออก และเป็นแผ่นทองแปะบนแถบดำ
   ⇒ พลิกเป็น "ไส้เข้ม ตัวอักษรทอง" ตามภาษาเว็บอ้างอิง (ทองอยู่ที่หัวข้อ/ขอบ ไม่ใช่พื้น)
   ใช้ --surf (#303030) ไม่ใช่ --bg2 (#000) เพราะ `.announcement-bar` พื้นเป็น --ink (#0a0a12)
   ดำบนดำจะไม่เหลือรูปป้าย · ขอบทองบางเฉพาะ 2 ด้านที่ป้ายมีขอบจริง (ป้ายชิด right:0/top:0
   และโค้งแค่มุมซ้ายล่าง) ⇒ อ่านเป็นป้ายชัดขึ้นโดยไม่ตีกรอบด้านที่ไม่มีอยู่
   ⚠️ ไม่แตะ border-top/bottom ของ `.announcement-bar` เอง (style.css:1756 ฝัง `gold` ไว้ตาย
      เหมือนกัน) — เส้น 2px บนพื้น --ink คือ "ขอบทอง" ซึ่งตรงกับภาษาเว็บอ้างอิงอยู่แล้ว
      ไม่ใช่พื้นที่กว้าง จึงไม่เข้าข่ายอาการที่เจ้าของงานทัก */
html[data-theme="c18"] .announcement-label {
  background-color: var(--surf);
  color: var(--gold);
  border-left: 1px solid var(--edge);
  border-bottom: 1px solid var(--edge);
}

/* ลิ้นชักเมนู (hamburger) — ตัวลิ้นชักเป็นดำแล้วตั้งแต่ §1 (--chrome-bg) แต่ไทล์เมนูข้างในยังเป็น
   `background-color: var(--gold-lo)` ทึบ + `border: 2px solid var(--gold)` (style.css:2009)
   ⇒ แผงทอง 2 คอลัมน์เรียงเต็มลิ้นชักดำ · นี่คือ "sidebar" ตรงตัวที่เจ้าของงานทัก
   🔴 ต้องเกาะ `.side-menu` ด้วย = (0,3,1) เพื่อชนะ `.menu-options .menu-item` (0,2,0) ให้ขาด
   🔴 ที่นี่ **ต้องล้าง background-color เอง** ต่างจาก .btnMenu08/.slidePartner ข้างบน —
      กฎต้นทางใช้ `background-color:` เดี่ยว ๆ ไม่ใช่ shorthand ⇒ ไม่มีอะไรมารีเซ็ตให้
   ⚠️ `.menu-item:hover { background-color: var(--info) }` (0,2,0) เป็น background-**color**
      ซึ่งถูกวาดอยู่ "ใต้" background-image ทึบของเรา ⇒ hover จะไม่เห็นอะไรเปลี่ยนเลย
      ต้องคืน feedback ด้วย filter แบบเดียวกับปุ่ม auth ของธีมนี้ (--btn-auth-hover-filter)
      ✅ `.menu-item` เป็น <a> ที่มีแค่ img + span ไม่มี LinkPending/ลูก absolute
         (Hamburger.tsx) ⇒ containing block ใหม่ที่ filter สร้างขึ้นไม่กระทบใคร */
html[data-theme="c18"] .side-menu .menu-item {
  border: 2px solid transparent;
  background-color: transparent;
  background-image: linear-gradient(var(--surf), #101010), linear-gradient(var(--gold-hi), #151515);
  background-origin: border-box, border-box;
  background-clip: padding-box, border-box;
}
html[data-theme="c18"] .side-menu .menu-item:hover {
  filter: var(--btn-auth-hover-filter);
}

/* ════════ D5 · พิลล์ยอดเงินในหัวเว็บ (2026-08-29 รอบ 3) ════════
   หัวเว็บของ c18 เป็นดำไปแล้ว (§1 → --chrome-grad) แต่ `.balance-box` (style.css:2046) ยังถม
   `linear-gradient(90deg, var(--gold-lo), var(--gold-lo))` = ทองทึบเฉดเดียว + ขอบ --gold +
   `box-shadow: 0 0 10px var(--gold)` ⇒ เป็นก้อนทองก้อนเดียวที่เหลือบนแถบดำ

   🔴 ไม่ใช่แค่เรื่องสวยงาม — `.balance-amount` มีคลาส `text-white` ของ bootstrap (มี
      `!important`) ⇒ ขาวบน #b38c2c = **3.1:1** ตกเกณฑ์ 4.5:1 (ตัวเลข 16px bold ยังไม่นับเป็น
      large text ซึ่งต้อง 18.66px ขึ้นไป) และเป็น "ยอดเงิน" = ตัวเลขที่คนดูบ่อยที่สุดในเว็บ
   🔴 แก้ที่ **พื้น** ไม่ใช่ที่ตัวอักษร — `text-white` เป็น !important ของ bootstrap
      เขียน `color:` ทับต้องใช้ !important ตาม ซึ่งไม่จำเป็นเลยถ้าพลิกพื้นเป็นไส้ดำ
      ขาวบน --surf→#101010 = 13.2:1 ถึง 19.0:1 ผ่านสบาย ๆ โดยไม่ต้องแตะ DOM หรือชน !important

   ใช้สูตรเดียวกับ D2/D4 เป๊ะ (ไส้ --surf→#101010 · ขอบไล่ --gold-hi→#151515)
   ⚠️ style.css ตั้งพื้นด้วย shorthand `background:` ⇒ background-color ถูกรีเซ็ตเป็น transparent
      ให้แล้ว เขียนแค่ background-image/origin/clip พอ (เหมือน .btnMenu08)
   ⚠️ ขอบ 1px → 2px ⇒ พิลล์โตขึ้น 2px ทั้งกว้างและสูง (ไม่มี width/height ตายตัว box-sizing
      จึงไม่ช่วย) — ไม่กระทบเลย์เอาต์เพราะความสูง `.header` ถูกกำหนดโดยกล่องโลโก้ 117.7px
      (ดูหัวไฟล์ §โลโก้ header) ซึ่งสูงกว่าพิลล์ ~32px อยู่มาก
   🔴 เงา: ลดจาก `var(--gold)` ทึบ → `var(--gold-glow)` (rgba .5 — token ที่ repo นี้ตั้งไว้
      สำหรับ "เงาเรือง" โดยเฉพาะ) เพราะเงา #e8da9b ทึบ 10px รอบพิลล์ที่กลายเป็นไส้ดำแล้ว
      จะสว่างกว่าตัวขอบทองของมันเอง = กลับหัวลำดับสายตา (วงแสงเด่นกว่าของที่มันล้อม) */
html[data-theme="c18"] .balance-box {
  border: 2px solid transparent;
  background-image: linear-gradient(var(--surf), #101010), linear-gradient(var(--gold-hi), #151515);
  background-origin: border-box, border-box;
  background-clip: padding-box, border-box;
  box-shadow: 0 0 10px var(--gold-glow);
}

/* ════════ D6 · ช่องที่เลือก/hover บนแถบเมนูล่าง ════════
   style.css:704 ตั้ง `background-color: var(--gold-hi); color: var(--main-color)`

   🔴 **ตั้งใจไม่พลิกพื้นเป็นไส้ดำ** ต่างจาก D4 — เว็บอ้างอิง luxkywinv2.pro ให้ทองโผล่ที่
      "ขอบ / **เมนูที่เลือก** / หัวข้อ" ⇒ ช่องเมนูที่ถูกเลือกเป็นทองเต็มช่อง **คือภาษาของเว็บนั้น
      อยู่แล้ว** ไม่ใช่อาการที่เจ้าของงานทัก (ที่ทักคือทองที่ถมเป็นพื้น *ตลอดเวลา* เช่นไทล์/แถบ
      sidebar ซึ่งเป็นทองทั้งที่ไม่ได้ถูกเลือก) · และถ้าพลิกช่องที่เลือกเป็นดำด้วย แถบล่างจะไม่มี
      สถานะ "เลือกอยู่" ให้เห็นเลยสักแบบ เพราะทั้งแถบเป็นดำหมดแล้ว

   ของที่พังจริงคือ **ตัวอักษร**: --main-color = var(--prim) ซึ่ง c18 คือ #fffe97 (ทองอ่อน)
   บนพื้น --gold-hi #ffe29b ⇒ **1.2:1** = มองไม่เห็นตัวหนังสือเลย (ธีมอื่นไม่เป็นเพราะ --prim
   เป็นสีเข้ม/สด — เหตุผลเดียวกับหัวข้อ D1 ข้างบน)
   ⇒ ใช้ --gold-ink เหมือน D1 ทุกประการ ได้ 12.8:1
   🔴 specificity ต้อง (0,3,3) — กฎต้นทางเป็น `.menuListNavBottom li a:hover` = (0,2,2)
      ซึ่ง **สูงกว่า** ก้อน D1 ข้างบน (0,2,1) ⇒ เอาไปต่อท้ายลิสต์ D1 เฉย ๆ ไม่ติด ต้องแยกกฎ
   หมายเหตุ: `.active` ยังไม่มีใครเซ็ตในโค้ดเรา (BottomNav.tsx ไม่ใส่ — ดู §1b B3) แต่เขียน
      คู่ไว้ให้ตรงกฎต้นทางที่ประกาศสองตัวพร้อมกัน วันหลังเปิดใช้จะได้ไม่พังเงียบ ๆ */
html[data-theme="c18"] .menuListNavBottom li a:hover,
html[data-theme="c18"] .menuListNavBottom li a.active {
  color: var(--gold-ink);
}

/* ════════ D7 · การ์ดเนื้อหา = พื้นผิวการ์ด (--surf) ไม่ใช่แผงทอง ════════
   4 ตัวนี้คือทองแผงกว้างที่เหลือทั้งหมดหลัง D4 — และเป็นแผงที่ **กว้างที่สุดในเว็บ**
     .cardBlock     (style.css:786)  ไล่ทอง 3 จุด · ใช้ 54 จุดใน 23 ไฟล์ = การ์ดหลักของทั้งโซนสมาชิก
     .cardNormal    (style.css:1272) ไล่ทองชุดเดียวกัน + ขอบ --gold-lo
     .cardColorDark (style.css:949)  --gold-lo ทึบ (ชื่อว่า Dark แต่ธีมนี้ #b38c2c ไม่ดำเลย)
     .custom-card   (style.css:2072) ไล่ --gold-lo→--gold = แผงยอดเงินหัวหน้า /account

   🔴 **ทำไมถึงแตะ ทั้งที่สเปกจัด "การ์ด" เป็นคนละหมวดกับโครงหน้า**
   ก) สเปกจัดคนละหมวด = ห้ามลาก **โครงหน้า** ไปใช้สีการ์ด (และกลับกัน) — ไม่ได้แปลว่าการ์ด
      ต้องเป็นทอง · สเปกฉบับเดียวกันเรียกพื้นการ์ดว่า `--surf` ตรง ๆ ("วัด contrast ระหว่าง
      --chrome-bg (พื้น footer) กับ --surf (พื้นการ์ด)") ⇒ token ของการ์ดในระบบนี้คือ --surf
      อยู่แล้ว ที่ style.css เรียกทองเพราะตอนโคลนต้นแบบ `--gold` กับ `--prim2` ของ maruay
      **ตั้งค่าเท่ากันเป๊ะ (#ffbd0c)** — ตรงกับที่สเปกเขียนไว้เองว่า "หยิบ token ที่สีตรงกัน
      ไม่ใช่ token ที่ความหมายตรงกัน" ⇒ นี่คือการจัดหมวดผิดแบบเดียวกับลิ้นชักใน §1
   ข) c18 ปรับ --surf (#303030) ให้ห่างจาก --bg1 (#141414) ชัด ๆ **เพราะเรื่องนี้โดยเฉพาะ** —
      สเปกจดไว้ว่ารอบแรกตั้ง #292929/#2a2a2a แล้ว "พื้นหน้ากับการ์ดกลืนเป็นเทาแบนก้อนเดียว
      เจ้าของงานทักทันที" ⇒ ค่านี้ถูกจูนมาเพื่อเป็นพื้นการ์ดของธีมนี้อยู่แล้ว ไม่ได้ประดิษฐ์ใหม่
   ค) contrast ของเดิมพังจริง ไม่ใช่เรื่องรสนิยม (บนพื้น --gold #e8da9b):
        h2/h5/h6 ที่สืบทอด body color (#fffe97) → **1.3:1**
        `.color-secondary` (--sub #c9c9c9)      → **1.3:1**
        `.text-white` ใน .custom-card           → **1.4:1**
      หลังแก้บน --surf: 12.5:1 / 8.0:1 / 13.2:1
   ง) หลัง D4 การ์ดพวกนี้เป็นทองแผงเดียวที่เหลือทั้งหน้า — ปล่อยไว้ = ไทล์ดำล้อมด้วยการ์ดครีม
      ซึ่งอ่านเป็น "แก้ไม่เสร็จ" มากกว่าตอนยังไม่แก้อะไรเลย

   🔴 ยัง **เฉพาะ c18** เท่านั้น — 26 ธีมที่เหลือโครงหน้าเป็นทอง การ์ดทองจึงเข้าชุดถูกแล้ว
      และ maruay = เว็บที่โคลนมา ห้ามขยับสักพิกเซล
   ✅ ของที่จงใจไม่แตะ (ทองที่อยู่ที่ "ขอบ/หัวข้อ" = ตรงภาษาเว็บอ้างอิงแล้ว):
        `.cardBlock::before` เส้นทอง --gold-hi 3px หัวการ์ด · ขอบ --gold-lo ของ .cardNormal
        และ .custom-card · `.custom-card::after` (คลื่นตกแต่งโปร่ง ไม่ใช่ทอง) */
html[data-theme="c18"] .cardBlock,
html[data-theme="c18"] .cardNormal,
html[data-theme="c18"] .custom-card {
  background: var(--surf);
}
/* .cardColorDark วางซ้อนใต้ .cardBlock ในหน้าเดียวกัน (deposit) ⇒ ถ้าให้พื้นเท่ากันเฉย ๆ
   สองการ์ดจะกลืนเป็นก้อนเดียว · .cardBlock มีเส้นทองหัวการ์ด (::before) เป็นตัวแยกอยู่แล้ว
   ตัวนี้จึงแยกด้วย "เส้นขอบ" แทน — ใช้ --edge (#917232) ซึ่งเป็น token ของขอบโดยตรง
   🔴 ไม่ใช้ --bg2 (#000) แม้ชื่อคลาสจะว่า Dark: พื้นหน้าไล่ลงไปจบที่ --bg2 อยู่แล้ว
      (--page-grad) ⇒ ท้ายหน้ายาว ๆ การ์ดจะหายไปกับพื้น */
html[data-theme="c18"] .cardColorDark {
  background: var(--surf);
  border: 1px solid var(--edge);
}
/* ผลพวงที่ต้องเก็บพร้อมกัน: `.text-muted` ของ bootstrap คือ rgba(33,37,41,.75) = หมึกเข้ม
   ที่ออกแบบมาสำหรับพื้นสว่าง · เดิมมันนั่งบนการ์ดทอง (ยังพออ่านได้ ~5.5:1) พอการ์ดเป็น --surf
   จะเหลือ **1.2:1 = หายไปเลย** ⇒ ต้องพลิกเป็นหมึกอ่อนพร้อมกันในคอมมิตเดียว ไม่งั้นเราแก้ที
   เดียวพังอีกที่ (ใช้ 11 จุด ส่วนใหญ่อยู่ในโฟลว์ฝากเงินซึ่งอยู่ใน .cardBlock ทั้งหมด)
   🔴 ต้องมี `!important` เพราะกฎต้นทางของ bootstrap เป็น !important — specificity (0,2,1)
      ของเราสูงกว่า (0,1,0) ของเขา ⇒ ชนะในชั้น !important ด้วยกันเอง
   ⚠️ ผูกกับธีมไม่ใช่กับการ์ด: c18 พื้นดำทั้งหน้าอยู่แล้ว หมึกเข้มจึงผิดทุกที่ในธีมนี้ */
html[data-theme="c18"] .text-muted {
  color: var(--sub) !important;
}

/* ════════ D8 · ทองที่ยังฝังคีย์เวิร์ด `gold` (#ffd700) ไว้ตาย ════════
   สองจุดสุดท้ายที่ไม่ผูกกับธีมเลย — ทุกธีมได้เหลืองสด #ffd700 ดวงเดียวกันหมด
   เรื่องเดียวกับที่ D4 เก็บไปแล้วที่ `.partSlide:hover` / `.partnerSlider` เป๊ะ ๆ
   🔴 คงพฤติกรรม "เป็นทอง" ไว้ตามเดิม เปลี่ยนแค่ให้เป็น **ทองของธีม** — สองจุดนี้เป็น
      "เส้น/ขอบ" ตรงภาษาเว็บอ้างอิงอยู่แล้ว ไม่ใช่พื้นกว้าง จึงไม่พลิกเป็นไส้ดำ
   🔴 แก้เฉพาะ c18 ตามกติกางาน — อีก 26 ธีมค่าตายตัวยังอยู่ที่เดิม */

/* เส้นบน/ล่างของแถบข่าววิ่ง (style.css:1756) — พื้นแถบเป็น --ink (#0a0a12 คงที่ทุกธีม)
   เส้น #ffd700 บนพื้นเกือบดำจึงกระโดดออกจากจานสีของ c18 ชัดที่สุด */
html[data-theme="c18"] .announcement-bar {
  border-top-color: var(--gold);
  border-bottom-color: var(--gold);
}

/* สกอลบาร์ของลิ้นชัก hamburger — จุดนี้เป็นโค้ด**ของเราเอง** (หัวไฟล์ §hamburger scroll)
   ที่เผลอฝัง `gold` ไว้ตอนยังไม่มีระบบธีม · ลิ้นชักเป็นดำแล้ว (§1 --chrome-bg) และไทล์ข้างใน
   เป็นไส้ดำแล้ว (D4) เหลือสกอลบาร์เป็นเหลืองสดอยู่ชิ้นเดียว
   ใช้ --gold-lo (เข้มสุดในชุด) ให้ตรงกับที่ D4 เลือกใช้กับสกอลบาร์ `.partnerSlider` */
html[data-theme="c18"] .side-menu .menu-options {
  scrollbar-color: var(--gold-lo) transparent;
}
html[data-theme="c18"] .side-menu .menu-options::-webkit-scrollbar-thumb {
  background-color: var(--gold-lo);
}

/* ════════ §4 PWA install banner + layout push (ticket 005) ════════ */
/* §4 banner = บล็อกในเลย์เอาต์ปกติบนสุด (ไม่ fixed → ไม่บัง header · ปิดแล้ว unmount คืนพื้นที่เอง)
   render ก่อน children ใน providers → อยู่เหนือ header เสมอ */
.pwa-install-banner {
  position: relative;
  width: 100%;
  height: 64px;
  display: none;                     /* desktop ซ่อน */
  align-items: center;
  gap: 10px;
  padding: 0 12px;
  /* โครงหน้า ⇒ หมวด CHROME (ดู §1) — ค่าตั้งต้นเท่า --Linear เดิมเป๊ะ */
  background: var(--chrome-grad);
  border-bottom: 1px solid var(--edge);
  box-shadow: 0 2px 12px 0 var(--glow);
}
@media (max-width: 767.98px) { .pwa-install-banner { display: flex; } }

.pwa-install-banner .pwa-x {
  flex: 0 0 auto; cursor: pointer;
  /* พื้นที่กด ≥40px (เดิม glyph เล็ก 13×22 → มือถือจิ้มพลาด) + reset ปุ่ม */
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; margin-left: -6px;
  border: 0; background: transparent; padding: 0;
  font-size: 26px; line-height: 1;
  color: var(--gold-ink); opacity: .85;
  -webkit-tap-highlight-color: transparent;
}
.pwa-install-banner .pwa-x:active { opacity: .5; }
.pwa-install-banner .pwa-appicon {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  border-radius: 9px; object-fit: cover;
  background: #fff2;
}
.pwa-install-banner .pwa-text {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; line-height: 1.15;
  color: var(--gold-ink);
}
.pwa-install-banner .pwa-title {
  font-weight: 700; font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pwa-install-banner .pwa-sub {
  font-size: 11px; opacity: .85;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pwa-install-banner .pwa-cta {
  flex: 0 0 auto; cursor: pointer; border: 0;
  padding: 7px 16px; border-radius: 20px;
  background: var(--gold-ink); color: var(--gold);
  font-weight: 700; font-size: 13px; white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}

/* ── BankSelect (หน้า register) ────────────────────────────────────────────
 * custom dropdown แทน native <select> เพื่อโชว์โลโก้ธนาคาร (field img จาก /bank/list)
 * trigger ยังใช้ class .form-select → ได้กรอบ/มุมโค้ง/caret + floating label ตรงต้นแบบ
 */
.bankSelect { position: relative; }
.bankSelect__trigger {
  display: flex; align-items: center; gap: 8px;
  width: 100%; text-align: left;
}
/* .form-select ต้นแบบมี padding แนวตั้งของ floating อยู่แล้ว — คงไว้ ให้ชื่อไม่ล้น caret */
.bankSelect__trigger .bankSelect__name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bankSelect__logo {
  width: 22px; height: 22px; flex: 0 0 auto;
  object-fit: contain; border-radius: 4px; background: #fff;
}
.bankSelect__menu {
  position: absolute; z-index: 30; top: calc(100% + 4px); left: 0; right: 0;
  max-height: 280px; overflow-y: auto; margin: 0; padding: 6px;
  list-style: none;
  /* พื้น "ปกติ" = ทองเข้มโทนการ์ด (mix จาก --gold-lo) ให้ลิสต์เข้าธีมทอง + ขอบทอง
     ตัวอักษรขาวยังอ่านออก · เปลี่ยนพรีเซ็ตธีม → ทองเปลี่ยนตาม token */
  background: color-mix(in srgb, var(--gold-lo) 32%, #000);
  border: 1px solid var(--gold);
  border-radius: 10px; box-shadow: 0 8px 24px rgba(0, 0, 0, .45);
}
.bankSelect__menu li { margin: 0; }
.bankSelect__opt {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 10px; border: 0; border-radius: 8px;
  background: transparent; color: var(--txt);
  text-align: left; cursor: pointer; font-size: 14px;
  transition: background-color .15s;
}
.bankSelect__opt .bankSelect__name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* hover = ทองสว่างจาง (บนพื้นทองเข้ม) · ตัวที่เลือก = ไล่เฉดสีหลักของธีม (--Linear) อ่านออกชัด */
.bankSelect__opt:hover { background: color-mix(in srgb, var(--gold-hi) 22%, transparent); }
.bankSelect__opt.is-active { background: var(--Linear); color: var(--txt); }

/* ════════ §6 แถบ "อัตราแตก %" บนการ์ดเกมสล็อต ════════
   ⚠️ ตัวเลขเป็นค่าสุ่มฝั่ง client (Math.random 90–99) **ไม่ใช่ RTP จริง และไม่ได้มาจาก API**
      ทำเหมือนต้นแบบตามที่ผู้ใช้สั่ง — อย่าเอาไปอ้างอิงเป็นค่าจริง
   เดิม GameLobby ใส่คลาส progress-bg-danger/warning/success ไว้แล้ว แต่ **ไม่มี CSS รองรับสักตัว**
   → ทุกระดับเห็นเป็นลายทองเหมือนกันหมด (แยก 3 ระดับไม่ออก) · คลาสพวกนี้จึงมาผูก token ตรงนี้
   คงสัญญาณ ต่ำ→สูง = แดง/เหลือง/เขียว (ถ้า map เข้าสีธีมล้วน ธีมสีเดียวจะแยกระดับไม่ออก) */
.progress-bar-stripes.progress-bg-danger {
  background-image: linear-gradient(306deg, var(--danger) 50%, var(--danger-2) 50%);
}
.progress-bar-stripes.progress-bg-warning {
  background-image: linear-gradient(306deg, var(--warning) 50%, var(--gold-lo) 50%);
}
.progress-bar-stripes.progress-bg-success {
  background-image: linear-gradient(306deg, var(--success) 50%, var(--success-2) 50%);
}
/* เงาเรืองแสงทองของแถบ — ใช้ token --gold-glow (ก่อนหน้านี้ประกาศครบ 14 ธีมแต่ไม่มีใครอ่านเลย)
   ฟีเจอร์นี้ default ปิด ⇒ เว็บที่ไม่ได้เปิดจะไม่มีอะไรเปลี่ยนจากเดิม */
.gameList .progress {
  box-shadow: 0 0 8px 0 var(--gold-glow);
}

/* ════════ §7 แท็บเลือกช่องทางฝาก (/account/deposit) ════════
   ⚠️ ต้นแบบ (onemaster) มีช่องทางฝาก "ช่องทางเดียว" จึงไม่มีแท็บให้ dump —
      backend ของเราส่ง deposit_channels มาได้ถึง 4 ช่อง (docs/deposit-flow-ui.md §3)
      จึง reuse .nav-tabs.tabAff ของหน้า history (คลาสเดิมของธีม ไม่มีสีใหม่)
   ปัญหาที่วัดได้จริงที่ 390px: .nav-tabs .nav-link padding 10px 32px → 2 แท็บรวม 344px
   เกินความกว้างใน .cardBlock (~334px) ⇒ ตกบรรทัด เยื้องกันอ่านยาก
   แก้เฉพาะจอ < 768px: ล็อก 2 แท็บต่อบรรทัด (สี/เงา/มุมเดิมทั้งหมด)
   ⚠️ เคยลอง `nowrap + flex:1` ก่อน → พอมี 4 ช่องทางแท็บเหลือ 78px ข้อความไทยถูก ellipsis
      จนเหลือ "ฝากผ่าน…"/"ฝากด้วย…" แยกกันไม่ออก (วัดจริงที่ 390px) — 2 คอลัมน์อ่านออกกว่า */
@media (max-width: 767.98px) {
  .nav-tabs.tabAff { flex-wrap: wrap; row-gap: 4px; }
  .nav-tabs.tabAff .nav-item { flex: 1 1 calc(50% - 6px); min-width: 0; }
  .nav-tabs.tabAff .nav-link {
    width: 100%; padding: 10px 6px; margin-right: 2px; font-size: 14px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
}

/* ════════ §7b หน้าฝาก: ตัวอักษรบนการ์ดทองอ่านไม่ออก (2026-10-09) ════════
   🔴 **เจ้าของงานอนุมัติให้ต่างจากต้นฉบับเพื่อให้อ่านออก** — ยกเว้นกติกา "maruay ห้ามขยับสักพิกเซล"
      (§1d D7) เฉพาะหน้าฝาก (`.depositPage` ที่ app/account/(member)/deposit/page.tsx) เท่านั้น
   ของเดิม: ข้อความรับ `color` จาก body (= --main-color = --prim) หรือ `a { color: --main-color }`
   แล้ววางบนการ์ดทอง ⇒ maruay ได้ส้ม #ff7501 บน --gold-lo #b97b01 = **1.3:1**
   (กล่อง "ขั้นตอนการฝากเงิน", คำแนะนำในแท็บสลิป, ชื่อ/เลขบัญชีเว็บ, ปุ่ม "คัดลอกเลขบัญชี" ส้มบนส้ม,
    ตัวอักษรส้มบนปุ่มน้ำเงิน "ติดต่อแอดมิน") · ป้ายสีอ่อน (`.color-secondary` = --sub) ก็ได้แค่ ~1.4–2.9:1
   ⇒ ใช้หมึกที่ระบบนิยามไว้แล้ว ไม่ประดิษฐ์สีใหม่:
      บนการ์ดทอง → --gold-ink (หมึกคู่กับทองของทุกพรีเซ็ต — §1d D1/D6 ใช้ตัวเดียวกัน)
      บนปุ่มไล่สีหลัก `.grad_color02` (= --Linear) → --btn-login-ink (หมึกของปุ่มเข้าสู่ระบบซึ่งพื้นเป็น --Linear เหมือนกัน)
      บนปุ่มน้ำเงิน `.btn-flat` (= --info #2479dc คงที่ทุกพรีเซ็ต) → ขาว
   🔴 ไม่รวม c18 — c18 พลิกการ์ดเป็น --surf (§1d D7) แล้ว ตัวอักษรเดิม (#fffe97/--sub) อ่านออกอยู่แล้ว
      ถ้าใส่ --gold-ink ที่นั่นจะกลายเป็นหมึกเข้มบนพื้นเข้ม
   ⚠️ อยู่นอก §1d โดยตั้งใจ — §1d ล็อกไว้ให้มีแต่กฎของ c18 (tests/theme-c18-scope.test.mjs)
   ⚠️ `.text-muted` ต้อง !important — ของ bootstrap เป็น !important (เหตุผลเดียวกับ §1d D7) */
html[data-theme]:not([data-theme="c18"]) .depositPage .cardBlock,
html[data-theme]:not([data-theme="c18"]) .depositPage .cardColorDark,
html[data-theme]:not([data-theme="c18"]) .depositPage .cardBlock .color-secondary,
html[data-theme]:not([data-theme="c18"]) .depositPage .leftBankname h6,
html[data-theme]:not([data-theme="c18"]) .depositPage .bankBottom h6,
html[data-theme]:not([data-theme="c18"]) .depositPage .btn-main {
  color: var(--gold-ink);
}
html[data-theme]:not([data-theme="c18"]) .depositPage .cardBlock .text-muted,
html[data-theme]:not([data-theme="c18"]) .depositPage .cardColorDark .text-muted {
  color: var(--gold-ink) !important;
}
html[data-theme]:not([data-theme="c18"]) .depositPage .grad_color02 {
  color: var(--btn-login-ink);
}
html[data-theme]:not([data-theme="c18"]) .depositPage .btn-flat {
  color: #fff;
}

/* ════════ §9 จองพื้นที่รูปกัน CLS (วัดจริง 2026-08-09) ════════
   ก่อนแก้: CLS 0.107 (เดสก์ท็อป) / 0.160 (มือถือ 4G) · รูปทั้งหน้า 250 ใบไม่มี width/height เลย
   สาเหตุ: `<img>` ที่ไม่มีขนาด + CSS `height:auto` = สูง 0 จนกว่ารูปจะมา ⇒ ของใต้มันกระโดด
   (ต้นเหตุที่วัดได้: .fixedMenu เลื่อน 0.075 ตอน 2.6s = จังหวะแบนเนอร์ลงจอ)

   ⚠️ ค่าสัดส่วนอยู่ที่ src/config/imageAspect.ts (แหล่งเดียว) — ที่นี่รับมาผ่าน inline style
      ยกเว้นการ์ดเกมที่เป็นค่าเดียวตายตัว (รูป PG จัตุรัส 360×360 ทุกใบ) เขียนไว้ตรงนี้เลย */

/* การ์ดเกมในกริด — จองกล่องจัตุรัสไว้ก่อน รูปมาแล้วเติมพอดี ไม่ดันแถวล่าง */
.gameCard img {
  aspect-ratio: 1 / 1;
  display: block;
}

/* กล่องแบนเนอร์ — `aspect-ratio` ตั้งจาก inline style ของ BannerCarousel
   ⚠️ ต่างจากต้นแบบโดยตั้งใจ: แบนเนอร์ของ tenant เราสัดส่วนไม่เท่ากัน (2.40 กับ 3.00)
      ถ้าปล่อยกล่องสูงตามรูปแบบต้นแบบ กล่องจะเปลี่ยนความสูงทุก 3 วิที่สไลด์หมุน = CLS ตลอดเวลา

   🪤 เคยใช้ `cover` ก่อน → เทียบ screenshot แล้วเห็นชัดว่า **รูป 3.00 ถูก crop ข้างจนข้อความ
      โปรโมชั่นหายไปครึ่งประโยค** ("พร้อมใบเซอร์การันตี" เหลือ "พร้อมใบเซอร์การั")
      ⇒ ใช้ `contain` แทน: จองพื้นที่เท่าเดิม (CLS ยังเป็น 0) แต่ไม่ตัดเนื้อหาแบนเนอร์ทิ้ง
      รูปที่กว้างกว่ากล่องจะมีช่องว่างบน-ล่างเล็กน้อยแทน — ยอมได้ ดีกว่าข้อความขาด
      เลือกสัดส่วนกล่องเป็นใบที่ "สูงที่สุด" (2.40) ช่องว่างจึงน้อยที่สุดเท่าที่เป็นไปได้ */
.bannerCarousel .carousel-item,
.bannerCarousel .carousel-item img {
  height: 100%;
}
.bannerCarousel .carousel-item img {
  object-fit: contain;
  object-position: center;
}

/* ════════ §10 useLinkStatus — ตัวยืนยันว่ากดติดระหว่างรอ navigate ════════
   ปิด prefetch ทุก <Link> ทั้งเว็บ (ดูเหตุผล/ตัวเลขที่ BottomNav.tsx) → กด nav แล้วต้อง
   รอ RSC ตอบจริง ไม่มี prefetch cache ช่วย ⇒ ผู้ใช้กดแล้วไม่เห็นอะไรขยับสักพัก
   src/components/LinkPending.tsx เรียก useLinkStatus() จาก <Link> ที่ผู้ใช้กดย้ายหน้าจริง
   (bottom nav, header, เมนูสมาชิก, ปุ่มย้อนกลับ) แล้ว toggle คลาส .is-pending ที่นี่

   [Fix round 1 — พบจากรีวิวในเบราว์เซอร์จริง] ของเดิม (.link-pending-anchor กว้าง/สูง 0
   วางอยู่ตรงจุดแทรกใน DOM) ทำให้สปินเนอร์ลอยที่ "ท้ายเนื้อหา" ของ Link ไม่ใช่กลางกล่อง — ล้น
   ขอบทั้งโลโก้ (ขวา 8px) และปุ่มการ์ด (ล่าง 2px) เปลี่ยนมาให้ `<a>` ที่มี LinkPending ข้างใน
   เป็น positioning context ของตัวเองแทน ด้วย `a:has()` (ไม่ต้องแก้ 18 จุดที่เรียก — Chrome/
   Safari/Firefox รุ่นที่ใช้จริงรองรับแล้ว) แล้วให้ `.link-pending-anchor` เป็น
   position:absolute; inset:0 คลุมทั้งกล่อง Link แทนจุด 0×0 เดิม — ยังอยู่นอก flow เหมือนเดิม
   (absolute descendant ไม่มีผลต่อขนาดกล่อง ancestor ไม่ว่าจะตั้ง inset เท่าไหร่) จึงไม่กระทบ
   CLS เพิ่มจากที่วัดได้ (0.0055 ทั้งสอง viewport)

   🔴 ระหว่างแก้เจออีกบั๊ก: 2 จุดในธีมมี selector "span" แบบกว้าง (ไม่จำกัดชั้นลูก) ที่ดักสปินเนอร์
      ของเราไปโดยไม่ตั้งใจ เพราะ specificity สูงกว่าคลาสเดี่ยวของเรา:
        • .btnMenu span (style.css:482, specificity 0,1,1) ตั้ง position:relative ทับ
          position:absolute ของ .link-pending (0,1,0) — ผลคือในกริดเมนู (.btnMenu — ปุ่มฝาก/
          ถอนลัด, เมนูสมาชิก 14 ช่อง, TOP_MENU ของแขก) สปินเนอร์ไม่ได้ absolute จริง
        • .menuDashboard .btnMenu span (บรรทัดข้างบนในไฟล์นี้ ทั้ง 2 media query,
          specificity 0,2,1) ตั้ง display:block; width:100% ทับ width:16px ของเรา (0,1,0)
          ⇒ สปินเนอร์ที่ควรกว้าง 16px ไปกว้างเท่าเนื้อที่ tile แทน (วัดจริงได้ ~54px บน tile
          มือถือ 52px กว้าง) — เป็นสาเหตุของความกว้างผิดปกติที่วัดเจอ ไม่ใช่แค่ตำแหน่งเพี้ยน
      แก้ด้วย !important เฉพาะ property ที่กระทบ geometry (position/inset/width/height/
      margin/pointer-events) — คลาสพวกนี้เป็นของ LinkPending เท่านั้น ไม่มี legit case ที่
      ควรมี selector อื่นมา override ต่อ ⚠️ ห้ามใส่ !important ที่ opacity/transform —
      2 ตัวนี้ถูก @keyframes ควบคุมอยู่ (linkPendingFade/linkPendingSpin) ใส่ !important จะ
      ทำให้ animation เปลี่ยนค่าไม่ได้เลย */
a:has(.link-pending-anchor) {
  /* ของเดิม <a> บางกลุ่มมี position:relative อยู่แล้ว (.btnMenu) บางกลุ่มไม่มีเลย
     (.menuListNavBottom li a, .header a, .backLink a) — บังคับให้เท่ากันหมดด้วย :has()
     เดียว ไม่ต้องส่อง 18 จุด · ไม่มี top/left ตามมา ⇒ ไม่ขยับตำแหน่งเดิมของ <a> เอง */
  position: relative !important;
}
.link-pending-anchor {
  position: absolute !important;
  inset: 0 !important;
  pointer-events: none !important;
}
/* [Fix round 2 — พบจากรีวิวในเบราว์เซอร์จริง] วง var(--gold) เดี่ยวๆ contrast ต่ำกว่าเกณฑ์
   WCAG 3:1 (non-text UI) มาก — วัดจริงบนพื้นขาว 1.68:1, พื้นแดง 2.88:1 (ตรงกับตัวเลขที่คำนวณ
   ด้วยสูตร relative-luminance ของ WCAG เป๊ะ — 1.675/2.883) เพราะทองสว่างใกล้เคียง midtone
   ไม่ต่างจากพื้นขาว/แดง/ทองด้วยกันเองมากพอ ปัญหาคือ "พื้นหลังไม่คงที่" — การ์ดขาว ปุ่มแดง
   โครมทอง แบนเนอร์รูปภาพ และสีธีมที่แอดมินเปลี่ยนได้จาก studio ไม่มีสีเดียวที่ tune ให้พอดี
   กับทุกพื้นได้

   แก้ด้วยหลักการ "สีคู่ตรงข้ามสุดขั้ว" (ดำ+ขาว ทึบแสง) แทนการ tune สีเดียว: ดำกับขาวคือ
   luminance 0 กับ 1 — พิสูจน์ได้ด้วยสูตร WCAG เองว่า max(contrast(ดำ,L), contrast(ขาว,L))
   สำหรับพื้นหลัง luminance L ใดๆ ต่ำสุดที่เป็นไปได้คือ 4.58:1 (จุดตัดที่ L≈0.179 ที่ทั้งสองค่า
   เท่ากันพอดี) สูงกว่าเกณฑ์ 3:1 เสมอไม่ว่าพื้นหลังจะเป็นสีอะไร — ไม่ใช่การเดา แต่เป็นการรับประกัน
   ทางคณิตศาสตร์ ตัวเลขที่วัด/คำนวณจริง (สคริปต์ตรวจสอบ node ยืนยันตรงกับเบราว์เซอร์ก่อนแก้):
     • ดำ (แผ่นหลัง .link-pending) vs ขาว:        21.00:1
     • ดำ vs var(--gold) (โครมทองของธีม):          12.54:1
     • ดำ vs ปุ่มแดง rgb(220,38,38):                4.35:1
     • ขาว (ขอบ box-shadow) vs ปุ่มแดง:             4.83:1
     • วงทอง vs แผ่นดำของตัวเอง (คงแบรนด์ไว้):      12.54:1
   โครง: .link-pending มี background ทึบดำ (แผ่นหลังควบคุมพื้นให้วงทองเสมอ ไม่ขึ้นกับหน้าเว็บ)
   + border ทองเดิม (ยังหมุนได้ตามปกติ) + box-shadow ขาวทึบบางๆ ล้อมนอกสุด (คุมเคสพื้นหลังมืด
   ที่แผ่นดำเองจะกลืนไป) — ทั้งสองเป็น paint-only (background/box-shadow ไม่กระทบ box model)
   จึงไม่แตะ geometry 16×16 หรือ zero-layout-impact ที่ยืนยันไปแล้วในรอบ 1 เลย
   ⚠️ ปรับปลายทาง fade เป็น opacity:1 (จากเดิม 0.9) ด้วย — ตัวเลขข้างบนคำนวณจากสีทึบเต็ม
   100% หาก stop ที่ 0.9 พื้นหลังหน้าเว็บจะเจือสีเข้ามา 10% ลด margin ที่มีอยู่ (safety margin
   53% เหนือเกณฑ์ 3:1) ลงเล็กน้อย — 1.0 ตัดปัญหานี้ทิ้งไปเลยไม่มีเหตุผลให้ต้องเสี่ยง */
.link-pending {
  position: absolute !important;
  top: 50% !important;
  left: 50% !important;
  width: 16px !important;
  height: 16px !important;
  margin: -8px 0 0 -8px !important;
  border-radius: 50%;
  background: #000;
  border: 2px solid var(--gold);
  border-top-color: transparent;
  box-shadow: 0 0 0 1.5px #fff;
  opacity: 0;
  visibility: hidden !important;
  pointer-events: none !important;
}
.link-pending.is-pending {
  visibility: visible !important;
  /* ดีเลย์ 100ms ก่อนแสดง — นำทางที่จบเร็วจะไม่เห็นตัวหมุนกระพริบเลย (ตามคำแนะนำใน
     Next.js docs ของ useLinkStatus) */
  animation:
    linkPendingFade 150ms ease 100ms forwards,
    linkPendingSpin 0.6s linear 100ms infinite;
}
@keyframes linkPendingFade {
  to {
    opacity: 1;
  }
}
@keyframes linkPendingSpin {
  to {
    transform: rotate(360deg);
  }
}

/* ── ท้ายเว็บที่ตั้งจาก /theme-studio ────────────────────────────────────────
   🔴 ต้นแบบ (maruay) ไม่มี footer เลย — บล็อกนี้โผล่เฉพาะตอนแอดมินตั้งค่าจากแท็บ "ท้ายเว็บ"
   เท่านั้น (SiteFooter.tsx คืน null ถ้าทั้ง 4 ช่องว่าง/ปิดฟีเจอร์ — ไม่มีบรรทัดว่าง ไม่มีกล่องเปล่า)
   ใช้คลาส `.site-footer` ของเราเอง ไม่ทับ `.footer` ที่ค้างอยู่ใน style.css:827 (ไม่มีใครใช้
   คลาสนั้น แต่ padding-bottom 120px ของมันไม่ตรงกับที่เราต้องการอยู่ดี — ตั้งชื่อแยกกันชัดกว่า)

   🔴 ห้ามใช้ margin-bottom ที่นี่ — body โดน margin collapse มาแล้ว (ดู CLAUDE.md
      §.mgMenuBottom) ระยะกัน BottomNav มาจาก `body.mgMenuBottom { padding-bottom }` ที่มีอยู่แล้ว
      (.fixedMenu เป็น position:fixed ไม่กินพื้นที่ใน flow — footer แค่ต้องเรนเดอร์ "ก่อน"
      ระยะเผื่อนั้นในลำดับ DOM ซึ่งมันเป็นอยู่แล้วเพราะ mount ท้ายสุดใน providers.tsx)

   สี/ฟอนต์ยึด token ของธีมนี้ ไม่ hardcode ค่าใหม่:
   · border ใช้ `--edge-soft` (ตัวเดียวกับที่จุดอื่นในไฟล์นี้ใช้ทำเส้นขอบบางๆ)
   · หัวข้อหนาด้วย `--font-bold` ไม่ใช่ `font-weight:700` — ธีมนี้ทำตัวหนาด้วยการสลับ "ตระกูล
     ฟอนต์" คนละไฟล์ (ดู font-style.css) `@font-face` ทุกตัวประกาศ `font-weight: normal`ไว้หมด
     ใส่ font-weight:700 ทับจะไม่ทำให้ตัวหนาขึ้นจริง
   · ขนาดฟอนต์ 15/13/13/12px อยู่ในสเกลเดียวกับที่ style.css ใช้ซ้ำอยู่แล้วทั้งเว็บ (12px = ฐาน
     ของ body, 13/15px = ข้อความรองที่ใช้หลายจุด) ไม่ได้เพิ่มสเกลใหม่
   · ความกว้าง .sf-about จำกัดที่ 660px = ความกว้างคอลัมน์เนื้อหาเดสก์ท็อป (.col-md-6) ที่วัดไว้
     ใน CLAUDE.md ให้ย่อหน้ายาวอ่านง่ายเหมือนเนื้อหาอื่นของหน้า ไม่ใช้ 640px ลอยๆ

   ⚠️ `white-space: pre-line` ใส่แบบ**ไม่มีเงื่อนไข**บน `.sf-about` — ปกติกับดักนี้ต้องผูกเงื่อนไข
   กับ "ค่ามาจาก studio" (ดู PORT-PLAYBOOK.md บทเรียน 5) แต่ **ที่นี่ไม่มีทางอื่นที่ .sf-about จะ
   เรนเดอร์ได้เลยนอกจากมาจาก studio** — SiteFooter คืน null ทั้งก้อนถ้าไม่มีอะไรให้โชว์ และ about
   ไม่มี fallback จาก API/hardcode ใดๆ (theme4 ไม่เคยมี footer มาก่อน) ⇒ ไม่มี path ที่ pre-line
   จะไปเปลี่ยนย่อหน้าเดิมของธีม เพราะ "ย่อหน้าเดิม" ไม่มีอยู่จริง */
.site-footer {
  text-align: center;
  padding: 24px 16px;
  border-top: 1px solid var(--edge-soft);
}

/* ── §1e เส้นแบ่งหัว footer ตอนเลือกธีมสำเร็จรูป (2026-08-29) ──
   ตัวหลักเปิดเบราว์เซอร์วัด contrast ระหว่างพื้น footer กับพื้นการ์ด (--surf) ครบทุกธีมใน theme2
   ได้ 1.04-1.18 และ **3 ธีมพื้นสว่างได้ 1.00 พอดี** (9 แดง&ขาว · 14 ขาว&ฟ้า) กับ 1.05 (11)
   ⇒ footer จมหายไปกับหน้า เป็นอาการเดียวกับที่เจ้าของงานทักตอน c18
   ("ทำไมสี footer ถึงเป็นแบบนี้ มันไม่แยกกับตัวสี card หรอ") แค่ธีมสว่างหนักกว่าจนหายไปเลย

   🔴 **ห้ามแก้ด้วยการดันสีพื้นให้ต่างกัน** — จานสีพวกนี้ตั้ง --bg1 กับ --surf เป็นขาวทั้งคู่
      **โดยตั้งใจ** ธีมพื้นสว่างเขาแยกชั้นด้วย "เส้น/เงา" ไม่ใช่สีพื้น · และ c18 ถ้าดันพื้น footer
      ให้สว่างขึ้นจะไปชนกับ --surf #303030 พอดี = แย่กว่าเดิม
   ⇒ ใช้ "เส้นขอบบน" แทน ได้ผลทุกจานสีโดยไม่แตะสีสักตัว

   ที่นี่ต่างจาก theme2 ตรงที่ .site-footer **มีเส้นนี้อยู่แล้ว** แต่เป็น --edge-soft (= --edge
   ที่ความทึบ 55%) ซึ่งบนธีมพื้นสว่างแทบมองไม่เห็น ⇒ ดันเป็น --edge เต็มความทึบเฉพาะตอนเลือกธีม
   ⚠️ กัน maruay ออกเสมอ (ที่นี่ <html> มี data-theme ตลอด ดู §1b) — ธีมเริ่มต้นต้องได้เส้นจาง
      เท่าเดิมเป๊ะ · specificity (0,3,1) ชนะ .site-footer (0,1,0) ที่ประกาศเส้นจางไว้ข้างบน */
html[data-theme]:not([data-theme="maruay"]) .site-footer {
  border-top: 1px solid var(--edge);
}

/* 🔴 I-1 (final-review.md) — ช่องพวกนี้พิมพ์เองจาก studio ไม่ผ่านการตัดคำ (contactLine เป็น URL
   ยาวๆ ได้จริง เช่นลิงก์เชิญ Telegram) ⇒ ไม่มี overflow-wrap แล้วโทเคนยาวเกินกล่องหนึ่งคำ จะดัน
   documentElement.scrollWidth เกิน clientWidth ทั้งหน้า (footer เป็นลูกตรงของ body เต็มความกว้าง
   จอ ไม่ได้อยู่ใน .container ที่ตัดคำให้) — วัดจริงที่ 390px: URL Telegram 68 ตัวอักษรทำให้เลื่อน
   แนวนอนได้ 125px ก่อนแก้ ⇒ 0px หลังแก้ (theme4-overrides.css:99 ใช้สำนวนเดียวกันนี้อยู่แล้วกับ
   ปัญหาชนิดเดียวกัน) */
.site-footer p { margin: 0 0 8px; overflow-wrap: anywhere; }
.site-footer p:last-child { margin-bottom: 0; }
.site-footer .sf-heading { font-family: var(--font-bold); font-size: 15px; }
.site-footer .sf-about {
  font-size: 13px;
  line-height: 1.6;
  max-width: 660px;
  margin-inline: auto;
  white-space: pre-line;
}
.site-footer .sf-contact { font-size: 13px; color: var(--secondary-color); }
.site-footer .sf-copy    { font-size: 12px; opacity: 0.7; }

/* ── ชิปแท็ก SEO (พอร์ตจาก theme7@1740530) ──
   หัวข้อ "แท็ก" ใช้สเกล/น้ำหนักเดียวกับ .sf-heading (ฟอนต์หนา + 15px) เพราะเป็นหัวข้อย่อย
   ระดับเดียวกันในบล็อกนี้ ไม่ใช่หัวข้อใหญ่แบบ .article-tags__heading (16px) ของหน้าบทความ —
   ที่นั่นเป็นบล็อกเดี่ยวเต็มความกว้างคอนเทนต์ ส่วนนี่ซ้อนอยู่ในคอลัมน์ footer ที่แคบกว่า

   ชิป `.sf-tag` เลียนแบบ `.article-tags .tag` (โทเคนสีชุดเดียวกัน: --edge / --bg1 / --sub)
   ให้ "ชิปคำ" ทั้งเว็บหน้าตาเป็นภาษาเดียวกัน ไม่ประดิษฐ์สีใหม่ — ต่างแค่ scope class เพราะ
   `.tag` เปล่าๆ ไม่มีกฎอะไรนอก `.article-tags` (ดูไฟล์ article-page.css) ใส่ตรงๆ ที่นี่จะไม่มีผล

   🔴 overflow-wrap: anywhere ต้องอยู่ที่ชิป ไม่ใช่แค่ที่ .site-footer p — คีย์เวิร์ดยาวไม่มีช่องว่าง
      (เช่นโดเมน/แบรนด์ภาษาอังกฤษยาวๆ) ดันความกว้างชิปเดี่ยวเกินคอนเทนเนอร์ได้เหมือนกับปัญหา
      contactLine ที่แก้ไว้แล้วข้างบน (theme4-overrides.css:99 ใช้สำนวนเดียวกันนี้) — flex-wrap
      บน `.sf-tags` ช่วยแค่ตอนมีหลายชิป ไม่ช่วยตอนชิป "หนึ่งชิ้น" ยาวเกินบรรทัดเดียว */
.site-footer .sf-tags-heading { font-family: var(--font-bold); font-size: 15px; margin: 0 0 8px; }
.site-footer .sf-tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 0 0 8px;
}
.site-footer .sf-tag {
  display: inline-block;
  padding: 4px 12px;
  border: 1px solid var(--edge);
  border-radius: 50px;
  background: var(--bg1);
  color: var(--sub);
  font-size: 13px;
  overflow-wrap: anywhere;
}
