/* ============================================================================
   OMCWEB — Management UI
   ทิศทางการออกแบบ: corporate clean (CLAUDE.md ข้อ 1)
   ‼️ ค่าสี ระยะห่าง ขนาด ทั้งระบบอยู่ที่ไฟล์นี้ที่เดียว (กฎเหล็กข้อ 8)
      ห้าม hardcode ค่าดิบในหน้า ห้ามมี <style> ในหน้า ห้ามมี CSS แยกต่อหน้า
   ============================================================================ */

:root {
    /* ---- สีแบรนด์ ---- */
    /* --color-primary คือสีแบรนด์ ใช้กับพื้นที่ขนาดใหญ่และงานตกแต่ง
       ส่วนข้อความและพื้นปุ่มต้องใช้ --color-primary-strong เพราะสีแบรนด์บนพื้นขาว
       ได้ contrast เพียง 3.58:1 ซึ่งไม่ผ่าน WCAG AA (design.md ข้อ 3.8) */
    --color-primary:        #E8590C;
    --color-primary-strong: #C0430A;
    --color-primary-hover:  #A63808;
    --color-primary-soft:   #FDF0E7;
    --color-primary-border: #F6C9AC;
    --color-secondary:      #1B2A4A;
    --color-secondary-soft: #EDF1F7;

    /* ---- พื้นเข้มของหน้าแนะนำผลิตภัณฑ์ ---- */
    /* ‼️ ตัวอักษรบนพื้นกรมท่าต้องใช้สามตัวนี้เท่านั้น ค่าอื่นไม่ผ่าน WCAG AA
       #FFFFFF บน --color-hero = 14.11:1 · --color-text-on-dark-muted = 7.94:1
       --color-primary-on-dark = 6.02:1 (สีแบรนด์ตัวจริงได้แค่ 3.96:1 จึงใช้บนพื้นเข้มไม่ได้)
       --color-success-on-dark = 8.16:1 */
    --color-hero:               #1B2A4A;
    --color-hero-deep:          #101B31;
    --color-text-on-dark-muted: #B9C4D6;
    --color-primary-on-dark:    #FF8A3D;
    --color-success-on-dark:    #6FD6AE;
    --color-device-edge:        #D4DAE3;

    /* ---- พื้นผิว ---- */
    --color-bg:            #F6F7F9;
    --color-surface:       #FFFFFF;
    --color-surface-muted: #FAFAFB;
    --color-border:        #E3E6EA;
    --color-border-strong: #CBD2DA;
    --color-text:          #1C2430;
    --color-text-muted:    #667283;
    /* ‼️ --color-text-muted ถูกเลือกโดยเทียบพื้นขาว (4.88:1 ผ่าน AA พอดี)
       พอเอาไปวางบนพื้นที่เข้มกว่าอย่าง --color-neutral-soft จะเหลือ 4.32:1 = ไม่ผ่าน
       ตัวอักษรที่อยู่บนพื้นสีเทาอ่อนต้องใช้ตัวนี้แทน (5.60:1 บนพื้นเทาอ่อน · 6.34:1 บนขาว)
       ยกเว้น control ที่ปิดใช้งาน (WCAG 1.4.3) และไอคอนล้วน (ใช้เกณฑ์ 3:1 ตาม 1.4.11) */
    --color-text-muted-on-soft: #566072;
    --color-text-inverse:  #FFFFFF;

    /* ---- สี semantic: ใช้สื่อสถานะเท่านั้น ห้ามใช้ตกแต่ง ---- */
    --color-success:      #16704F;
    --color-success-soft: #E7F5EF;
    --color-warning:      #92610F;
    --color-warning-soft: #FDF5E3;
    --color-danger:       #C42B2B;
    --color-danger-soft:  #FCEDED;
    --color-info:         #1F5F9E;
    --color-info-soft:    #EAF2FA;
    /* #667283 บนพื้น --color-neutral-soft ได้แค่ 4.32:1 จึงต้องเข้มกว่าสีข้อความรองทั่วไป */
    --color-neutral:      #55606F;
    --color-neutral-soft: #EFF1F4;

    /* ---- ระยะห่าง: ทวีคูณของ 4px ---- */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 16px;
    --space-4: 24px;
    --space-5: 32px;
    --space-6: 48px;
    --space-7: 64px;
    --space-8: 88px;

    /* ---- ตัวอักษร (ต้องรองรับไทยและละติน · ห้ามใช้ Inter/Roboto ตาม design.md ข้อ 1) ---- */
    --font-family: "IBM Plex Sans Thai", "Noto Sans Thai", "Sarabun", "Segoe UI", system-ui, sans-serif;
    --font-family-mono: "JetBrains Mono", "Cascadia Mono", ui-monospace, monospace;
    --font-size-xs:   12px;
    --font-size-sm:   14px;
    --font-size-base: 16px;
    --font-size-lg:   20px;
    --font-size-xl:   24px;
    --font-size-2xl:  32px;
    --font-size-3xl:  40px;
    --font-size-4xl:  50px;
    --font-weight-normal: 400;
    --font-weight-medium: 500;
    --font-weight-bold:   600;
    --line-height-base:  1.6;
    --line-height-tight: 1.3;

    /* ---- รูปทรง ---- */
    --radius-sm:   4px;
    --radius-base: 8px;
    --radius-lg:   12px;
    --radius-pill: 999px;
    --border-width: 1px;
    --shadow-sm:    0 1px 2px rgba(28, 36, 48, .06);
    --shadow-base:  0 2px 8px rgba(28, 36, 48, .08);
    --shadow-lg:    0 12px 32px rgba(28, 36, 48, .14);
    --shadow-device: 0 24px 60px rgba(9, 15, 28, .35);

    /* ---- ขนาด component: ต้องเท่ากันทั้งระบบ ---- */
    --height-input:  40px;
    --height-button: 40px;
    --height-row:    48px;
    --icon-size:     20px;
    --sidebar-width: 248px;
    --topbar-height: 60px;
    --content-max:   1320px;
    --size-strip-icon:     40px;
    --size-tpl-card:       208px;
    --size-rail-arrow:     40px;
    --size-rail-arrow-top: 84px;

    --transition-base: 180ms ease;

    /* ---- โทนสีของชิปไอคอน (design system v2) ----
       ‼️ ใช้กับ "ชิปไอคอน" ในการ์ดเท่านั้น ห้ามใช้ระบายพื้นการ์ดทั้งใบ (design.md ข้อ 5.3)
          การ์ดทุกใบยังเป็นพื้นขาวเหมือนกันหมด ต่างกันแค่ไอคอนนำสายตาให้จำตำแหน่งได้
       ‼️ ทุกคู่ผ่าน WCAG AA บนพื้นของตัวเอง (ตรวจซ้ำด้วย scripts/check-screens.php) */
    --tint-brand-bg:  #FDF0E7;  --tint-brand-fg:  #C0430A;
    --tint-green-bg:  #E7F5EF;  --tint-green-fg:  #16704F;
    --tint-violet-bg: #EFECFD;  --tint-violet-fg: #4F35BE;
    --tint-blue-bg:   #EAF2FA;  --tint-blue-fg:   #1F5F9E;
    --tint-slate-bg:  #EFF1F4;  --tint-slate-fg:  #55606F;

    /* ---- สีของกราฟ (ไล่ตามลำดับเสมอ ห้ามสุ่ม · design.md ข้อ 5.4) ---- */
    --chart-1: #E8590C;
    --chart-2: #5B3FD1;
    --chart-3: #16704F;
    --chart-4: #1F5F9E;
    --chart-5: #C9CFD8;
    --chart-grid: #EDEFF3;

    /* ---- โครงหน้าจอเพิ่มเติม ---- */
    --sidebar-width-collapsed: 76px;
    --radius-xl: 16px;
    --shadow-card: 0 1px 2px rgba(28, 36, 48, .04), 0 1px 3px rgba(28, 36, 48, .06);
    --shadow-pop:  0 8px 24px rgba(28, 36, 48, .10);
    --height-control-sm: 32px;
    /* ช่องกรอกของหน้าที่ยังไม่ล็อกอิน — สูงกว่าในระบบจัดการเพราะเป็นหน้าที่ผู้ใช้ใหม่เจอก่อนใคร */
    --height-input-auth: 46px;

    /* ---- ค่าที่เคยเขียนดิบอยู่ในกฎ ยกขึ้นมาเป็น token เพื่อให้โหมดมืดเปลี่ยนตามได้ ---- */
    /* ‼️ ฉากหลังของ modal/drawer/ทัวร์ ต้องเข้มขึ้นในโหมดมืด ไม่ใช่ค่าเดิม
       พื้นหลังโหมดมืดเข้มอยู่แล้ว ถ้าใช้ความทึบเท่าเดิมจะแยกไม่ออกว่าอะไรอยู่หน้าอะไร */
    --color-backdrop:        rgba(28, 36, 48, .5);
    --color-backdrop-strong: rgba(28, 36, 48, .55);
    --auth-aside-bg:   linear-gradient(160deg, #FFF6EF 0%, #FFFDFB 46%, #FDF1E7 100%);
    --auth-aside-glow: radial-gradient(circle, rgba(232, 89, 12, .10), transparent 64%);
}

/* ---------------------------------------------------------------- base */

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

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-family);
    font-size: var(--font-size-base);
    line-height: var(--line-height-base);
}

h1, h2, h3, h4, h5, h6 {
    margin: 0 0 var(--space-2);
    line-height: var(--line-height-tight);
    font-weight: var(--font-weight-bold);
}

h1 { font-size: var(--font-size-2xl); }
h2 { font-size: var(--font-size-xl); }
h3 { font-size: var(--font-size-lg); }
h4 { font-size: var(--font-size-base); }

p { margin: 0 0 var(--space-3); }

a {
    color: var(--color-primary-strong);
    text-decoration: none;
    transition: color var(--transition-base);
}

a:hover { color: var(--color-primary-hover); text-decoration: underline; }

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

img { max-width: 100%; height: auto; }

hr {
    border: 0;
    border-top: var(--border-width) solid var(--color-border);
    margin: var(--space-4) 0;
}

small { font-size: var(--font-size-sm); }

code, pre { font-family: var(--font-family-mono); font-size: var(--font-size-sm); }

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

.skip-link {
    position: absolute;
    left: var(--space-3);
    top: calc(var(--space-3) * -4);
    z-index: 100;
    background: var(--color-surface);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-base);
    box-shadow: var(--shadow-base);
    transition: top var(--transition-base);
}

.skip-link:focus { top: var(--space-3); }

/* ------------------------------------------------------------- utilities */

.text-muted   { color: var(--color-text-muted); }
.text-sm      { font-size: var(--font-size-sm); }
.text-xs      { font-size: var(--font-size-xs); }
.text-lg      { font-size: var(--font-size-lg); }
.text-bold    { font-weight: var(--font-weight-bold); }
.text-medium  { font-weight: var(--font-weight-medium); }
.text-right   { text-align: right; }
.text-center  { text-align: center; }
.text-nowrap  { white-space: nowrap; }
.text-block   { display: block; }   /* ข้อความรองที่ต้องขึ้นบรรทัดใหม่ใต้ชื่อหลัก */
.text-danger  { color: var(--color-danger); }
.text-success { color: var(--color-success); }
.text-primary { color: var(--color-primary-strong); }

.truncate {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ‼️ ใช้กับ <ul> ได้ด้วย จึงต้องล้าง padding/marker ของ list ทิ้ง ไม่งั้นเนื้อหาจะเยื้องเข้าไป 40px */
ul[class*="stack"],
ol[class*="stack"] { list-style: none; padding: 0; margin: 0; }

/* ‼️ .stack-1 เคยถูกใช้ในหน้าโดยไม่มีนิยาม (ทะเบียนหนี้เทคนิค) — ประกาศไว้ที่นี่ให้ครบชุด */
.stack-1 { display: flex; flex-direction: column; gap: var(--space-1); }
.stack   { display: flex; flex-direction: column; gap: var(--space-3); }
.stack-2 { display: flex; flex-direction: column; gap: var(--space-2); }
.stack-4 { display: flex; flex-direction: column; gap: var(--space-4); }
.stack-5 { display: flex; flex-direction: column; gap: var(--space-5); }

.row-flex {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.row-between {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.grid { display: grid; gap: var(--space-4); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* คอลัมน์ที่เนื้อหาสั้นกว่าไม่ต้องยืดตามคอลัมน์ที่ยาวกว่า — กันการ์ดว่างสูงเกินจำเป็น */
.grid-sidebar { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: start; }

.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mb-0 { margin-bottom: 0; }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.w-full { width: 100%; }
.flex-1 { flex: 1 1 0%; min-width: 0; }   /* basis 0 เพื่อให้ข้อความยาวหดตัว ไม่ใช่ wrap ทั้งบล็อกลงบรรทัดใหม่ */

/* ------------------------------------------------------------ app shell */

.app {
    display: grid;
    grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
    min-height: 100vh;
}

/* ‼️ แถบข้างเป็นพื้นขาว ไม่ใช่พื้นกรมท่าอีกต่อไป (Visual Standard ที่อนุมัติ 2026-08-23)
   สีกรมท่ายังเป็นสีรองของแบรนด์ แต่ย้ายไปอยู่ที่ตัวอักษรหัวข้อและพื้นเข้มของหน้าแนะนำผลิตภัณฑ์
   เหตุผล: เมนู 12-13 รายการบนพื้นเข้มเต็มความสูงจอ กินสัดส่วนสีเกิน 30% ตาม design.md ข้อ 3.7
   และทำให้พื้นที่เนื้อหาดู "จม" — พื้นขาวคั่นด้วยเส้นเดียวให้น้ำหนักสายตาไปที่เนื้อหาแทน */
.sidebar {
    background: var(--color-surface);
    border-right: var(--border-width) solid var(--color-border);
    color: var(--color-text);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-3);
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.sidebar-brand {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-text);
    font-weight: var(--font-weight-bold);
    font-size: var(--font-size-lg);
    letter-spacing: .01em;
    padding: 0 var(--space-1);
    min-height: var(--space-5);
}

.sidebar-brand:hover { color: var(--color-text); text-decoration: none; }

.sidebar-brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-5);
    height: var(--space-5);
    /* ‼️ ต้องเป็น --color-primary-strong ไม่ใช่ --color-primary
       ตัวอักษรขาวบนสีแบรนด์ตัวจริงได้ contrast แค่ 3.58:1 ซึ่งไม่ผ่าน WCAG AA (design.md ข้อ 3.8) */
    background: var(--btn-primary-bg);
    color: var(--btn-primary-fg);
    border-radius: var(--radius-base);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-bold);
    letter-spacing: .04em;
    flex: none;
}

.sidebar-section-title {
    font-size: var(--font-size-xs);
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--color-text-muted);
    padding: 0 var(--space-2);
    margin-bottom: var(--space-1);
}

.sidebar-nav { display: flex; flex-direction: column; gap: 2px; }

/* ‼️ เส้นบอกตำแหน่งด้านซ้ายอยู่ที่ ::before ของทุกลิงก์ (โปร่งใสเมื่อไม่ active)
   ถ้าใส่เฉพาะตัวที่ active ข้อความจะขยับตอนเปลี่ยนหน้า */
.sidebar-link {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
    border-radius: var(--radius-base);
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-sm);
    transition: background var(--transition-base), color var(--transition-base);
}

.sidebar-link::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 3px;
    height: 60%;
    border-radius: 0 var(--radius-pill) var(--radius-pill) 0;
    background: transparent;
    transition: background var(--transition-base);
}

.sidebar-link:hover {
    background: var(--color-surface-muted);
    color: var(--color-text);
    text-decoration: none;
}

.sidebar-link.is-active {
    background: var(--color-primary-soft);
    color: var(--color-primary-strong);
    font-weight: var(--font-weight-medium);
}

.sidebar-link.is-active::before { background: var(--color-primary); }

.sidebar-link .icon { width: var(--icon-size); height: var(--icon-size); flex: none; }

.sidebar-footer { margin-top: auto; display: flex; flex-direction: column; gap: var(--space-2); }

/* การ์ดคู่มือท้ายแถบข้าง — จุดเดียวที่พาผู้ใช้ใหม่ไปหาวิธีใช้งานได้โดยไม่ต้องถาม */
.sidebar-card {
    display: block;
    background: var(--color-primary-soft);
    border: var(--border-width) solid var(--color-primary-border);
    border-radius: var(--radius-lg);
    padding: var(--space-3);
    color: var(--color-text);
}

.sidebar-card:hover { text-decoration: none; color: var(--color-text); }

.sidebar-card-title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-bold);
    color: var(--color-primary-strong);
    margin-bottom: var(--space-1);
}

.sidebar-card-title .icon { width: var(--icon-size); height: var(--icon-size); flex: none; }

.sidebar-card-text {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted-on-soft);
    margin: 0 0 var(--space-3);
    line-height: var(--line-height-base);
}

/* ---- โหมดย่อแถบข้างบนจอใหญ่ (ปุ่มเดียวกับที่เปิด drawer บนมือถือ) ---- */
.app.is-rail { grid-template-columns: var(--sidebar-width-collapsed) minmax(0, 1fr); }

.app.is-rail .sidebar { padding-left: var(--space-2); padding-right: var(--space-2); align-items: stretch; }
.app.is-rail .sidebar-brand { justify-content: center; padding: 0; }
.app.is-rail .sidebar-brand > span:not(.sidebar-brand-mark) { display: none; }
.app.is-rail .sidebar-link { justify-content: center; padding-left: var(--space-2); }
.app.is-rail .sidebar-link > span { display: none; }
.app.is-rail .sidebar-link::before { display: none; }
.app.is-rail .sidebar-section-title,
.app.is-rail .sidebar-card-title span,
.app.is-rail .sidebar-card-text,
.app.is-rail .sidebar-card .btn span { display: none; }
.app.is-rail .sidebar-card { padding: var(--space-2); text-align: center; }
.app.is-rail .sidebar-card-title { justify-content: center; margin: 0; }

.main { display: flex; flex-direction: column; min-width: 0; }

.topbar {
    height: var(--topbar-height);
    background: var(--color-surface);
    border-bottom: var(--border-width) solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: 0 var(--space-4);
    position: sticky;
    top: 0;
    z-index: 20;
}

.topbar-left { display: flex; align-items: center; gap: var(--space-3); min-width: 0; flex: 1 1 auto; }

/* ป้ายบอกโซนบนแถบบนของทีมงานแพลตฟอร์ม — ลูกค้าไม่มีป้ายนี้ */
.topbar-context {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--color-text-muted-on-soft);
    min-width: 0;
}

/* ห้าม wrap เด็ดขาด — ถ้า wrap บนจอแคบ แถบภาษาจะถูกดันขึ้นไปพ้นขอบจอด้านบน */
.topbar-right { display: flex; align-items: center; gap: var(--space-2); flex-wrap: nowrap; min-width: 0; }

.content {
    /* เว้นท้ายหน้าไว้ให้ปุ่มแจ้งปัญหาแบบลอย ไม่ทับปุ่มหรือฟอร์มบรรทัดสุดท้าย */
    padding: var(--space-4) var(--space-4) var(--space-7);
    width: 100%;
    max-width: var(--content-max);
    margin: 0 auto;
    flex: 1 1 auto;
}

.content-narrow { max-width: 720px; }

/* --------------------------------------------------------- page header */

.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
    margin-bottom: var(--space-4);
}

.page-header h1 { margin-bottom: var(--space-1); }

.page-header-description { color: var(--color-text-muted); margin: 0; }

.page-header-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }

.breadcrumb {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    list-style: none;
    padding: 0;
    margin: 0 0 var(--space-2);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    flex-wrap: wrap;
}

.breadcrumb li::after { content: "/"; margin-left: var(--space-2); color: var(--color-border-strong); }
.breadcrumb li:last-child::after { content: ""; }

/* ---------------------------------------------------------------- card */

.card {
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
}

.card + .card { margin-top: var(--space-4); }

.card-header {
    padding: var(--space-3) var(--space-4);
    border-bottom: var(--border-width) solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.card-header h2,
.card-header h3 { margin: 0; font-size: var(--font-size-base); }

.card-body { padding: var(--space-4); }
.card-body-tight { padding: var(--space-3); }

.card-footer {
    padding: var(--space-3) var(--space-4);
    border-top: var(--border-width) solid var(--color-border);
    background: var(--color-surface-muted);
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.section-title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-bold);
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--color-text-muted);
    margin-bottom: var(--space-2);
}

/* ------------------------------------------------------------ KPI card */

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: var(--space-3);
}

/* ‼️ ชิปไอคอนอยู่ซ้าย ตัวเลขอยู่ขวา ตาม Visual Standard ที่อนุมัติ
   การ์ดทุกใบพื้นขาวเหมือนกัน ต่างกันแค่โทนของชิปไอคอน (design.md ข้อ 5.3) */
.kpi {
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--space-3) var(--space-4);
    box-shadow: var(--shadow-card);
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    min-width: 0;
}

.kpi-body { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; flex: 1 1 auto; }

.kpi-label {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

.kpi-value {
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-bold);
    line-height: var(--line-height-tight);
    font-variant-numeric: tabular-nums;
}

/* ‼️ ค่าที่เป็นข้อความ (เช่น "ต้องดำเนินการ") ยาวกว่าตัวเลขมาก
      ถ้าปล่อยขนาดเดิมจะตัดสองบรรทัดจนการ์ดสูงไม่เท่ากันทั้งแถว
      เจอจากภาพหน้าจอจริง 2026-08-27
      ‼️ ลดขนาดเฉพาะค่าที่เป็นคำ ไม่แตะค่าที่เป็นตัวเลข
         เพราะตัวเลขคือสิ่งที่คนกวาดตาหาก่อน ต้องใหญ่ไว้เหมือนเดิม */
.kpi-value.is-text {
    font-size: var(--font-size-lg);
    line-height: var(--line-height-snug);
}
.kpi-meta { font-size: var(--font-size-sm); color: var(--color-text-muted); }

.kpi-icon {
    width: var(--space-6);
    height: var(--space-6);
    border-radius: var(--radius-lg);
    background: var(--tint-brand-bg);
    color: var(--tint-brand-fg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
}

.kpi-icon .icon { width: var(--space-4); height: var(--space-4); }

/* โทนชิปไอคอน — ใช้ได้กับ .kpi-icon และ .tile-icon เท่านั้น */
.tint-brand  { background: var(--tint-brand-bg);  color: var(--tint-brand-fg); }
.tint-green  { background: var(--tint-green-bg);  color: var(--tint-green-fg); }
.tint-violet { background: var(--tint-violet-bg); color: var(--tint-violet-fg); }
.tint-blue   { background: var(--tint-blue-bg);   color: var(--tint-blue-fg); }
.tint-slate  { background: var(--tint-slate-bg);  color: var(--tint-slate-fg); }

/* ค่าเปลี่ยนแปลงเทียบช่วงก่อนหน้า — แสดงเฉพาะเมื่อมีข้อมูลช่วงก่อนหน้าจริง */
.kpi-delta { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--font-size-sm); }
.kpi-delta .icon { width: var(--font-size-sm); height: var(--font-size-sm); }
.kpi-delta.is-up { color: var(--color-success); }
.kpi-delta.is-down { color: var(--color-danger); }
.kpi-delta.is-flat { color: var(--color-text-muted); }

/* -------------------------------------------------------------- button */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    height: var(--height-button);
    padding: 0 var(--space-3);
    border-radius: var(--radius-base);
    border: var(--border-width) solid transparent;
    background: var(--color-surface);
    color: var(--color-text);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}

.btn:hover { text-decoration: none; }

/* ‼️ นิยามของปุ่มหลักย้ายไปอยู่ท้ายไฟล์ในหมวดโหมดมืด เพราะต้องใช้ token ของตัวเอง */

.btn-secondary {
    background: var(--color-surface);
    border-color: var(--color-border-strong);
    color: var(--color-text);
}

.btn-secondary:hover { background: var(--color-surface-muted); border-color: var(--color-text-muted); color: var(--color-text); }

.btn-ghost { background: transparent; color: var(--color-text-muted); }
.btn-ghost:hover { background: var(--color-neutral-soft); color: var(--color-text); }

.btn-danger { background: var(--solid-danger-bg); border-color: var(--solid-danger-bg); color: var(--solid-danger-fg); }
.btn-danger:hover { background: var(--solid-danger-bg); border-color: var(--solid-danger-bg); filter: brightness(.92); color: var(--solid-danger-fg); }

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

.btn-sm { height: var(--space-5); padding: 0 var(--space-2); font-size: var(--font-size-xs); }
.btn-lg { height: var(--space-6); padding: 0 var(--space-4); font-size: var(--font-size-base); }
.btn-block { width: 100%; }

.btn[disabled],
.btn.is-disabled {
    background: var(--color-neutral-soft);
    border-color: var(--color-border);
    /* ปุ่มที่กดไม่ได้ก็ต้องอ่านออก — ผู้ใช้ต้องรู้ว่าปุ่มนี้คืออะไรจึงจะรู้ว่าต้องทำอะไรก่อน */
    color: var(--color-neutral);
    cursor: not-allowed;
    box-shadow: none;
}

.btn-icon { width: var(--height-button); padding: 0; }

.btn .icon { width: var(--icon-size); height: var(--icon-size); }

/* --------------------------------------------------------------- forms */

.form-grid { display: grid; gap: var(--space-3); }
.form-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.field { display: flex; flex-direction: column; gap: var(--space-1); }

.field-label {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text);
}

.field-required { color: var(--color-danger); margin-left: var(--space-1); }

.field-hint { font-size: var(--font-size-xs); color: var(--color-text-muted); }

.field-error { font-size: var(--font-size-xs); color: var(--color-danger); }

.input,
.select,
.textarea {
    width: 100%;
    min-height: var(--height-input);
    padding: 0 var(--space-2);
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-base);
    background: var(--color-surface);
    color: var(--color-text);
    font-family: inherit;
    font-size: var(--font-size-sm);
    transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.textarea { padding: var(--space-2); min-height: calc(var(--height-input) * 3); resize: vertical; line-height: var(--line-height-base); }

.input:hover,
.select:hover,
.textarea:hover { border-color: var(--color-text-muted); }

.input:focus,
.select:focus,
.textarea:focus {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-soft);
    outline: none;
}

.input[disabled],
.select[disabled],
.textarea[disabled] {
    background: var(--color-neutral-soft);
    color: var(--color-text-muted);
    cursor: not-allowed;
}

.input.has-error,
.select.has-error,
.textarea.has-error { border-color: var(--color-danger); }

.select { appearance: none; padding-right: var(--space-5); background-image: none; }

.checkbox,
.radio {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    font-size: var(--font-size-sm);
    cursor: pointer;
}

.checkbox input,
.radio input { margin-top: var(--space-1); accent-color: var(--color-primary); }

.form-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    padding-top: var(--space-3);
    border-top: var(--border-width) solid var(--color-border);
    margin-top: var(--space-4);
}

.input-group { display: flex; align-items: stretch; gap: var(--space-2); flex-wrap: wrap; }
.input-group > .input { flex: 1 1 200px; }

/* ‼️ ช่องกรอกที่มีป้ายกำกับของตัวเอง อยู่แถวเดียวกับปุ่มได้
   ต้องชิดล่างไม่ใช่ยืดเต็ม ไม่งั้นปุ่มจะสูงเท่าป้าย+ช่องรวมกัน */
.input-group-field { align-items: flex-end; }
.input-group-field > .field { flex: 1 1 200px; min-width: 0; }

.input-affix {
    display: inline-flex;
    align-items: center;
    padding: 0 var(--space-2);
    background: var(--color-surface-muted);
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-base);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    white-space: nowrap;
}

.color-input { width: var(--space-6); min-width: var(--space-6); padding: var(--space-1); height: var(--height-input); }

/* --------------------------------------------------------------- table */

/* ‼️ ต้องเป็น position: relative — ไม่งั้นลูกที่เป็น position:absolute (เช่น .visually-hidden ในหัวคอลัมน์)
   จะหลุดออกไปนอกกรอบที่เลื่อนได้ แล้วดันให้ทั้งหน้าเลื่อนแนวนอนตามไปด้วย
   (เจอจริงที่จอ 820px หน้ารายการเว็บไซต์ของทีมงาน: หน้าเลื่อนได้ 881px ทั้งที่จอกว้าง 798px) */
.table-wrap {
    position: relative;
    width: 100%;
    overflow-x: auto;
    border-radius: var(--radius-lg);
}

.table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--font-size-sm);
    background: var(--color-surface);
}

.table th,
.table td {
    padding: var(--space-2) var(--space-3);
    text-align: left;
    border-bottom: var(--border-width) solid var(--color-border);
    vertical-align: middle;
}

.table th {
    background: var(--color-surface);
    color: var(--color-text-muted-on-soft);
    font-weight: var(--font-weight-medium);
    font-size: var(--font-size-xs);
    letter-spacing: .02em;
    white-space: nowrap;
}

/* หัวคอลัมน์ที่กดเรียงลำดับได้ — ต้องเป็น <a> เพราะเปลี่ยน URL จริง (เรียงฝั่งเซิร์ฟเวอร์) */
.table th a {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: inherit;
}

.table th a:hover { color: var(--color-text); text-decoration: none; }
.table th a .icon { width: var(--font-size-sm); height: var(--font-size-sm); opacity: .55; }
.table th a.is-sorted { color: var(--color-primary-strong); }
.table th a.is-sorted .icon { opacity: 1; }

.table tbody tr { height: var(--height-row); }

.table tbody tr:hover { background: var(--color-surface-muted); }

.table tbody tr:last-child td { border-bottom: 0; }

.table .cell-numeric { text-align: right; font-variant-numeric: tabular-nums; }

.table .cell-actions { text-align: right; white-space: nowrap; }

.table-compact th,
.table-compact td { padding: var(--space-1) var(--space-2); }

/* --------------------------------------------------------------- badge */

.badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0 var(--space-2);
    height: var(--space-4);
    border-radius: var(--radius-pill);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    background: var(--color-neutral-soft);
    color: var(--color-neutral);
    white-space: nowrap;
}

.badge-success { background: var(--color-success-soft); color: var(--color-success); }
.badge-warning { background: var(--color-warning-soft); color: var(--color-warning); }
.badge-danger  { background: var(--color-danger-soft);  color: var(--color-danger); }
.badge-info    { background: var(--color-info-soft);    color: var(--color-info); }
.badge-primary { background: var(--color-primary-soft); color: var(--color-primary-strong); }

.badge-dot {
    width: var(--space-2);
    height: var(--space-2);
    border-radius: var(--radius-pill);
    background: currentColor;
    flex: none;
}

/* --------------------------------------------------------------- alert */

.alert {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3);
    border-radius: var(--radius-base);
    border: var(--border-width) solid transparent;
    font-size: var(--font-size-sm);
    margin-bottom: var(--space-3);
}

.alert-success { background: var(--color-success-soft); border-color: var(--color-success); color: var(--color-success); }
.alert-danger  { background: var(--color-danger-soft);  border-color: var(--color-danger);  color: var(--color-danger); }
.alert-warning { background: var(--color-warning-soft); border-color: var(--color-warning); color: var(--color-warning); }
.alert-info    { background: var(--color-info-soft);    border-color: var(--color-info);    color: var(--color-info); }

.toast-stack {
    position: fixed;
    right: var(--space-4);
    bottom: var(--space-4);
    z-index: 80;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    max-width: 360px;
}

.toast {
    background: var(--color-surface);
    border-left: var(--space-1) solid var(--color-primary);
    box-shadow: var(--shadow-lg);
    border-radius: var(--radius-base);
    padding: var(--space-3);
    font-size: var(--font-size-sm);
}

.toast-success { border-left-color: var(--color-success); }
.toast-danger  { border-left-color: var(--color-danger); }
.toast-info    { border-left-color: var(--color-info); }

/* --------------------------------------------------- empty / loading state */

.empty-state {
    text-align: center;
    padding: var(--space-6) var(--space-4);
    color: var(--color-text-muted);
}

.empty-state-icon {
    width: var(--space-7);
    height: var(--space-7);
    border-radius: var(--radius-pill);
    background: var(--color-neutral-soft);
    color: var(--color-text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-bottom: var(--space-3);
}

.empty-state h3 { color: var(--color-text); }

.loading-state {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-5);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
}

.spinner {
    width: var(--space-4);
    height: var(--space-4);
    border: 2px solid var(--color-border);
    border-top-color: var(--color-primary);
    border-radius: var(--radius-pill);
    animation: spin 700ms linear infinite;
    flex: none;
}

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

@media (prefers-reduced-motion: reduce) {
    * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ---------------------------------------------------------- pagination */

.pagination {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    flex-wrap: wrap;
    list-style: none;
    padding: 0;
    margin: 0;
}

.pagination a,
.pagination span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--space-5);
    height: var(--space-5);
    padding: 0 var(--space-2);
    border-radius: var(--radius-base);
    border: var(--border-width) solid var(--color-border);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: var(--font-size-sm);
}

.pagination a:hover { background: var(--color-surface-muted); text-decoration: none; }

.pagination .is-current {
    background: var(--btn-primary-bg);
    border-color: var(--btn-primary-bg);
    color: var(--btn-primary-fg);
    font-weight: var(--font-weight-medium);
}

.pagination .is-disabled { color: var(--color-text-muted); background: var(--color-surface-muted); }

.list-toolbar {
    display: flex;
    align-items: flex-end;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-bottom: var(--space-3);
}

.list-toolbar .field { min-width: 160px; }

.list-summary {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    margin-top: var(--space-3);
}

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

.modal-backdrop {
    position: fixed;
    inset: 0;
    background: var(--color-backdrop);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-3);
    z-index: 90;
}

.modal-backdrop[hidden] { display: none; }

.modal {
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    width: 100%;
    max-width: 560px;
    max-height: 90vh;
    overflow-y: auto;
}

.modal-lg { max-width: 860px; }

.modal-header {
    padding: var(--space-3) var(--space-4);
    border-bottom: var(--border-width) solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}

.modal-header h2 { margin: 0; font-size: var(--font-size-lg); }

.modal-body { padding: var(--space-4); }

.modal-footer {
    padding: var(--space-3) var(--space-4);
    border-top: var(--border-width) solid var(--color-border);
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.drawer {
    position: fixed;
    top: 0;
    right: 0;
    height: 100vh;
    width: min(480px, 100%);
    background: var(--color-surface);
    box-shadow: var(--shadow-lg);
    z-index: 90;
    display: flex;
    flex-direction: column;
}

.drawer[hidden] { display: none; }

/* ----------------------------------------------------- support button */

.support-fab {
    position: fixed;
    right: var(--space-4);
    bottom: var(--space-4);
    z-index: 70;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: var(--space-6);
    padding: 0 var(--space-3);
    border-radius: var(--radius-pill);
    background: var(--color-secondary);
    color: var(--color-text-inverse);
    border: 0;
    box-shadow: var(--shadow-lg);
    cursor: pointer;
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
}

.support-fab:hover { background: var(--btn-primary-bg); color: var(--btn-primary-fg); }

.support-type-list { display: grid; gap: var(--space-2); }

.support-type {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-3);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    background: var(--color-surface);
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    font-size: var(--font-size-sm);
    width: 100%;
    transition: border-color var(--transition-base), background var(--transition-base);
}

.support-type:hover { border-color: var(--color-primary); background: var(--color-primary-soft); }

.support-type-title { font-weight: var(--font-weight-medium); color: var(--color-text); }

.support-type-hint { color: var(--color-text-muted); font-size: var(--font-size-xs); }

/* ---------------------------------------------------------------- tabs */

.tabs {
    display: flex;
    gap: var(--space-1);
    border-bottom: var(--border-width) solid var(--color-border);
    margin-bottom: var(--space-4);
    overflow-x: auto;
}

.tab {
    padding: var(--space-2) var(--space-3);
    border-bottom: 2px solid transparent;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    white-space: nowrap;
}

.tab:hover { color: var(--color-text); text-decoration: none; }

.tab.is-active {
    color: var(--color-primary-strong);
    border-bottom-color: var(--color-primary);
    font-weight: var(--font-weight-medium);
}

/* --------------------------------------------------------------- steps */

.steps {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-bottom: var(--space-4);
}

.step {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.step-number {
    width: var(--space-5);
    height: var(--space-5);
    border-radius: var(--radius-pill);
    background: var(--color-neutral-soft);
    color: var(--color-text-muted-on-soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: var(--font-weight-medium);
    flex: none;
}

.step.is-active { color: var(--color-text); font-weight: var(--font-weight-medium); }
.step.is-active .step-number { background: var(--btn-primary-bg); color: var(--btn-primary-fg); }
.step.is-done .step-number { background: var(--color-success-soft); color: var(--color-success); }

.step-divider { flex: 1 1 var(--space-5); height: var(--border-width); background: var(--color-border); min-width: var(--space-4); }

/* ------------------------------------------------------ choice / option */

.choice-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--space-3);
}

.choice {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-3);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    background: var(--color-surface);
    cursor: pointer;
    transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.choice:hover { border-color: var(--color-primary); }

.choice input { position: absolute; opacity: 0; pointer-events: none; }

.choice.is-selected,
.choice:has(input:checked) {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-soft);
}

.choice-title { font-weight: var(--font-weight-medium); }
.choice-hint { font-size: var(--font-size-xs); color: var(--color-text-muted); }

/* ---------------------------------------------- การ์ดแม่แบบ (ภาพเป็นพระเอก)

   ‼️ ภาพในการ์ดคือ "ภาพหน้าจอจริง" ของเว็บที่สร้างจากแม่แบบนั้น
      (สร้างด้วย scripts/build-template-previews.php) จึงตรงกับสิ่งที่ผู้ใช้จะได้เสมอ
   ‼️ การ์ดต้องใหญ่พอให้ดูออกว่าเป็นธุรกิจอะไรโดยไม่ต้องอ่านตัวหนังสือ
      ของเดิมกว้าง 260px และครอบ 4:3 ทำให้เห็นแค่หัวเว็บ อ่านไม่ออกว่าเป็นแม่แบบของอะไร */

.template-card { padding: 0; overflow: hidden; }

.template-grid { grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: var(--space-4); }

/* กรอบเบราว์เซอร์จำลอง — วาดด้วย CSS ล้วน ไม่มีไฟล์ภาพเพิ่ม */
.template-frame { display: block; border-bottom: var(--border-width) solid var(--color-border); }

.template-frame-bar {
    display: flex;
    align-items: center;
    gap: 5px;
    height: 26px;
    padding: 0 var(--space-2);
    background: var(--color-surface-muted);
    border-bottom: var(--border-width) solid var(--color-border);
}

.template-frame-bar > span {
    width: 7px;
    height: 7px;
    border-radius: var(--radius-pill);
    background: var(--color-border-strong);
    flex: none;
}

.template-frame-address {
    flex: 1 1 auto;
    height: 10px;
    margin-left: var(--space-2);
    border-radius: var(--radius-pill);
    background: var(--color-border);
}

.template-preview {
    aspect-ratio: 3 / 2;
    background: var(--color-secondary-soft);
    display: block;
    overflow: hidden;
}

.template-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;
    display: block;
    transition: transform var(--transition-base);
}

.template-card:hover .template-preview img { transform: scale(1.02); }

/* ‼️ ข้อความใต้ภาพต้องสั้น — ภาพคือสิ่งที่บอกว่าเป็นแม่แบบของธุรกิจอะไร */
.template-card .choice-body {
    padding: var(--space-3);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.template-card .choice-hint {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

@media (max-width: 600px) {
    .template-grid { grid-template-columns: 1fr; }
}

/* ------------------------------------------- ขั้นตอนแนะนำ (setup progress)

   ‼️ สถานะทุกขั้นมาจากข้อมูลจริง (SetupProgressService) แผงนี้จึงหายไปเองเมื่อครบ
      ห้ามทำให้ดู "เกือบเสร็จ" ด้วยการนับขั้นที่ระบบทำให้เองเป็นผลงานของผู้ใช้ */

/* ‼️ ข้อความต้องใช้ --color-primary-strong เสมอ — สีแบรนด์บนพื้นขาวได้ contrast แค่ 3.58:1
   ซึ่งไม่ผ่าน WCAG AA (ดูหมายเหตุที่ตัวแปรสีด้านบนของไฟล์) */
.setup-percent {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-bold);
    color: var(--color-primary-strong);
    flex: none;
}

.setup-bar {
    height: 8px;
    border-radius: var(--radius-pill);
    background: var(--color-neutral-soft);
    overflow: hidden;
}

.setup-bar-fill {
    display: block;
    height: 100%;
    width: var(--setup-percent, 0%);
    border-radius: var(--radius-pill);
    background: var(--color-primary);
    transition: width var(--transition-base);
}

.setup-steps {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: var(--space-2);
    list-style: none;
    margin: 0;
    padding: 0;
    counter-reset: none;
}

.setup-step a {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2);
    border-radius: var(--radius-base);
    text-align: center;
    text-decoration: none;
    color: var(--color-text-muted);
    transition: background var(--transition-base);
}

.setup-step a:hover { background: var(--color-surface-muted); }

.setup-step-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-5);
    height: var(--space-5);
    border-radius: var(--radius-pill);
    border: var(--border-width) solid var(--color-border-strong);
    background: var(--color-surface);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    flex: none;
}

.setup-step-label { font-size: var(--font-size-sm); }

.setup-step.is-done a { color: var(--color-text); }

.setup-step.is-done .setup-step-mark {
    background: var(--color-success-soft);
    border-color: var(--color-success);
    color: var(--color-success);
}

/* ------------------------------------------------- หน้าเปิดใช้เว็บไซต์ */

.launch-pages { list-style: none; margin: 0; padding: 0; }

.launch-page {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-top: var(--border-width) solid var(--color-border);
}

.launch-page-check { display: inline-flex; color: var(--color-success); flex: none; }

.launch-page-name {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

.launch-live {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3);
    border-radius: var(--radius-base);
    background: var(--color-success-soft);
    color: var(--color-success);
}

.launch-live-icon { display: inline-flex; flex: none; }

.launch-url {
    display: block;
    padding: var(--space-2) var(--space-3);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    background: var(--color-surface-muted);
    word-break: break-all;
    font-size: var(--font-size-sm);
}

.button-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* -------------------------------------------------------- editor layout */

.editor {
    display: grid;
    grid-template-columns: 320px minmax(0, 1fr);
    gap: var(--space-4);
    align-items: start;
}

.editor-panel {
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    position: sticky;
    top: calc(var(--topbar-height) + var(--space-3));
    max-height: calc(100vh - var(--topbar-height) - var(--space-5));
    overflow-y: auto;
}

.editor-canvas {
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    min-width: 0;
}

.section-list { display: flex; flex-direction: column; }

.section-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-bottom: var(--border-width) solid var(--color-border);
}

.section-item:last-child { border-bottom: 0; }

.section-item.is-hidden { background: var(--color-surface-muted); color: var(--color-text-muted); }

.section-item-title { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); }

.section-item-type { font-size: var(--font-size-xs); color: var(--color-text-muted); }

.section-item-actions { display: flex; align-items: center; gap: var(--space-1); }

.preview-frame {
    width: 100%;
    height: 70vh;
    border: 0;
    display: block;
    background: var(--color-surface);
}

.preview-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-bottom: var(--border-width) solid var(--color-border);
    background: var(--color-surface-muted);
    flex-wrap: wrap;
}

.preview-frame.is-mobile { max-width: 420px; margin: 0 auto; border-left: var(--border-width) solid var(--color-border); border-right: var(--border-width) solid var(--color-border); }

/* --------------------------------------------------------- media grid */

.media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: var(--space-3);
}

.media-item {
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    overflow: hidden;
    background: var(--color-surface);
    display: flex;
    flex-direction: column;
}

.media-thumb {
    aspect-ratio: 4 / 3;
    background: var(--color-neutral-soft);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.media-thumb img { width: 100%; height: 100%; object-fit: cover; }

.media-meta { padding: var(--space-2); font-size: var(--font-size-xs); color: var(--color-text-muted); display: flex; flex-direction: column; gap: var(--space-1); }

/* --------------------------------------------------------- auth layout */

/* ‼️ หน้าที่ยังไม่ล็อกอินทั้งชุดใช้กฎด้านล่างนี้ร่วมกัน — สมัคร / เข้าสู่ระบบ / ลืมรหัสผ่าน /
   ตั้งรหัสผ่านใหม่ เปิดติดกันแล้วต้องรู้ว่าเป็นชุดเดียวกัน ห้ามมีกฎเฉพาะหน้าใดหน้าหนึ่ง */

/* ‼️ พื้นหลังเป็นครีมอุ่น ไม่ใช่พื้นกรมท่าทึบแบบเดิม (Visual Standard 2026-08-23)
   เหตุผลเดียวกับแถบข้างของระบบจัดการ: กรมท่าเต็มครึ่งจอกินสัดส่วนสีเกิน 30%
   ตอนนี้กรมท่าย้ายไปอยู่ที่ตัวอักษรพาดหัวซึ่งเป็นจุดที่ต้องการน้ำหนักจริง */
.auth-body { background: var(--color-surface); }

.auth-shell {
    /* ‼️ dvh ไม่ใช่ vh — บนมือถือ vh นับรวมแถบที่อยู่ของเบราว์เซอร์ ทำให้ฟอร์มถูกดันตกจอ
       min-height ไม่ใช่ height เพื่อให้ยังเลื่อนได้เองเมื่อมี error หรือจอเตี้ยกว่ามาตรฐาน */
    min-height: 100dvh;
    display: grid;
    /* 43 / 57 ตามสัดส่วนที่อนุมัติ — แผงแบรนด์แคบกว่า ฟอร์มได้พื้นที่มากกว่า */
    grid-template-columns: minmax(0, 43fr) minmax(0, 57fr);
}

/* ------------------------------------------------- แผงแบรนด์ (ฝั่งซ้าย) */

.auth-aside {
    position: relative;
    overflow: hidden;
    background: var(--auth-aside-bg);
    color: var(--color-text);
    padding: var(--space-5) var(--space-6) 0;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--space-4);
    border-right: var(--border-width) solid var(--color-border);
}

/* วงกลมนวลมุมบนขวาให้พื้นครีมไม่แบนเป็นแผ่นเดียว — วาดด้วย gradient ไม่ใช้ไฟล์ภาพ */
.auth-aside::before {
    content: "";
    position: absolute;
    inset: -34% -26% auto auto;
    width: 66%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: var(--auth-aside-glow);
    pointer-events: none;
}

/* ส่วนโค้งกรมท่ามุมล่างซ้าย — จุดเดียวที่สีรองของแบรนด์ยังเป็นพื้นที่ใหญ่ */
.auth-aside::after {
    content: "";
    position: absolute;
    left: -18%;
    bottom: -26%;
    width: 46%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: var(--color-secondary);
    opacity: .9;
    pointer-events: none;
}

.auth-aside-top {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    max-width: 30rem;
}

.auth-brand { display: inline-flex; align-items: center; gap: var(--space-2); color: inherit; text-decoration: none; }

.auth-brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius-base);
    /* ‼️ ตัวอักษรขาวบน --color-primary ได้ 3.58:1 ไม่ผ่าน AA — ต้องใช้ตัวเข้ม (design.md ข้อ 3.8) */
    background: var(--btn-primary-bg);
    color: var(--btn-primary-fg);
    font-weight: var(--font-weight-bold);
    font-size: var(--font-size-sm);
    letter-spacing: .02em;
}

.auth-brand-name { font-size: var(--font-size-lg); font-weight: var(--font-weight-bold); }

.auth-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    align-self: flex-start;
    margin: 0;
    padding: var(--space-2) var(--space-3);
    border: var(--border-width) solid var(--color-primary-border);
    border-radius: var(--radius-pill);
    background: var(--color-surface);
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-sm);
    box-shadow: var(--shadow-sm);
}

.auth-badge .icon { color: var(--color-primary-strong); flex: none; }

.auth-headline {
    margin: 0;
    color: var(--color-secondary-text);
    font-size: var(--font-size-3xl);
    line-height: 1.25;
    /* ‼️ ภาษาไทยไม่มีช่องว่างระหว่างคำ เบราว์เซอร์จึงตัดบรรทัดตรงไหนก็ได้
       และมักเหลือคำสั้นๆ ค้างบรรทัดสุดท้ายคำเดียว (เช่น "ได้") ซึ่งอ่านแล้วสะดุด
       balance เกลี่ยความยาวของทุกบรรทัดให้ใกล้กัน · เบราว์เซอร์ที่ไม่รองรับก็ตัดแบบเดิม */
    text-wrap: balance;
}

/* ‼️ คำที่เน้นในพาดหัวใช้สีหลักของแบรนด์ ไม่ใช่สีใหม่นอกชุด
   และห้ามตัดคำกลางคำเน้น — ภาษาไทยไม่มีช่องว่างระหว่างคำ เบราว์เซอร์จึงตัดตรงไหนก็ได้
   ปล่อยไว้จะได้ "น่าเชื่อ / ถือ" คร่อมสองบรรทัดซึ่งอ่านแล้วสะดุด */
.auth-accent { color: var(--color-primary-strong); white-space: nowrap; }

.auth-subtitle { margin: 0; color: var(--color-text-muted-on-soft); max-width: 26rem; }

.auth-features {
    list-style: none;
    margin: var(--space-1) 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.auth-features li { display: flex; align-items: flex-start; gap: var(--space-3); }

.auth-feature-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius-base);
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    color: var(--color-primary-strong);
    box-shadow: var(--shadow-sm);
}

.auth-feature-text { display: flex; flex-direction: column; gap: 2px; }

.auth-feature-title { font-weight: var(--font-weight-bold); font-size: var(--font-size-sm); color: var(--color-secondary-text); }

.auth-feature-hint { color: var(--color-text-muted-on-soft); font-size: var(--font-size-xs); }

/* ‼️ ภาพเป็นภาพผลิตภัณฑ์จริงของระบบ (ตัวสร้างเว็บ + มุมมองมือถือ + รายงานผู้เข้าชม)
   ห้ามใช้ข้อมูลลูกค้าจริงในภาพ — ทุกตัวเลขในภาพเป็นค่าสมมุติที่วาดไว้ในไฟล์ภาพเอง
   ‼️ ต้องมี width/height เสมอ ไม่งั้นหน้าจะกระตุกตอนภาพโหลดเสร็จ */
.auth-artwork {
    position: relative;
    z-index: 1;
    display: block;
    width: 100%;
    max-width: 34rem;
    height: auto;
    margin: 0 auto;
}

/* ------------------------------------------------------- ฟอร์ม (ฝั่งขวา) */

.auth-main {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--space-3) var(--space-4) var(--space-5);
    background: var(--color-surface);
}

.auth-topbar { width: 100%; display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); }

/* ‼️ การ์ดต้องไม่มี scroll ของตัวเอง — ถ้าเนื้อหาสูงเกิน ให้ทั้งหน้าเลื่อนแทน
   (ผู้ใช้ที่เลื่อนในการ์ดจะมองไม่เห็นว่ายังมีช่องเหลืออยู่ข้างล่าง) */
.auth-card {
    width: 100%;
    max-width: 28rem;
    margin: auto 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-5);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-xl);
    background: var(--color-surface);
    box-shadow: var(--shadow-lg);
    overflow: visible;
}

/* ‼️ ช่องกรอกของหน้าที่ยังไม่ล็อกอินสูงกว่าในระบบจัดการ (46px) ตามมาตรฐานที่อนุมัติ
   คุมด้วย token ตัวเดียว ไม่ได้ไล่ตั้งค่าทีละหน้า */
.auth-card .input,
.auth-card .select { min-height: var(--height-input-auth); height: var(--height-input-auth); }
.auth-card .btn-lg { height: var(--height-input-auth); }
.auth-card .field { gap: var(--space-1); }
.auth-card .input-affix .input { padding-left: 2.75rem; }

/* ฟอร์มสมัครใช้งานจับคู่ช่องรหัสผ่านไว้แถวเดียวกันบนจอกว้าง — มือถือเรียงเดี่ยวเอง */
.auth-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }

.auth-head { display: flex; flex-direction: column; gap: var(--space-2); }

.auth-head-center { align-items: center; text-align: center; }

.auth-card-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-base);
    /* ‼️ เหตุผลเดียวกับ .auth-brand-mark — ตัวอักษรบนสีแบรนด์ต้องใช้ตัวเข้ม */
    background: var(--btn-primary-bg);
    color: var(--btn-primary-fg);
    font-weight: var(--font-weight-bold);
}

.auth-card-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 50%;
    background: var(--color-primary-soft);
    color: var(--color-primary);
}

.auth-title { margin: 0; font-size: var(--font-size-2xl); }

.auth-lead { margin: 0; color: var(--color-text-muted); font-size: var(--font-size-sm); }

.auth-row-end { display: flex; justify-content: flex-end; font-size: var(--font-size-sm); }

.auth-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin: 0;
    padding: var(--space-3);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    background: var(--color-surface-muted);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
}

.auth-note-icon { display: inline-flex; flex: 0 0 auto; color: var(--color-info); }

.auth-foot { text-align: center; font-size: var(--font-size-sm); color: var(--color-text-muted); }

.auth-foot a { display: inline-flex; align-items: center; gap: var(--space-1); font-weight: var(--font-weight-bold); }

.auth-links { display: flex; justify-content: space-between; gap: var(--space-2); font-size: var(--font-size-sm); flex-wrap: wrap; }

/* ------------------------------- ช่องกรอกที่มีไอคอนนำหน้าและปุ่มดูรหัสผ่าน */

.input-affix { position: relative; display: block; }

.input-affix .input { padding-left: 2.75rem; }

.input-affix .input[type="password"],
.input-affix .input.has-reveal { padding-right: 2.75rem; }

.input-icon {
    position: absolute;
    top: 50%;
    left: var(--space-3);
    transform: translateY(-50%);
    display: inline-flex;
    color: var(--color-text-muted);
    pointer-events: none;
}

.input-reveal {
    position: absolute;
    top: 50%;
    right: var(--space-2);
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* ‼️ 2.25rem = 36px ผ่านเกณฑ์เป้าสัมผัสขั้นต่ำ 24px ของ WCAG 2.2 AA */
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 0;
    border-radius: var(--radius-base);
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
}

.input-reveal:hover { color: var(--color-text); }

/* -------------------------------------- แถบความแข็งแรงของรหัสผ่าน */

/* ‼️ ซ่อนทั้งแถบจนกว่าจะเริ่มพิมพ์ — เส้นเทาลอยอยู่ใต้ช่องว่างๆ อ่านแล้วเหมือนเส้นขีดฆ่า
   JS เติม is-typing ให้เมื่อมีตัวอักษร (ปิด JS แล้วแถบนี้ไม่โผล่ ซึ่งถูกต้อง เพราะมันคำนวณด้วย JS) */
.pw-strength { display: none; flex-direction: column; gap: var(--space-1); }

.pw-strength.is-typing { display: flex; }

.pw-strength-track {
    display: block;
    height: .25rem;
    border-radius: var(--radius-pill);
    background: var(--color-border);
    overflow: hidden;
}

.pw-strength-bar {
    display: block;
    width: 0;
    height: 100%;
    border-radius: var(--radius-pill);
    background: var(--color-danger);
    transition: width .15s ease-out;
}

.pw-strength-bar.is-fair { background: var(--color-warning); }

.pw-strength-bar.is-strong { background: var(--color-success); }

.pw-strength-label { font-size: var(--font-size-xs); color: var(--color-text-muted); }

/* -------------------------------------------------------- manual pages */

.manual-layout { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: var(--space-4); align-items: start; }

.manual-article { line-height: var(--line-height-base); }

.manual-article h2 { font-size: var(--font-size-lg); margin-top: var(--space-4); }

.manual-article ol,
.manual-article ul { padding-left: var(--space-4); display: flex; flex-direction: column; gap: var(--space-1); }

.manual-article figure { margin: var(--space-3) 0; }

.manual-article figcaption { font-size: var(--font-size-sm); color: var(--color-text-muted); margin-top: var(--space-1); }

.manual-article img { border: var(--border-width) solid var(--color-border); border-radius: var(--radius-base); }

/* --------------------------------------------------------- misc blocks */

/* ‼️ ตารางนิยามเคยเป็น grid คอลัมน์ตายตัว (คอลัมน์แรกกว้างได้ถึง 200px)
   ปัญหาคือ grid ไม่ยอมย่อคอลัมน์แรกให้เล็กกว่าค่าที่ขอ พอกล่องแคบมาก
   คอลัมน์ค่าจึงเหลือ 0 แล้วป้ายสถานะข้างในดันล้นออกนอกการ์ด
   เจอจริงที่จอ 1024px: หักแถบข้าง 248px เหลือเนื้อที่ 754px การ์ดคอลัมน์ขวา
   จึงกว้างแค่ ~227px ล้นออกไป 6px — จอ 1440/820/390 ไม่เจอเพราะกว้างพอ
   หรือแคบพอจนกฎ 992px สั่งซ้อนบรรทัดไปแล้ว
   ‼️ ใช้ flex-wrap แทน เพราะมันวัดจาก "พื้นที่จริงของกล่อง" ไม่ใช่ความกว้างจอ
      กว้างพอ = หัวข้อกับค่าอยู่บรรทัดเดียวกันเหมือนเดิม
      แคบเกิน = ตัดบรรทัดเองอัตโนมัติ ไม่ต้องพึ่ง media query */
/* ‼️ เปลี่ยนจาก flex-wrap เป็น grid สองคอลัมน์ "หัวข้อ | ค่า" หนึ่งคู่ต่อหนึ่งแถว
   เหตุผล: flex-wrap ยัดหลายคู่ในบรรทัดเดียวเมื่อกล่องกว้าง แล้วอ่านไม่ออกว่าค่าไหนคู่กับหัวข้อไหน
           (เจอจริงที่หน้าเครื่องมือระบบ: "29 ตัวในซอร์ส" ไปอยู่ใต้หัวข้อ "สภาพแวดล้อม")
   ‼️ คอลัมน์ค่าเป็น minmax(0, 1fr) จึงหดได้จนสุด — ไม่กลับไปเป็นบั๊กล้นกรอบที่ 1024px แบบ grid เดิม */
.definition-list {
    display: grid;
    grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
    gap: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    margin: 0;
}

.definition-list dt { min-width: 0; color: var(--color-text-muted); }
.definition-list dd { min-width: 0; margin: 0; word-break: break-word; }

/* ‼️ ตัวแปรของ .code-block สำหรับคำสั่งที่คนต้อง "คัดลอกไปวาง"
      ตัวหลักใช้ overflow-x: auto ซึ่งถูกสำหรับโค้ดที่แค่อ่าน
      แต่คำสั่ง cron ที่ยาวกว่าจอ จะถูกตัดที่ขอบจนคนไม่รู้ว่ายังมีต่อ
      แล้วคัดลอกไปไม่ครบ · เจอจากภาพหน้าจอจริง 2026-08-27
   ‼️ ตัดคำที่ตำแหน่งไหนก็ได้ เพราะ path กับ argument ไม่มีช่องว่างให้ตัด */
.code-block--wrap {
    white-space: pre-wrap;
    word-break: break-all;
    overflow-x: visible;
}

.code-block {
    background: var(--color-secondary);
    color: var(--color-text-inverse);
    padding: var(--space-3);
    border-radius: var(--radius-base);
    font-family: var(--font-family-mono);
    font-size: var(--font-size-sm);
    overflow-x: auto;
    white-space: pre;
}

.progress {
    height: var(--space-2);
    background: var(--color-neutral-soft);
    border-radius: var(--radius-pill);
    overflow: hidden;
}

.progress-bar { height: 100%; width: var(--progress, 0%); background: var(--color-primary); }

.progress-bar.is-success { background: var(--color-success); }
.progress-bar.is-warning { background: var(--color-warning); }
.progress-bar.is-danger { background: var(--color-danger); }

.avatar {
    width: var(--space-5);
    height: var(--space-5);
    border-radius: var(--radius-pill);
    background: var(--color-primary-soft);
    color: var(--color-primary-strong);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-bold);
    flex: none;
}

.lang-switch { display: inline-flex; gap: var(--space-1); background: var(--color-neutral-soft); padding: var(--space-1); border-radius: var(--radius-pill); }

.lang-switch a {
    padding: 0 var(--space-2);
    height: var(--space-4);
    display: inline-flex;
    align-items: center;
    border-radius: var(--radius-pill);
    font-size: var(--font-size-xs);
    color: var(--color-neutral);   /* ต้องอ่านออกบนพื้น --color-neutral-soft ของตัวสลับภาษา */
}

.lang-switch a:hover { text-decoration: none; color: var(--color-text); }

.lang-switch a.is-active { background: var(--color-surface); color: var(--color-text); font-weight: var(--font-weight-medium); box-shadow: var(--shadow-sm); }

.org-switch { display: flex; align-items: center; gap: var(--space-2); }

.menu-dropdown { position: relative; }

.menu-dropdown-panel {
    position: absolute;
    right: 0;
    top: calc(100% + var(--space-1));
    min-width: 220px;
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    box-shadow: var(--shadow-lg);
    padding: var(--space-1);
    z-index: 30;
}

.menu-dropdown-panel[hidden] { display: none; }

.menu-dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-sm);
    color: var(--color-text);
    width: 100%;
    background: none;
    border: 0;
    font-family: inherit;
    cursor: pointer;
    text-align: left;
}

.menu-dropdown-item:hover { background: var(--color-surface-muted); text-decoration: none; }

.error-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    text-align: center;
}

.error-code { font-size: var(--font-size-2xl); color: var(--color-primary); font-weight: var(--font-weight-bold); }

.reference-code {
    /* ‼️ ต้องกำหนดสีตัวอักษรเอง ห้ามรับทอดจากพ่อแม่
          กล่องนี้มีพื้นเป็น --color-neutral-soft ซึ่งเข้มกว่าพื้นการ์ด
          ถ้าอยู่ใน .text-muted จะกลายเป็นเทาบนเทา = 4.32:1 ไม่ผ่าน WCAG AA (ต้อง 4.5)
          พบด้วย check-screens.php ที่หน้าเครื่องมือระบบ 2026-08-27 · ตอนนี้ได้ 13.9:1
          ‼️ เป็นรหัสอ้างอิงที่คนต้องอ่านแล้วเทียบทีละตัวอักษร จางไม่ได้ตั้งแต่ต้น */
    color: var(--color-text);
    display: inline-block;
    font-family: var(--font-family-mono);
    background: var(--color-neutral-soft);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
}

/* ‼️ ปุ่มสองใบที่อยู่คู่กันในช่องตาราง — ต้องอ่านครบทั้งคำเหมือนปุ่มท้ายการ์ด
      ใช้กติกาเดียวกับ .site-card-footer โดยตั้งใจ: กว้างพอ = บรรทัดเดียว
      แคบแล้วขึ้นบรรทัดใหม่ ไม่ใช่หดจนข้อความถูกตัด */
/* ‼️ แถวของ "สิ่งที่ต้องดำเนินการ" — ข้อความซ้าย ปุ่มขวา
      เจอจากภาพหน้าจอจริง 2026-08-27: ตอนแรกลืมเขียน class นี้
      แถวจึงกองซ้อนกันชิดซ้ายทั้งหมดจนอ่านไม่ออกว่าปุ่มเป็นของข้อไหน
      ‼️ ชุดตรวจอัตโนมัติจับไม่ได้ เพราะไม่ล้นขอบและ contrast ผ่าน
         เป็นตัวอย่างว่าทำไมต้องเปิดภาพดูด้วยตาจริง */
.action-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) 0;
    border-bottom: var(--border-width) solid var(--color-border);
}

/* แถวสุดท้ายไม่ต้องมีเส้นคั่น ไม่งั้นจะเหมือนมีของต่ออยู่ข้างล่าง */
.action-row:last-child { border-bottom: 0; padding-bottom: 0; }

.action-row-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
    flex: 1 1 20rem;
}
.action-pair {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.action-pair > * { flex: 0 1 auto; min-width: max-content; }

/* ---------------------------------------------- แถบเมนูย่อยของหน้าเครื่องมือระบบ
   ‼️ เป็นลิงก์จริง ไม่ใช่แท็บที่ซ่อนการ์ดด้วย JavaScript
      จึงต้องมีสถานะ :focus-visible ที่มองเห็นได้ เพราะเดินด้วยคีย์บอร์ดได้จริง */
.subnav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    border-bottom: var(--border-width) solid var(--color-border);
    margin-bottom: var(--space-4);
}

.subnav-item {
    padding: var(--space-2) var(--space-3);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: calc(var(--border-width) * -1);
    white-space: nowrap;
}

.subnav-item:hover { color: var(--color-text); }

/* ‼️ ไม่พึ่งสีอย่างเดียว — มีเส้นใต้หนาเป็นสัญญาณที่สอง
      คนที่แยกสีไม่ได้ต้องรู้ได้ว่าอยู่หน้าไหน */
.subnav-item.is-active {
    /* ‼️ ข้อความต้องใช้ --color-primary-strong ไม่ใช่ --color-primary
          สีแบรนด์บนพื้นขาวได้ contrast ไม่ถึงเกณฑ์ ตามที่ token เตือนไว้เอง
          ส่วนเส้นใต้ใช้สีแบรนด์ได้ เพราะเป็นงานตกแต่ง ไม่ใช่ข้อความที่ต้องอ่าน */
    color: var(--color-primary-strong);
    border-bottom-color: var(--color-primary);
}

.sidebar-toggle { display: none; }

/* ---------------------------------------------------------- responsive */

@media (max-width: 1200px) {
    .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .editor { grid-template-columns: 280px minmax(0, 1fr); }
}

@media (max-width: 992px) {
    .app { grid-template-columns: minmax(0, 1fr); }

    .sidebar {
        position: fixed;
        left: 0;
        top: 0;
        width: var(--sidebar-width);
        z-index: 95;
        transform: translateX(-100%);
        transition: transform var(--transition-base);
    }

    .sidebar.is-open { transform: translateX(0); }

    .sidebar-toggle { display: inline-flex; }

    .grid-2,
    .grid-3,
    .grid-sidebar,
    .form-grid-2 { grid-template-columns: minmax(0, 1fr); }

    .editor { grid-template-columns: minmax(0, 1fr); }

    .editor-panel { position: static; max-height: none; }

    .manual-layout { grid-template-columns: minmax(0, 1fr); }

    /* ‼️ จอแคบซ้อนเป็นคอลัมน์เดียว และแผงแบรนด์ย่อเหลือเฉพาะแบรนด์กับพาดหัว
       ภาพประกอบกับรายการคุณสมบัติถูกซ่อน เพื่อให้ผู้ใช้ไม่ต้องเลื่อนผ่านงานโฆษณายาวๆ
       ก่อนจะถึงฟอร์ม — ซึ่งคือสิ่งเดียวที่เขาเปิดหน้านี้มาทำ */
    /* ‼️ แถวบนสูงตามเนื้อหา แถวล่างกินที่เหลือ — ถ้าไม่กำหนด สองแถวจะหารความสูงจอกันคนละครึ่ง
       แล้วแผงแบรนด์จะเหลือพื้นกรมท่าว่างเปล่ายาวเป็นคืบก่อนถึงฟอร์ม */
    .auth-shell { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; }

    .auth-aside {
        padding: var(--space-5) var(--space-4);
        gap: var(--space-4);
        justify-content: flex-start;
    }

    .auth-headline { font-size: var(--font-size-2xl); }

    .auth-artwork { display: none; }

    /* ‼️ จอแคบไม่ต้องจัดฟอร์มไว้กลางแนวตั้ง — ผู้ใช้เลื่อนหน้าจออยู่แล้ว
       การดันการ์ดลงไปกลางจอทำให้เปิดมาแล้วเห็นแต่พื้นที่ว่างก่อนถึงช่องกรอก */
    .auth-main { padding: var(--space-4) var(--space-3) var(--space-7); }

    .auth-card { margin: 0; }
}

@media (max-width: 640px) {
    .auth-features,
    .auth-subtitle { display: none; }

    .auth-aside { padding: var(--space-4) var(--space-3); }

    .auth-card { padding: var(--space-5) var(--space-4); box-shadow: var(--shadow-sm); }

    /* ปุ่มแจ้งปัญหาลอยอยู่มุมล่างขวา — เว้นที่ท้ายฟอร์มไม่ให้ทับปุ่มหลัก */
    .auth-main { padding-bottom: var(--space-8); }
}

@media (max-width: 640px) {
    .content { padding: var(--space-3) var(--space-3) var(--space-7); }

    /* จอแคบแสดงเฉพาะอักษรย่อของผู้ใช้ — กันแถบบนล้นจนแถบภาษาหลุดขอบจอ */
    .topbar-user-name { display: none; }

    .page-header { flex-direction: column; align-items: stretch; }

    .page-header-actions .btn { flex: 1 1 auto; }

    .grid-4 { grid-template-columns: minmax(0, 1fr); }

    /* จอมือถือใช้ 2 คอลัมน์ — ถ้าเรียงเดี่ยวต้องเลื่อนผ่านการ์ดสรุป 4 ใบก่อนถึงตาราง */
    .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

    .list-toolbar { flex-direction: column; align-items: stretch; }

    .support-fab { right: var(--space-3); bottom: var(--space-3); }

    /* จอมือถือ: หัวข้อกับค่าเรียงบนล่าง ไม่ใช่ซ้ายขวา — ค่ายาวๆ จะได้ไม่ถูกบีบจนขึ้นบรรทัดทีละคำ */
    .definition-list { grid-template-columns: minmax(0, 1fr); gap: var(--space-1); }

    .definition-list dt { margin-top: var(--space-2); }

    .modal { max-height: 96vh; }
}

@media print {
    .sidebar,
    .topbar,
    .support-fab,
    .page-header-actions { display: none; }

    body { background: var(--color-surface); }
}

/* ---------------------------------------------------------------- แถบสวมสิทธิ์
   ‼️ ทีมงานแพลตฟอร์มกำลังดูระบบในฐานะลูกค้าตัวอย่าง — ต้องเห็นชัดทุกหน้า
      ไม่งั้นจะลืมตัวแล้วเข้าใจว่ากำลังดูระบบของตัวเอง
   ‼️ พื้น --color-warning กับตัวอักษรขาวได้ contrast 5.33:1 ผ่าน WCAG AA
      ปุ่มกลับใช้พื้นขาวกับตัวอักษร --color-warning ได้ค่าเดียวกัน */
.impersonation-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    background: var(--solid-warning-bg);
    color: var(--solid-warning-fg);
    font-size: var(--font-size-sm);
}

.impersonation-bar-text {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

.impersonation-bar-hint { opacity: 0.9; }

.impersonation-bar-button {
    background: var(--color-text-inverse);
    color: var(--color-warning);
    border-color: var(--color-text-inverse);
}

.impersonation-bar-button:hover {
    background: var(--color-warning-soft);
    color: var(--color-warning);
}

/* ‼️ บนจอแคบให้ข้อความย่อลงแทนที่จะดันปุ่มตกขอบ */
@media (max-width: 640px) {
    .impersonation-bar-hint { display: none; }
}

/* ============================================================================
   หน้าแนะนำผลิตภัณฑ์ (สาธารณะ) — คลาสขึ้นต้นด้วย mk- ทั้งหมด
   ‼️ ใช้เฉพาะหน้าแรกและคลังแม่แบบ ไม่ปนกับระบบจัดการ จึงแยกบล็อกไว้ท้ายไฟล์
   ‼️ พื้นสีเข้มทุกก้อนต้องตั้ง background-color เป็นสีทึบด้วยเสมอ ไม่ใช่ gradient อย่างเดียว
      ถ้าตั้งแต่ gradient ตัวตรวจ contrast จะอ่านพื้นไม่เจอ แล้วไปเทียบกับพื้นขาวของ body แทน
      ซึ่งทำให้ตัวอักษรสีขาวถูกรายงานว่าไม่ผ่านทั้งที่จริงผ่าน
   ============================================================================ */

.mk-body { background: var(--color-surface); }

/* ‼️ ตราสินค้าบนพื้นขาว — ห้ามใช้ .sidebar-brand ตรงๆ เพราะตัวอักษรของมันเป็นสีขาว
   (ออกแบบไว้สำหรับแถบข้างพื้นเข้ม) วางบนพื้นขาวแล้วได้ contrast 1.00 คือมองไม่เห็นเลย */
.mk-brand {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-text);
    font-weight: var(--font-weight-bold);
    font-size: var(--font-size-lg);
    letter-spacing: .02em;
    text-decoration: none;
}

.mk-brand:hover { color: var(--color-text); text-decoration: none; }

/* ‼️ ตัวอักษร OW ในกล่องสีส้มต้องเป็นสีขาว (5.19:1) — ถ้าปล่อยให้สืบทอดสีเข้มจาก .mk-brand
   จะได้ 3.01:1 ซึ่งไม่ผ่าน AA และเป็นตราสินค้าที่อยู่บนทุกหน้าสาธารณะ */
/* ‼️ ต้องจับคู่กับ --btn-primary-bg เสมอ ไม่ใช่ขาวตายตัว — ไม่งั้นพอพื้นเปลี่ยนเฉด ตัวอักษรจะไม่ตาม */
.mk-brand .sidebar-brand-mark { color: var(--btn-primary-fg); }

/* -------------------------------------------------------------- แถบบนสุด */

.mk-topbar {
    position: sticky;
    top: 0;
    z-index: 30;
    background: var(--color-surface);
    border-bottom: var(--border-width) solid var(--color-border);
}

.mk-topbar-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    width: 100%;
    max-width: var(--content-max);
    margin: 0 auto;
    padding: var(--space-3) var(--space-4);
}

.mk-nav {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    flex: 1 1 auto;
    justify-content: center;
    min-width: 0;
}

.mk-nav-link {
    position: relative;
    padding: var(--space-2) 0;
    color: var(--color-text);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    white-space: nowrap;
}

.mk-nav-link:hover { color: var(--color-primary-strong); }

.mk-nav-link.is-active { color: var(--color-primary-strong); }

.mk-nav-link.is-active::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--space-1);
    border-radius: var(--radius-pill);
    background: var(--color-primary);
}

.mk-topbar-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.mk-lang {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-pill);
}

.mk-lang-icon {
    display: inline-flex;
    color: var(--color-text-muted-on-soft);
}

.mk-lang a {
    padding: 0 var(--space-1);
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
}

.mk-lang a.is-active { color: var(--color-text); }

/* ------------------------------------------------------------- ส่วนหัวใหญ่ */

.mk-hero {
    position: relative;
    overflow: hidden;
    /* ‼️ ต้องมีสีทึบคู่กับ gradient เสมอ — ดูเหตุผลที่หัวบล็อก */
    background-color: var(--color-hero);
    background-image: linear-gradient(140deg, var(--color-hero) 0%, var(--color-hero-deep) 55%, var(--color-hero) 100%);
    color: var(--color-text-inverse);
    padding: var(--space-8) var(--space-4) var(--space-7);
}

.mk-hero-inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    align-items: center;
    gap: var(--space-6);
    width: 100%;
    max-width: var(--content-max);
    margin: 0 auto;
}

.mk-hero-copy { min-width: 0; }

.mk-hero-title {
    margin: 0 0 var(--space-4);
    font-size: var(--font-size-3xl);
    line-height: 1.18;
    letter-spacing: -0.01em;
}

.mk-hero-title-line { display: block; }

/* ‼️ วลีที่เน้นต้องไม่ถูกตัดกลาง ไม่งั้นหัวเรื่องจะกลายเป็นสามบรรทัดและผิดจากแบบ */
.mk-accent {
    color: var(--color-primary-on-dark);
    white-space: nowrap;
}

.mk-hero-text {
    margin: 0 0 var(--space-5);
    max-width: 34em;
    color: var(--color-text-on-dark-muted);
    font-size: var(--font-size-lg);
}

.mk-hero-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.mk-btn-ghost {
    background: transparent;
    border-color: var(--color-text-inverse);
    color: var(--color-text-inverse);
}

.mk-btn-ghost:hover {
    background: var(--color-text-inverse);
    color: var(--color-hero);
}

.mk-hero-points {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    color: var(--color-text-on-dark-muted);
    font-size: var(--font-size-sm);
}

.mk-hero-check {
    display: inline-flex;
    color: var(--color-success-on-dark);
}

/* ------------------------------------------------- กรอบจอคอมพิวเตอร์และมือถือ */

.mk-hero-visual {
    position: relative;
    min-width: 0;
    padding-bottom: var(--space-6);
}

.mk-device {
    overflow: hidden;
    border: var(--border-width) solid var(--color-device-edge);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    box-shadow: var(--shadow-device);
}

.mk-device-bar {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    background: var(--color-surface-muted);
    border-bottom: var(--border-width) solid var(--color-border);
}

.mk-device-dot {
    width: var(--space-2);
    height: var(--space-2);
    border-radius: var(--radius-pill);
    background: var(--color-border-strong);
}

.mk-device-shot,
.mk-phone-shot {
    display: block;
    width: 100%;
    height: auto;
}

.mk-phone {
    position: absolute;
    right: var(--space-5);
    bottom: 0;
    width: 31%;
    max-width: 168px;
    overflow: hidden;
    padding: var(--space-2) var(--space-1);
    border-radius: var(--radius-lg);
    background: var(--color-secondary);
    box-shadow: var(--shadow-device);
}

.mk-phone-notch {
    display: block;
    width: 40%;
    height: var(--space-1);
    margin: 0 auto var(--space-1);
    border-radius: var(--radius-pill);
    background: var(--color-border-strong);
}

.mk-phone-shot {
    border-radius: var(--radius-sm);
    /* ‼️ ครอปให้เป็นทรงมือถือ ไม่ใช่ย่อภาพจอคอมทั้งใบจนอ่านไม่ออก */
    aspect-ratio: 9 / 16;
    object-fit: cover;
    object-position: top center;
}

/* ------------------------------------------------------ แถวภาพย่อของแม่แบบ */

.mk-thumbs {
    display: flex;
    gap: var(--space-3);
    width: 100%;
    max-width: var(--content-max);
    margin: var(--space-6) auto 0;
    padding: 0 0 var(--space-2);
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x proximity;
}

.mk-thumb {
    flex: 0 0 auto;
    width: 172px;
    scroll-snap-align: start;
}

.mk-thumb a {
    display: block;
    overflow: hidden;
    border-radius: var(--radius-base);
    background: var(--color-surface);
    box-shadow: var(--shadow-device);
    text-decoration: none;
}

.mk-thumb img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 10;
    object-fit: cover;
    object-position: top center;
}

.mk-thumb-label {
    display: block;
    padding: var(--space-2);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    text-align: center;
    /* ‼️ ชื่อแม่แบบบางตัวยาว ต้องตัดด้วย … ไม่ใช่ดันการ์ดให้สูงไม่เท่ากัน */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* -------------------------------------------- แถบจุดเด่น (คร่อมขอบล่างส่วนหัว) */

.mk-strip-wrap {
    width: 100%;
    max-width: var(--content-max);
    margin: calc(var(--space-6) * -1) auto 0;
    padding: 0 var(--space-4);
    position: relative;
    z-index: 2;
}

.mk-strip {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--space-4);
    margin: 0;
    padding: var(--space-5);
    list-style: none;
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

.mk-strip-item {
    display: grid;
    gap: var(--space-1);
    min-width: 0;
}

.mk-strip-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--size-strip-icon);
    height: var(--size-strip-icon);
    margin-bottom: var(--space-1);
    border-radius: var(--radius-base);
    background: var(--color-secondary-soft);
    color: var(--color-secondary-text);
}

.mk-strip-title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-bold);
}

.mk-strip-text {
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-base);
}

/* --------------------------------------------------------- ส่วนเนื้อหาทั่วไป */

.mk-section { padding: var(--space-8) var(--space-4); }

.mk-section-muted { background: var(--color-bg); }

.mk-section-inner {
    width: 100%;
    max-width: var(--content-max);
    margin: 0 auto;
}

.mk-section-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-4);
    margin-bottom: var(--space-5);
}

.mk-section-head-center {
    text-align: center;
    margin-bottom: var(--space-5);
}

.mk-section-title {
    margin: 0;
    font-size: var(--font-size-3xl);
}

.mk-section-hint {
    margin: 0;
    color: var(--color-text-muted-on-soft);
}

/* ------------------------------------------------------- การ์ดแม่แบบและราง */

.mk-rail-wrap { position: relative; }

.mk-rail {
    display: flex;
    gap: var(--space-3);
    margin: 0;
    padding: 0 0 var(--space-3);
    list-style: none;
    overflow-x: auto;
    scroll-behavior: smooth;
    scroll-snap-type: x proximity;
}

.mk-tpl-card {
    position: relative;
    flex: 0 0 auto;
    width: var(--size-tpl-card);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    box-shadow: var(--shadow-sm);
    scroll-snap-align: start;
}

.mk-tpl-badge {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    padding: var(--space-1) var(--space-3);
    border-bottom-right-radius: var(--radius-base);
    background: var(--btn-primary-bg);
    color: var(--btn-primary-fg);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-bold);
}

.mk-tpl-media { display: block; }

.mk-tpl-media img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 10;
    object-fit: cover;
    object-position: top center;
}

.mk-tpl-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    flex: 1 1 auto;
    padding: var(--space-3);
}

.mk-tpl-category {
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-xs);
}

.mk-tpl-name {
    font-weight: var(--font-weight-bold);
    line-height: var(--line-height-tight);
}

.mk-tpl-hint {
    margin: 0;
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-sm);
}

.mk-tpl-link {
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    gap: var(--space-1);
    /* ‼️ ดันลงล่างสุดเสมอ ลิงก์ของทุกใบในแถวจึงอยู่ระดับเดียวกันแม้ชื่อจะยาวไม่เท่ากัน */
    margin-top: auto;
    padding-top: var(--space-2);
    color: var(--color-primary-strong);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
}

.mk-tpl-link:hover { text-decoration: underline; }

.mk-rail-arrow {
    position: absolute;
    top: var(--size-rail-arrow-top);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--size-rail-arrow);
    height: var(--size-rail-arrow);
    padding: 0;
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-pill);
    background: var(--color-surface);
    color: var(--color-text);
    box-shadow: var(--shadow-base);
    cursor: pointer;
}

.mk-rail-arrow:hover { border-color: var(--color-border-strong); }

.mk-rail-prev { left: calc(var(--size-rail-arrow) / -2); }
.mk-rail-next { right: calc(var(--size-rail-arrow) / -2); }

/* คลังแม่แบบเต็มหน้า — การ์ดชุดเดียวกับหน้าแรก แต่จัดเป็นตาราง ไม่ใช่ราง */
.mk-tpl-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
}

.mk-tpl-grid .mk-tpl-card { width: auto; }

/* ----------------------------------------------- แถบความน่าเชื่อถือ (พื้นเข้ม) */

.mk-trust {
    background-color: var(--color-hero);
    background-image: linear-gradient(120deg, var(--color-hero-deep) 0%, var(--color-hero) 70%);
    color: var(--color-text-inverse);
    padding: var(--space-8) var(--space-4);
}

.mk-trust-inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--space-6);
    width: 100%;
    max-width: var(--content-max);
    margin: 0 auto;
}

.mk-trust-title {
    margin: 0 0 var(--space-2);
    font-size: var(--font-size-3xl);
}

.mk-trust-text {
    margin: 0 0 var(--space-5);
    color: var(--color-text-on-dark-muted);
}

.mk-trust-stats {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
}

.mk-stat {
    display: grid;
    gap: var(--space-1);
    justify-items: start;
    min-width: 0;
}

.mk-stat-icon {
    display: inline-flex;
    color: var(--color-primary-on-dark);
}

.mk-stat-value {
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-bold);
    line-height: var(--line-height-tight);
}

.mk-stat-label {
    color: var(--color-text-on-dark-muted);
    font-size: var(--font-size-xs);
    line-height: var(--line-height-base);
}

/* ภาพสามใบ: ใบสูงด้านซ้าย และสองใบซ้อนกันด้านขวา
   ‼️ ต้องมี aspect-ratio ที่ตัวตาราง — ไม่งั้นความสูงของแถวจะมาจากเนื้อหา
      ส่วนเนื้อหา (img) ขอความสูง 100% ของแถว กลายเป็นวงกลมที่แก้ไม่ตก แล้วยุบเหลือศูนย์
      อาการคือภาพทั้งสามใบหายไปเฉยๆ โดยที่ HTML ถูกต้องทุกอย่าง */
.mk-collage {
    display: grid;
    grid-template-columns: 1.25fr 1fr;
    grid-template-rows: repeat(2, minmax(0, 1fr));
    aspect-ratio: 5 / 4;
    gap: var(--space-3);
    min-width: 0;
}

.mk-collage img {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: var(--radius-lg);
    object-fit: cover;
}

.mk-collage-tall { grid-row: span 2; }

/* ------------------------------------------------------------------ ราคา */

/* ‼️ stretch ไม่ใช่ start — การ์ด Custom มีรายการยาวกว่าการ์ดที่มีราคา
   ถ้าปล่อยให้สูงตามเนื้อหา ปุ่มของสามใบจะอยู่คนละระดับกันจนแถวดูไม่เป็นชุดเดียว */
.mk-price-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--space-4);
    align-items: stretch;
    margin: 0;
    padding: 0;
    list-style: none;
}

.mk-price-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-5) var(--space-4) var(--space-4);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    box-shadow: var(--shadow-sm);
}

/* ปุ่มของทุกใบอยู่ระดับเดียวกันเสมอ ไม่ว่ารายการข้างบนจะยาวไม่เท่ากัน */
.mk-price-card > .btn {
    margin-top: auto;
}

/* ‼️ ตัวที่เน้นใช้สีรองของแบรนด์ (กรมท่า) ไม่ใช่สีใหม่นอกชุด — ทิศทางธีมล็อกไว้ที่ CLAUDE.md ข้อ 1 */
.mk-price-card.is-featured {
    border-color: var(--color-secondary);
    box-shadow: var(--shadow-lg);
}

.mk-price-badge {
    position: absolute;
    top: calc(var(--space-3) * -1);
    left: 50%;
    transform: translateX(-50%);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    background: var(--color-secondary);
    color: var(--color-text-inverse);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-bold);
    white-space: nowrap;
}

.mk-price-name {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-bold);
}

.mk-price-value {
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-bold);
    color: var(--color-text);
}

.mk-price-list {
    display: grid;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--font-size-sm);
}

.mk-price-list li {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
}

.mk-price-check {
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--color-success);
}

/* ‼️ การ์ด Custom ไม่มีราคา จึงต้องมีบรรทัดบอกว่าคืออะไรแทนที่ตัวเลข
   ไม่งั้นคนอ่านจะเห็นแค่คำว่า "ติดต่อเรา" ลอยอยู่โดยไม่รู้ว่าได้อะไร */
.mk-price-tagline {
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
}

.mk-price-card-custom {
    border-style: dashed;
}

/* --------------------------------------------- การ์ดที่มีผลกับระบบทั้งระบบ */

/* ‼️ ใช้กับกล่องที่ "กดแล้วเปลี่ยนสถานะของทั้งระบบ" เท่านั้น เช่น รัน migration หรือลบชุดข้อมูล
   ต้องต่างจากการ์ดธรรมดาให้เห็นทันทีจากหางตา ไม่ใช่ต้องอ่านหัวข้อก่อนถึงจะรู้ว่าอันตราย
   ใช้สีเตือนของชุดสี ไม่ใช่สีแดงใหม่นอกระบบ */
.card-danger-zone {
    border-color: var(--color-warning);
    background: var(--color-warning-soft);
}

.card-danger-zone .card-header {
    border-bottom-color: var(--color-warning);
}

/* ------------------------------------------------------------- ติดต่อเรา */

.mk-contact {
    display: grid;
    justify-items: center;
    gap: var(--space-4);
    text-align: center;
}

/* ------------------------------------------------------- แถบคำมั่นปิดท้าย */

.mk-promise {
    background: var(--color-primary-soft);
    border-top: var(--border-width) solid var(--color-primary-border);
    padding: var(--space-5) var(--space-4);
}

.mk-promise-inner {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-4);
    width: 100%;
    max-width: var(--content-max);
    margin: 0 auto;
    padding: 0;
    list-style: none;
}

.mk-promise-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
}

.mk-promise-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: var(--size-strip-icon);
    height: var(--size-strip-icon);
    border-radius: var(--radius-base);
    background: var(--color-surface);
    color: var(--color-primary-strong);
}

.mk-promise-title {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-bold);
}

.mk-promise-text {
    display: block;
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-xs);
}

/* ------------------------------------------------------------------ ท้ายหน้า */

.mk-footer {
    background: var(--color-surface);
    border-top: var(--border-width) solid var(--color-border);
    padding: var(--space-6) var(--space-4) var(--space-4);
}

.mk-footer-inner {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    width: 100%;
    max-width: var(--content-max);
    margin: 0 auto;
}

.mk-footer-inner p { max-width: 46em; color: var(--color-text-muted-on-soft); }

.mk-footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
}

.mk-footer-links a,
.mk-footer-bottom a {
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-sm);
    text-decoration: none;
}

.mk-footer-links a:hover,
.mk-footer-bottom a:hover { color: var(--color-primary-strong); }

.mk-footer-bottom {
    align-items: center;
    margin-top: var(--space-4);
    padding-top: var(--space-3);
    border-top: var(--border-width) solid var(--color-border);
    color: var(--color-text-muted-on-soft);
}

/* ‼️ จอกว้าง: หกช่องพอดีความกว้างเนื้อหา ไม่ใช่ความกว้างคงที่แล้วล้นหรือเหลือช่องว่าง */
@media (min-width: 1100px) {
    .mk-thumb,
    .mk-rail .mk-tpl-card { width: calc((100% - var(--space-3) * 5) / 6); }
}
/* -------------------------------------------------------------- จอแคบลง */

@media (max-width: 1100px) {
    .mk-nav { display: none; }
    .mk-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .mk-trust-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 920px) {
    .mk-hero { padding-top: var(--space-6); }
    .mk-hero-inner { grid-template-columns: minmax(0, 1fr); }
    .mk-hero-title { font-size: var(--font-size-3xl); }
    .mk-trust-inner { grid-template-columns: minmax(0, 1fr); }
    .mk-rail-arrow { display: none; }
    .mk-promise-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .mk-footer-inner { flex-direction: column; }
}

@media (max-width: 640px) {
    /* ‼️ แถบบนใส่ในบรรทัดเดียวไม่พอที่ 390px — ตราสินค้าแถวหนึ่ง ปุ่มอีกแถวหนึ่ง
       ห้ามแก้ด้วยการซ่อนปุ่มเข้าสู่ระบบ เพราะคนที่เป็นลูกค้าอยู่แล้วจะเข้าระบบจากมือถือไม่ได้ */
    .mk-topbar-inner {
        flex-wrap: wrap;
        justify-content: center;
        gap: var(--space-2);
        padding: var(--space-2) var(--space-3);
    }
    .mk-topbar-actions { flex: 1 1 100%; justify-content: center; }

    /* ‼️ จอแคบต้องยอมให้วลีที่เน้นขึ้นบรรทัดใหม่ ไม่งั้นหัวเรื่องจะดันหน้าให้เลื่อนแนวนอน */
    .mk-accent { white-space: normal; }

    .mk-hero { padding: var(--space-5) var(--space-3) var(--space-6); }
    .mk-hero-title { font-size: var(--font-size-2xl); }
    .mk-hero-text { font-size: var(--font-size-base); }
    .mk-hero-actions .btn { width: 100%; }
    .mk-section { padding: var(--space-6) var(--space-3); }
    .mk-section-title { font-size: var(--font-size-2xl); }
    .mk-section-head { flex-direction: column; align-items: stretch; }
    .mk-strip-wrap { padding: 0 var(--space-3); }
    .mk-strip { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
    .mk-trust { padding: var(--space-6) var(--space-3); }
    .mk-trust-title { font-size: var(--font-size-2xl); }
    .mk-trust-stats { gap: var(--space-3); }
    .mk-promise-inner { grid-template-columns: minmax(0, 1fr); }
    .mk-collage { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; aspect-ratio: auto; }
    .mk-collage-tall { grid-row: auto; }
    .mk-collage img { aspect-ratio: 16 / 9; height: auto; }
}

/* ‼️ การ์ดในคลังแม่แบบต้องสูงเท่ากันทุกใบ ไม่งั้นแถวจะเหลื่อมและดูไม่เป็นระเบียบ
   คำอธิบายยาวไม่เท่ากัน จึงตัดที่สองบรรทัดแล้วดันปุ่มลงล่างสุดเสมอ */
.template-grid .template-card {
    display: flex;
    flex-direction: column;
}

.template-grid .template-card .card-body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
}

.template-card-hint {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 42px;
}

.template-card-actions { margin-top: auto; }

/* ‼️ แถบเข้าดูข้อมูลลูกค้าแบบอ่านอย่างเดียว — ใช้สีข้อมูล ไม่ใช่สีเตือน
   เพราะเป็นสถานะที่ปลอดภัยกว่าการสวมสิทธิ์ แต่ยังต้องเห็นชัดตลอดเวลา
   #FFFFFF บน --color-info (#1F5F9E) = 6.29:1 ผ่าน WCAG AA */
.support-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    background: var(--solid-info-bg);
    color: var(--solid-info-fg);
    font-size: var(--font-size-sm);
}

.support-bar-button {
    background: var(--color-text-inverse);
    color: var(--color-info);
    border-color: var(--color-text-inverse);
}

.support-bar-button:hover {
    background: var(--color-info-soft);
    color: var(--color-info);
}

/* ============================================================================
   DESIGN SYSTEM v2 — ส่วนประกอบกลางที่เพิ่มตาม Visual Standard ที่อนุมัติ 2026-08-23
   ‼️ ทุกอย่างในบล็อกนี้เป็น "ส่วนประกอบที่ใช้ซ้ำ" เท่านั้น ห้ามเพิ่มกฎเฉพาะหน้าใดหน้าหนึ่ง
      ถ้าหน้าไหนต้องการหน้าตาต่างออกไป ให้เพิ่ม modifier ที่นี่แล้วให้ทุกหน้าใช้ร่วมกันได้
   ============================================================================ */

/* -------------------------------------------------- แถบสลับค่าแบบปุ่มติดกัน
   ใช้กับ: สลับภาษา · เลือกช่วงเวลา · สลับชุดข้อมูลของกราฟ
   ‼️ ทุกตัวเลือกต้องเป็นลิงก์จริง (เปลี่ยน query string) ไม่ใช่ JS ที่ซ่อนข้อมูลไว้ */
.segmented {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    background: var(--color-neutral-soft);
    padding: var(--space-1);
    border-radius: var(--radius-pill);
    max-width: 100%;
    overflow-x: auto;
}

.segmented > * {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    height: var(--space-5);
    padding: 0 var(--space-3);
    border: 0;
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--color-text-muted-on-soft);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    white-space: nowrap;
    cursor: pointer;
}

.segmented > *:hover { color: var(--color-text); text-decoration: none; }

.segmented > .is-active {
    background: var(--color-surface);
    color: var(--color-primary-strong);
    box-shadow: var(--shadow-sm);
}

.segmented-sm > * { height: var(--space-4); padding: 0 var(--space-2); font-size: var(--font-size-xs); }

/* -------------------------------------------------------- ตัวเลือกในกล่อง
   select ที่ต้องดูเป็น "ตัวควบคุม" ไม่ใช่ช่องกรอก — ใช้บนแถบบนและหัวการ์ด */
.select-inline {
    height: var(--height-control-sm);
    padding: 0 var(--space-3);
    border-radius: var(--radius-pill);
    border: var(--border-width) solid var(--color-border-strong);
    background: var(--color-surface);
    color: var(--color-text);
    font-family: inherit;
    font-size: var(--font-size-sm);
    min-height: 0;
    max-width: 220px;
}

/* ------------------------------------------------------- ปุ่มผู้ใช้บนแถบบน */
.topbar-user { gap: var(--space-2); padding: 0 var(--space-2); height: var(--height-button); }
.topbar-user .icon-chevron { width: var(--font-size-sm); height: var(--font-size-sm); opacity: .6; }

.topbar-divider {
    width: var(--border-width);
    height: var(--space-4);
    background: var(--color-border);
    flex: none;
}

/* ------------------------------------------------------------ หัวการ์ดย่อย */
.card-header-tight { padding: var(--space-3) var(--space-4); border-bottom: 0; }

/* ----------------------------------------------------- แถบตัวเลขในหัวกราฟ
   ‼️ ทุกตัวเลขต้องมาจากชุดข้อมูลเดียวกับกราฟด้านล่าง (design.md ข้อ 5.11) */
.stat-strip {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    padding: 0 var(--space-4) var(--space-3);
}

.stat-strip-item {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding-right: var(--space-4);
    border-right: var(--border-width) solid var(--color-border);
    min-width: 0;
    flex: 1 1 120px;
}

.stat-strip-item:last-child { border-right: 0; padding-right: 0; }

.stat-strip-label { font-size: var(--font-size-xs); color: var(--color-text-muted); }
.stat-strip-value { font-size: var(--font-size-lg); font-weight: var(--font-weight-bold); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ กราฟ
   ‼️ กราฟทั้งหมดเป็น SVG ที่ PHP วาดจากข้อมูลจริง ไม่มีไลบรารีภายนอก (กฎเหล็กข้อ 11)
      ไม่มี animation และไม่มีสามมิติ ตาม design.md ข้อ 5.4 */
.chart { display: block; width: 100%; height: auto; }

.chart-grid-line { stroke: var(--chart-grid); stroke-width: 1; }
.chart-axis-text { fill: var(--color-text-muted); font-size: 11px; font-family: var(--font-family); }
.chart-line { fill: none; stroke: var(--chart-1); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-area { fill: var(--color-primary-soft); opacity: .8; }
.chart-dot { fill: var(--color-surface); stroke: var(--chart-1); stroke-width: 2; }

.chart-frame { padding: 0 var(--space-4) var(--space-4); }

.chart-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    padding: 0 var(--space-4) var(--space-4);
    font-size: var(--font-size-sm);
}

/* วงแหวนสัดส่วน + รายการกำกับ (ต้องมีข้อความและตัวเลขเสมอ ห้ามสื่อด้วยสีอย่างเดียว) */
.donut-layout {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
}

.donut { width: 168px; height: 168px; flex: none; }
.donut-center-value { fill: var(--color-text); font-size: 26px; font-weight: 600; font-family: var(--font-family); }
.donut-center-label { fill: var(--color-text-muted); font-size: 11px; font-family: var(--font-family); }

.legend-list { list-style: none; padding: 0; margin: 0; flex: 1 1 180px; min-width: 0; display: flex; flex-direction: column; gap: var(--space-2); }

.legend-row { display: flex; align-items: center; gap: var(--space-2); font-size: var(--font-size-sm); min-width: 0; }
.legend-swatch { width: var(--space-2); height: var(--space-2); border-radius: var(--radius-pill); flex: none; }
.legend-label { flex: 1 1 auto; min-width: 0; color: var(--color-text); }
.legend-value { color: var(--color-text); font-weight: var(--font-weight-medium); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ การ์ดทางลัด
   ‼️ ทุกใบต้องเป็นลิงก์ไปหน้าที่มีอยู่จริง ห้ามสร้างทางลัดไปหน้าที่ยังไม่มี */
.tile-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-3); }

.tile {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    color: var(--color-text);
    min-width: 0;
    transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.tile:hover { border-color: var(--color-primary-border); box-shadow: var(--shadow-card); text-decoration: none; color: var(--color-text); }

.tile-icon {
    width: var(--space-6);
    height: var(--space-6);
    border-radius: var(--radius-lg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    background: var(--tint-brand-bg);
    color: var(--tint-brand-fg);
}

.tile-icon .icon { width: var(--space-4); height: var(--space-4); }
.tile-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tile-title { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); }
.tile-hint { font-size: var(--font-size-xs); color: var(--color-text-muted); }

/* --------------------------------------------------------- รายการที่ต้องดูแล
   ตัวเลขทางขวาคือ "จำนวนที่ต้องจัดการ" — เป็น 0 ได้ และต้องแสดง 0 ตามจริง */
.attention-list { display: flex; flex-direction: column; gap: var(--space-2); list-style: none; padding: 0; margin: 0; }

.attention-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    color: var(--color-text);
    min-width: 0;
}

a.attention-item:hover { border-color: var(--color-primary-border); text-decoration: none; color: var(--color-text); }

.attention-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.attention-title { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); }
.attention-hint { font-size: var(--font-size-xs); color: var(--color-text-muted); }
.attention-count { font-size: var(--font-size-lg); font-weight: var(--font-weight-bold); font-variant-numeric: tabular-nums; flex: none; }

/* --------------------------------------------------------- การ์ดเว็บไซต์
   ภาพย่อคือภาพจริงของแม่แบบที่เว็บนั้นใช้ ถ้าไม่มีให้แสดงกรอบเปล่าพร้อมไอคอน */
.site-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(264px, 1fr)); gap: var(--space-3); }

.site-card {
    display: flex;
    flex-direction: column;
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    overflow: hidden;
    min-width: 0;
}

.site-card-media {
    position: relative;
    aspect-ratio: 16 / 10;
    background: var(--color-surface-muted);
    border-bottom: var(--border-width) solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-border-strong);
    overflow: hidden;
}

.site-card-media img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.site-card-media > .icon { width: var(--space-6); height: var(--space-6); }

.site-card-badges {
    position: absolute;
    top: var(--space-2);
    left: var(--space-2);
    right: var(--space-2);
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-2);
}

.site-card-body { padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.site-card-title { font-size: var(--font-size-base); font-weight: var(--font-weight-medium); margin: 0; }
.site-card-host { font-size: var(--font-size-xs); color: var(--color-text-muted); }

.site-card-stats { display: flex; gap: var(--space-4); margin-top: var(--space-2); flex-wrap: wrap; }
.site-card-stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.site-card-stat-label { font-size: var(--font-size-xs); color: var(--color-text-muted); display: flex; align-items: center; gap: var(--space-1); }
.site-card-stat-label .icon { width: var(--font-size-sm); height: var(--font-size-sm); }
.site-card-stat-value { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); font-variant-numeric: tabular-nums; }

.site-card-footer {
    display: flex;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3) var(--space-3);
    margin-top: auto;
}

/* ‼️ ปุ่มท้ายการ์ดต้องอ่านครบทั้งคำ ไม่ใช่ถูกตัดเป็น "เปิดเว็บไซต์จ..."
      คำที่ถูกตัดคือคำที่บอกความหมายพอดี ("จริง" ในปุ่มเปิดเว็บไซต์จริง)

   ค่าเดิม flex: 1 1 0 บังคับให้ปุ่มสองใบแบ่งความกว้างเท่ากันและหดได้จนถึงศูนย์
   พอการ์ดกว้างราว 264-380px ตามกริด minmax(264px, 1fr) ข้อความไทยสองปุ่มรวมไอคอน
   ก็เกินความกว้างอยู่ดี ทั้งคู่จึงหดจนโดนตัดพร้อมกัน

   วิธีแก้คือให้ขึ้นบรรทัดใหม่แทนการหด
     flex-wrap: wrap        กว้างพอ = บรรทัดเดียว · แคบ = ซ้อนสองบรรทัดอย่างเป็นระเบียบ
     flex: 1 1 auto         ยังยืดเต็มความกว้างได้เมื่อขึ้นบรรทัดของตัวเอง
     min-width: max-content ไม่ยอมหดต่ำกว่าข้อความของตัวเอง = ตัวกระตุ้นให้ wrap ทำงาน

   ‼️ ไม่เลือกวิธีขยาย minmax เป็น 320px เพราะจะลดจำนวนคอลัมน์บนจอกว้าง
      ทั้งที่ปัญหาเกิดเฉพาะช่วงแคบ · แก้จุดหนึ่งแล้วทำอีกจุดแย่ลงไม่ใช่การแก้
   ‼️ ไม่เลือกวิธีย่อข้อความให้สั้นลง — เป็นการซ่อนปัญหา layout ด้วยการทำให้ข้อความแย่ลง
   ‼️ span.truncate ใน site-card.php ยังอยู่เป็นด่านสุดท้าย เผื่อภาษาที่ยาวกว่านี้ */
.site-card-footer { flex-wrap: wrap; }
.site-card-footer > * { flex: 1 1 auto; min-width: max-content; }

/* ------------------------------------------------- แถบเครื่องมือของหน้ารายการ
   ค้นหา + ตัวกรอง + เรียงลำดับ + ล้างค่า อยู่ในฟอร์ม GET เดียวกันเสมอ
   ‼️ ต้องกรอง/แบ่งหน้าที่ฝั่งเซิร์ฟเวอร์ ห้ามโหลดทั้งหมดมากรองในเบราว์เซอร์ (design.md ข้อ 5.5) */
.toolbar {
    display: flex;
    align-items: flex-end;
    gap: var(--space-2);
    flex-wrap: wrap;
    padding: var(--space-3);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    margin-bottom: var(--space-3);
}

.toolbar-search { flex: 1 1 240px; min-width: 0; }
.toolbar-field { flex: 0 1 180px; min-width: 0; }
.toolbar-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.toolbar .field { gap: var(--space-1); }

.result-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-bottom: var(--space-2);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.chip-row { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }

.chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: var(--space-4);
    padding: 0 var(--space-2);
    border-radius: var(--radius-pill);
    background: var(--color-neutral-soft);
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-xs);
}

.chip .icon { width: var(--font-size-xs); height: var(--font-size-xs); }

/* ------------------------------------------------------- เมนูคำสั่งประจำแถว
   ‼️ 1-2 คำสั่งวางตรงได้ เกินกว่านั้นต้องยุบลงเมนูนี้ (design.md ข้อ 5.6) */
.row-menu { position: relative; display: inline-flex; }

.row-menu-panel {
    position: absolute;
    right: 0;
    top: calc(100% + var(--space-1));
    min-width: 200px;
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    box-shadow: var(--shadow-pop);
    padding: var(--space-1);
    z-index: 40;
    text-align: left;
}

.row-menu-panel[hidden] { display: none; }
.row-menu-panel form { margin: 0; }

.row-menu-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2);
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--color-text);
    font-family: inherit;
    font-size: var(--font-size-sm);
    text-align: left;
    cursor: pointer;
}

.row-menu-item:hover { background: var(--color-surface-muted); text-decoration: none; color: var(--color-text); }
.row-menu-item .icon { width: var(--icon-size); height: var(--icon-size); flex: none; }
.row-menu-item.is-danger { color: var(--color-danger); }
.row-menu-item.is-danger:hover { background: var(--color-danger-soft); color: var(--color-danger); }
.row-menu-divider { height: var(--border-width); background: var(--color-border); margin: var(--space-1) 0; }

/* --------------------------------------------------- ตารางที่กลายเป็นการ์ด
   ‼️ บนมือถือห้ามซ่อนคอลัมน์ทิ้ง ต้องพลิกเป็นการ์ดที่ยังเห็นข้อมูลครบ (design.md ข้อ 6)
      หัวคอลัมน์เดิมมาจาก data-label ที่ PHP ใส่ให้ในทุก <td> */
/* ‼️ ตารางทุกตัวในระบบพลิกเป็นการ์ดบนมือถือโดยปริยาย — ไม่ต้องไปเติมคลาสทีละหน้า
   หัวคอลัมน์ของแต่ละช่องมาจาก data-label ที่ JS เติมให้จาก <th> ตรงคอลัมน์นั้น
   ตารางที่ไม่ควรพลิก (เช่น ตารางที่มีคอลัมน์เดียวหรือใช้จัดวาง) ใส่คลาส .table-flat กำกับ */
@media (max-width: 720px) {
    .table:not(.table-flat) thead { display: none; }
    .table:not(.table-flat), .table:not(.table-flat) tbody, .table:not(.table-flat) tr, .table:not(.table-flat) td { display: block; width: 100%; }

    .table:not(.table-flat) tr {
        height: auto;
        border: var(--border-width) solid var(--color-border);
        border-radius: var(--radius-lg);
        padding: var(--space-2);
        margin-bottom: var(--space-2);
        background: var(--color-surface);
    }

    .table:not(.table-flat) tr:hover { background: var(--color-surface); }

    .table:not(.table-flat) td {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: var(--space-3);
        border-bottom: 0;
        padding: var(--space-1) var(--space-2);
        text-align: left;
    }

    .table:not(.table-flat) td::before {
        content: attr(data-label);
        flex: 0 0 38%;
        color: var(--color-text-muted);
        font-size: var(--font-size-xs);
    }

    .table:not(.table-flat) td.cell-actions { justify-content: flex-end; }
    .table:not(.table-flat) td.cell-actions::before { content: ""; flex: 0; }
    .table:not(.table-flat) .cell-numeric { text-align: left; }
    .table:not(.table-flat) tr:last-child td { border-bottom: 0; }
}

/* -------------------------------------------------------- สถานะกำลังโหลด */
.skeleton {
    background: linear-gradient(90deg, var(--color-neutral-soft) 25%, var(--color-surface-muted) 37%, var(--color-neutral-soft) 63%);
    background-size: 400% 100%;
    animation: skeleton-sweep 1.4s ease infinite;
    border-radius: var(--radius-sm);
    display: block;
}

.skeleton-text { height: var(--font-size-sm); margin-bottom: var(--space-2); }
.skeleton-title { height: var(--font-size-lg); width: 40%; margin-bottom: var(--space-3); }
.skeleton-block { height: var(--space-7); }

@keyframes skeleton-sweep { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ------------------------------------------------------------ สถานะผิดพลาด
   ‼️ ต้องบอกสาเหตุและวิธีแก้ ไม่ใช่แค่ "เกิดข้อผิดพลาด" (design.md ข้อ 3.5) */
.error-state { text-align: center; padding: var(--space-6) var(--space-4); }

.error-state-icon {
    width: var(--space-7);
    height: var(--space-7);
    border-radius: var(--radius-pill);
    background: var(--color-danger-soft);
    color: var(--color-danger);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-bottom: var(--space-3);
}

.error-state h3 { color: var(--color-text); }
.error-state p { color: var(--color-text-muted); }

/* ================================================== ฟอร์ม: ส่วนขยาย v2 == */

.form-section { padding-bottom: var(--space-4); }
.form-section + .form-section { border-top: var(--border-width) solid var(--color-border); padding-top: var(--space-4); }
.form-section-head { margin-bottom: var(--space-3); }
.form-section-head h3 { margin-bottom: var(--space-1); font-size: var(--font-size-base); }
.form-section-head p { margin: 0; font-size: var(--font-size-sm); color: var(--color-text-muted); }

.form-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.field-optional { font-size: var(--font-size-xs); color: var(--color-text-muted); font-weight: var(--font-weight-normal); margin-left: var(--space-1); }
.field-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }

.char-counter { font-size: var(--font-size-xs); color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
.char-counter.is-over { color: var(--color-danger); font-weight: var(--font-weight-medium); }

.input.is-success, .select.is-success, .textarea.is-success { border-color: var(--color-success); }
.input.is-warning, .select.is-warning, .textarea.is-warning { border-color: var(--color-warning); }
.field-success { font-size: var(--font-size-xs); color: var(--color-success); display: flex; align-items: center; gap: var(--space-1); }
.field-warning { font-size: var(--font-size-xs); color: var(--color-warning); display: flex; align-items: center; gap: var(--space-1); }
.field-error { display: flex; align-items: center; gap: var(--space-1); }
.field-success .icon, .field-warning .icon, .field-error .icon { width: var(--font-size-sm); height: var(--font-size-sm); flex: none; }

/* อ่านอย่างเดียว — ต้องแยกจากช่องที่ปิดใช้งานด้วยสายตา (ยังคัดลอกค่าได้) */
.input[readonly], .textarea[readonly] {
    background: var(--color-surface-muted);
    border-style: dashed;
    color: var(--color-text);
}

.field.is-loading .input,
.field.is-loading .select,
.field.is-loading .textarea { opacity: .6; pointer-events: none; }

/* สวิตช์เปิด/ปิด */
.switch { display: flex; align-items: center; gap: var(--space-3); cursor: pointer; font-size: var(--font-size-sm); }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }

.switch-track {
    position: relative;
    width: 44px;
    height: 24px;
    border-radius: var(--radius-pill);
    background: var(--color-border-strong);
    flex: none;
    transition: background var(--transition-base);
}

.switch-track::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 20px;
    height: 20px;
    border-radius: var(--radius-pill);
    background: var(--color-surface);
    box-shadow: var(--shadow-sm);
    transition: transform var(--transition-base);
}

.switch input:checked + .switch-track { background: var(--btn-primary-bg); }
.switch input:checked + .switch-track::after { transform: translateX(20px); }
.switch input:focus-visible + .switch-track { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.switch input:disabled + .switch-track { background: var(--color-neutral-soft); }
.switch-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.switch-hint { font-size: var(--font-size-xs); color: var(--color-text-muted); }

.check-card {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    background: var(--color-surface);
    font-size: var(--font-size-sm);
    cursor: pointer;
}

.check-card:hover { border-color: var(--color-primary-border); }
.check-card:has(input:checked) { border-color: var(--color-primary); background: var(--color-primary-soft); }
.check-card input { margin-top: 3px; accent-color: var(--color-primary); flex: none; }

/* ช่องกรอกที่มีคำนำหน้า/ต่อท้ายติดกัน เช่น slug ของหน้าเว็บ */
.input-joined { display: flex; align-items: stretch; width: 100%; }

.input-joined > .input-joined-affix {
    display: inline-flex;
    align-items: center;
    padding: 0 var(--space-2);
    background: var(--color-surface-muted);
    border: var(--border-width) solid var(--color-border-strong);
    color: var(--color-text-muted-on-soft);
    font-size: var(--font-size-sm);
    white-space: nowrap;
}

.input-joined > .input-joined-affix:first-child { border-radius: var(--radius-base) 0 0 var(--radius-base); border-right: 0; }
.input-joined > .input-joined-affix:last-child { border-radius: 0 var(--radius-base) var(--radius-base) 0; border-left: 0; }
.input-joined > .input { border-radius: 0; min-width: 0; }
.input-joined > .input:first-child { border-radius: var(--radius-base) 0 0 var(--radius-base); }
.input-joined > .input:last-child { border-radius: 0 var(--radius-base) var(--radius-base) 0; }

/* ช่องกรอกป้ายกำกับหลายค่า — ค่าจริงส่งเป็นข้อความคั่นจุลภาคช่องเดียว
   ‼️ ปิด JavaScript แล้วยังใช้ได้ (กลายเป็นช่องข้อความธรรมดา) */
.tag-input {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    min-height: var(--height-input);
    padding: var(--space-1);
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-base);
    background: var(--color-surface);
    cursor: text;
}

.tag-input:focus-within { border-color: var(--color-primary); box-shadow: 0 0 0 3px var(--color-primary-soft); }

.tag-input-entry {
    flex: 1 1 100px;
    min-width: 80px;
    border: 0;
    outline: none;
    font-family: inherit;
    font-size: var(--font-size-sm);
    background: transparent;
    color: var(--color-text);
    height: var(--space-5);
}

.tag-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: var(--space-4);
    padding: 0 var(--space-1) 0 var(--space-2);
    border-radius: var(--radius-pill);
    background: var(--color-primary-soft);
    color: var(--color-primary-strong);
    font-size: var(--font-size-xs);
}

.tag-chip button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--space-3);
    height: var(--space-3);
    border: 0;
    border-radius: var(--radius-pill);
    background: transparent;
    color: inherit;
    cursor: pointer;
    padding: 0;
}

.tag-chip button:hover { background: var(--color-primary-border); }
.tag-chip .icon { width: 12px; height: 12px; }

.repeater { display: flex; flex-direction: column; gap: var(--space-2); }

.repeater-row {
    display: flex;
    align-items: flex-end;
    gap: var(--space-2);
    padding: var(--space-2);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    background: var(--color-surface-muted);
}

.repeater-row > .field { flex: 1 1 160px; min-width: 0; }

/* แถบปุ่มบันทึกที่ติดขอบล่าง — ต้องไม่บังเนื้อหาบรรทัดสุดท้าย */
.sticky-actions {
    position: sticky;
    bottom: 0;
    z-index: 15;
    background: var(--color-surface);
    border-top: var(--border-width) solid var(--color-border);
    padding: var(--space-3) var(--space-4);
    margin: var(--space-4) calc(var(--space-4) * -1) calc(var(--space-4) * -1);
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.sticky-actions .sticky-actions-note { margin-right: auto; font-size: var(--font-size-sm); color: var(--color-text-muted); }

/* ปุ่มที่กำลังส่งฟอร์ม — กันกดซ้ำและบอกว่ากำลังทำงานอยู่ */
.btn.is-busy { position: relative; color: transparent !important; pointer-events: none; }

.btn.is-busy::after {
    content: "";
    position: absolute;
    width: var(--space-3);
    height: var(--space-3);
    border: 2px solid var(--color-text-inverse);
    border-top-color: transparent;
    border-radius: var(--radius-pill);
    animation: spin 700ms linear infinite;
}

.btn-secondary.is-busy::after,
.btn-ghost.is-busy::after { border-color: var(--color-text); border-top-color: transparent; }

/* =========================================== อัปโหลดไฟล์ (ส่วนประกอบกลาง)
   ‼️ ช่อง <input type="file"> ของเบราว์เซอร์ยังอยู่ในฟอร์มจริงเสมอ
      ถูกซ่อนเฉพาะเมื่อ JavaScript ทำงาน (คลาส is-enhanced) — ปิด JS แล้วยังอัปโหลดได้
   ‼️ การตรวจไฟล์ฝั่งเบราว์เซอร์เป็นแค่การช่วยผู้ใช้ ฝั่งเซิร์ฟเวอร์ยังตรวจซ้ำทุกครั้ง */
.uploader { display: flex; flex-direction: column; gap: var(--space-3); }

.uploader-drop {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-5) var(--space-4);
    border: 2px dashed var(--color-border-strong);
    border-radius: var(--radius-lg);
    background: var(--color-surface-muted);
    text-align: center;
    cursor: pointer;
    transition: border-color var(--transition-base), background var(--transition-base);
}

.uploader-drop:hover { border-color: var(--color-primary); background: var(--color-primary-soft); }
.uploader-drop.is-dragover { border-color: var(--color-primary); background: var(--color-primary-soft); border-style: solid; }
.uploader-drop.is-invalid { border-color: var(--color-danger); background: var(--color-danger-soft); }

.uploader-icon {
    width: var(--space-6);
    height: var(--space-6);
    border-radius: var(--radius-pill);
    background: var(--color-primary-soft);
    color: var(--color-primary-strong);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.uploader-title { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--color-text); }
.uploader-hint { font-size: var(--font-size-xs); color: var(--color-text-muted-on-soft); margin: 0; }

.uploader-rules {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-1) var(--space-3);
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: var(--font-size-xs);
    color: var(--color-text-muted-on-soft);
}

.uploader-rules li { display: flex; align-items: center; gap: var(--space-1); }
.uploader-rules .icon { width: var(--font-size-sm); height: var(--font-size-sm); flex: none; }

.uploader.is-enhanced .uploader-native { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

.uploader-list { display: flex; flex-direction: column; gap: var(--space-2); list-style: none; padding: 0; margin: 0; }

.uploader-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    background: var(--color-surface);
    min-width: 0;
}

.uploader-item.is-error { border-color: var(--color-danger); background: var(--color-danger-soft); }
.uploader-item.is-done { border-color: var(--color-success); }

.uploader-thumb {
    width: var(--space-6);
    height: var(--space-6);
    border-radius: var(--radius-base);
    background: var(--color-neutral-soft);
    color: var(--color-text-muted-on-soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    flex: none;
}

.uploader-thumb img { width: 100%; height: 100%; object-fit: cover; }

.uploader-info { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.uploader-name { font-size: var(--font-size-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uploader-meta { font-size: var(--font-size-xs); color: var(--color-text-muted); }
.uploader-item-actions { display: flex; align-items: center; gap: var(--space-1); flex: none; }

.uploader-progress { height: 4px; border-radius: var(--radius-pill); background: var(--color-neutral-soft); overflow: hidden; margin-top: var(--space-1); }
.uploader-progress > span { display: block; height: 100%; width: 0; background: var(--color-primary); transition: width var(--transition-base); }
.uploader-progress.is-error > span { background: var(--color-danger); }
.uploader-progress.is-done > span { background: var(--color-success); }

.uploader-total { display: flex; align-items: center; gap: var(--space-2); font-size: var(--font-size-sm); color: var(--color-text-muted); }
.uploader-total .progress { flex: 1 1 auto; }

/* ========================================================== ลิ้นชักด้านข้าง
   ‼️ ใช้กับงานที่มีหลายช่องแต่ไม่คุ้มจะเปลี่ยนหน้า — ห้ามซ้อนลิ้นชักในลิ้นชัก */
.drawer-backdrop {
    position: fixed;
    inset: 0;
    background: var(--color-backdrop);
    z-index: 88;
}

.drawer-backdrop[hidden], .drawer[hidden] { display: none; }

.drawer { border-left: var(--border-width) solid var(--color-border); }

.drawer-header {
    padding: var(--space-3) var(--space-4);
    border-bottom: var(--border-width) solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}

.drawer-header h2 { margin: 0; font-size: var(--font-size-lg); }
.drawer-body { padding: var(--space-4); overflow-y: auto; flex: 1 1 auto; }

.drawer-footer {
    padding: var(--space-3) var(--space-4);
    border-top: var(--border-width) solid var(--color-border);
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    flex-wrap: wrap;
}

/* ================================================================ ทัวร์แนะนำ
   ‼️ ขั้นตอนของทัวร์มาจาก PHP ตาม role ที่ล็อกอินอยู่ ทุกบรรทัดผ่าน __() */
.tour-backdrop { position: fixed; inset: 0; background: var(--color-backdrop-strong); z-index: 96; display: flex; align-items: center; justify-content: center; padding: var(--space-3); }
.tour-backdrop[hidden] { display: none; }

.tour-card {
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    width: 100%;
    max-width: 520px;
    overflow: hidden;
}

.tour-media {
    background: var(--color-primary-soft);
    color: var(--color-primary-strong);
    padding: var(--space-5);
    display: flex;
    align-items: center;
    justify-content: center;
}

.tour-media .icon { width: var(--space-7); height: var(--space-7); }
.tour-body { padding: var(--space-4); }
.tour-body h2 { font-size: var(--font-size-lg); }
.tour-body p { color: var(--color-text-muted); margin-bottom: 0; }

.tour-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-top: var(--border-width) solid var(--color-border);
    flex-wrap: wrap;
}

.tour-dots { display: flex; align-items: center; gap: var(--space-1); }
.tour-dot { width: var(--space-2); height: var(--space-2); border-radius: var(--radius-pill); background: var(--color-border-strong); transition: width var(--transition-base), background var(--transition-base); }
.tour-dot.is-active { background: var(--color-primary); width: var(--space-4); }

/* ============================================================== responsive */

@media (max-width: 992px) {
    /* จอกลางลงมาไม่มีโหมดย่อ — ปุ่มเดียวกันกลายเป็นปุ่มเปิดลิ้นชักแทน */
    .app.is-rail { grid-template-columns: minmax(0, 1fr); }
    .app.is-rail .sidebar { padding: var(--space-4) var(--space-3); }
    .app.is-rail .sidebar-brand { justify-content: flex-start; }
    .app.is-rail .sidebar-brand > span,
    .app.is-rail .sidebar-link > span,
    .app.is-rail .sidebar-section-title,
    .app.is-rail .sidebar-card-title span,
    .app.is-rail .sidebar-card-text,
    .app.is-rail .sidebar-card .btn span { display: inline; }
    .app.is-rail .sidebar-link { justify-content: flex-start; padding-left: var(--space-3); }
    .app.is-rail .sidebar-link::before { display: block; }
    .app.is-rail .sidebar-card { padding: var(--space-3); text-align: left; }

    .form-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .donut-layout { justify-content: center; }
}

@media (max-width: 640px) {
    .form-grid-3 { grid-template-columns: minmax(0, 1fr); }
    .stat-strip-item { border-right: 0; padding-right: 0; flex-basis: 42%; }
    .toolbar { padding: var(--space-2); }
    .toolbar-field, .toolbar-search { flex-basis: 100%; }
    .toolbar-actions { width: 100%; }
    .toolbar-actions .btn { flex: 1 1 auto; }
    .site-card-grid { grid-template-columns: minmax(0, 1fr); }
    .tile-grid { grid-template-columns: minmax(0, 1fr); }
    .sticky-actions { margin: var(--space-3) calc(var(--space-3) * -1) calc(var(--space-3) * -1); padding: var(--space-2) var(--space-3); }
    .sticky-actions .btn { flex: 1 1 auto; }
    .sticky-actions .sticky-actions-note { flex-basis: 100%; margin-bottom: var(--space-1); }
    .repeater-row { flex-wrap: wrap; }
    .donut { width: 140px; height: 140px; }
    .drawer { width: 100%; }
}

/* ======================================= หน้าที่ยังไม่ล็อกอิน: กฎเพิ่มเติม v2
   ‼️ ต้องอยู่ท้ายไฟล์เพื่อทับกฎ responsive ชุดเดิมของ auth ที่เขียนไว้ก่อนหน้า
   เป้าหมายความสูง: ที่ 1366x768 สถานะปกติต้องเห็นครบโดยไม่ต้องเลื่อน
   และห้ามใช้ overflow:hidden หรือ transform:scale() มาบังคับ */

/* จอเตี้ย (แล็ปท็อป 768px ลงมา) — บีบระยะห่างแทนการย่อขนาดตัวอักษรทั้งหน้า */
@media (min-width: 993px) and (max-height: 820px) {
    .auth-aside { padding: var(--space-4) var(--space-5) 0; gap: var(--space-3); }
    .auth-aside-top { gap: var(--space-2); }
    .auth-headline { font-size: var(--font-size-2xl); }
    .auth-features { gap: var(--space-2); }
    .auth-feature-icon { width: 2.25rem; height: 2.25rem; }
    .auth-artwork { max-width: 28rem; }
    .auth-main { padding: var(--space-2) var(--space-4) var(--space-4); }
    .auth-card { padding: var(--space-4); gap: var(--space-3); }
    .auth-title { font-size: var(--font-size-xl); }
}

/* จอเตี้ยมาก — ตัดคำอธิบายรองของรายการคุณสมบัติออกก่อน แล้วค่อยตัดภาพ */
@media (min-width: 993px) and (max-height: 700px) {
    .auth-feature-hint { display: none; }
    .auth-artwork { display: none; }
    .auth-aside { justify-content: flex-start; }
}

@media (max-width: 992px) {
    /* แท็บเล็ต: ลดข้อความและภาพผลิตภัณฑ์ก่อน แต่ยังคงแถบแบรนด์ไว้ */
    .auth-aside::after { display: none; }
    .auth-aside { border-right: 0; border-bottom: var(--border-width) solid var(--color-border); }
    .auth-headline { font-size: var(--font-size-2xl); }
}

@media (max-width: 640px) {
    /* มือถือ: เหลือแถบแบรนด์บางๆ กับฟอร์มเต็มความกว้าง และต้องเลื่อนได้เมื่อคีย์บอร์ดเปิด */
    .auth-shell { min-height: 100dvh; }
    .auth-aside { padding: var(--space-3); gap: 0; }
    .auth-aside::before { display: none; }
    .auth-headline { display: none; }
    .auth-badge { display: none; }
    .auth-card { padding: var(--space-4); box-shadow: none; border-radius: var(--radius-lg); }
    .auth-grid-2 { grid-template-columns: minmax(0, 1fr); }
}

/* สีของวงแหวนและจุดกำกับ — ไล่ตามลำดับเท่านั้น (ค่าจริงอยู่ที่ :root ข้างบน) */
.donut-slice-s1 { stroke: var(--chart-1); }
.donut-slice-s2 { stroke: var(--chart-2); }
.donut-slice-s3 { stroke: var(--chart-3); }
.donut-slice-s4 { stroke: var(--chart-4); }
.donut-slice-s5 { stroke: var(--chart-5); }

.legend-swatch-s1 { background: var(--chart-1); }
.legend-swatch-s2 { background: var(--chart-2); }
.legend-swatch-s3 { background: var(--chart-3); }
.legend-swatch-s4 { background: var(--chart-4); }
.legend-swatch-s5 { background: var(--chart-5); }

/* ‼️ ปุ่มแจ้งปัญหาลอยอยู่มุมขวาล่างทุกหน้า — บนหน้าที่ยังไม่ล็อกอินมันจะไปทับบรรทัดล่างสุดของการ์ด
   เว้นที่ให้มันด้วยการดันการ์ดขึ้น ไม่ใช่ย้ายปุ่มไปที่อื่น (ปุ่มต้องอยู่ตำแหน่งเดิมทุกหน้าของระบบ) */
@media (min-width: 993px) {
    .auth-main { padding-bottom: var(--space-7); }
}

/* จอเตี้ยบีบระยะห่างในการ์ดลงอีกขั้น เพื่อให้ฟอร์มสมัคร (5 ช่อง) พอดี 768px โดยไม่ต้องตัดช่องใดออก */
@media (min-width: 993px) and (max-height: 820px) {
    .auth-card { gap: var(--space-2); }
    .auth-head { gap: var(--space-1); }
    .auth-card-mark { width: 2.25rem; height: 2.25rem; }
    .auth-topbar { margin-bottom: var(--space-1); }
}

/* ‼️ ปุ่มแรก (แก้ไข) ยืดได้ ปุ่มที่สอง (เปิดเว็บ) กว้างตามข้อความ
   ถ้าแบ่งครึ่งเท่ากัน ข้อความภาษาอังกฤษที่ยาวกว่าจะถูกตัดหายทันที */
.site-card-footer > *:first-child { flex: 1 1 auto; }
.site-card-footer > *:last-child { flex: 0 1 auto; }
.site-card-footer > * { min-width: 0; }

/* ‼️ การ์ดรูปในคลังต้องกว้างพอให้ช่องคำอธิบายภาพใช้งานได้จริง
   ของเดิม 160px ทำให้ช่องกรอกเหลือความกว้างไม่ถึงครึ่งคำ */
.media-grid { grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); }
.media-item { border-radius: var(--radius-lg); box-shadow: var(--shadow-card); }
.media-thumb { aspect-ratio: 3 / 2; }
.media-meta { padding: var(--space-3); gap: var(--space-2); }
.media-meta .input { font-size: var(--font-size-xs); }

/* ‼️ เมนูคำสั่งประจำแถวที่อยู่ในตารางซึ่งเลื่อนแนวนอนได้ ต้อง "ลอย" ออกมานอกกรอบ
   ไม่งั้นแถวท้ายๆ จะถูกกรอบตัดจนกดคำสั่งไม่ได้ · ตำแหน่งคำนวณจาก JS ตอนเปิด */
.row-menu-panel.is-floating { position: fixed; }

/* แถบตัวเลขที่อยู่ใน card-body อยู่แล้ว ไม่ต้องเว้นระยะซ้ำอีกชั้น */
.card-body > .stat-strip { padding: 0; }

/* ================================================================ โหมดมืด
   ‼️ ไม่มี CSS ชุดที่สอง — โหมดมืดคือการเขียนทับ token ชุดเดิมเท่านั้น
      กฎทุกบรรทัดในไฟล์นี้อ้าง var(--…) อยู่แล้ว จึงเปลี่ยนตามได้ทั้งระบบโดยไม่ต้องแตะกฎใดเลย
      ถ้าวันไหนมีคนเขียนค่าสีดิบลงในกฎ จุดนั้นจะค้างเป็นสีของโหมดสว่างทันที (ห้ามทำ)

   ‼️ ขอบเขต: ระบบจัดการและหน้าที่ยังไม่ล็อกอินเท่านั้น
      เว็บไซต์ของลูกค้า, Editor canvas, Preview และเว็บที่ publish แล้ว ใช้ site.css คนละไฟล์
      และไม่มี attribute data-theme บน <html> จึงไม่ได้รับผลจากบล็อกนี้โดยโครงสร้าง

   ‼️ พื้นเป็นกรมท่า/สเลท ไม่ใช่ดำสนิท — ดำสนิทกับตัวอักษรขาวได้ contrast สูงเกินจนอ่านนาน ๆ แล้วล้า
      และทำให้แบรนด์กรมท่าหายไปทั้งหมด

   ‼️ ทุกคู่สีในบล็อกนี้ตรวจด้วย WCAG 2.1 แล้ว ตัวเลขกำกับไว้ท้ายบรรทัดที่สำคัญ
      ตรวจซ้ำอัตโนมัติด้วย scripts/check-screens.php ซึ่งเดินทั้งสองธีม */
:root[data-theme="dark"] {
    /* ---- สีแบรนด์ ----
       ‼️ กลับด้านจากโหมดสว่าง: ที่นั่น --color-primary-strong คือส้ม "เข้มขึ้น" เพื่อให้อ่านออกบนพื้นขาว
          ที่นี่ต้องส้ม "สว่างขึ้น" ด้วยเหตุผลเดียวกันแต่กลับทาง (#FF8A3D บนการ์ด = 6.94:1)
          ส้มแบรนด์ตัวจริง #E8590C บนพื้นเข้มได้ 3.96:1 จึงใช้เป็นตัวอักษรไม่ได้ ใช้ได้แค่เป็นพื้น */
    --color-primary:        #E8590C;
    --color-primary-strong: #FF8A3D;
    --color-primary-hover:  #FFA463;
    --color-primary-soft:   #33200F;
    --color-primary-border: #5A3218;
    /* ‼️ ยังเป็นกรมท่าในโหมดนี้ เพราะถูกใช้เป็น "พื้น" (ปุ่มลอย, บล็อกโค้ด, รูปทรงตกแต่งของหน้าล็อกอิน)
          สว่างขึ้นแค่พอให้แยกออกจากพื้นหน้า · ที่ใช้เป็น "ตัวอักษร" ใช้ --color-secondary-text แทน
    --color-secondary:      #22304E;
    --color-secondary-soft: #1C2740;

    /* ---- พื้นเข้มของหน้าแนะนำผลิตภัณฑ์ ----
       ‼️ ชุดนี้ถูกออกแบบมาสำหรับพื้นกรมท่าอยู่แล้ว จึงแทบไม่ต้องแก้
          ยกเว้น --color-device-edge ที่เป็นเส้นขอบอุปกรณ์บนพื้นสว่าง */
    --color-device-edge: #3A4763;

    /* ---- พื้นผิว ---- */
    --color-bg:            #0E1626;
    --color-surface:       #162034;
    --color-surface-muted: #1B2740;
    /* เส้นตกแต่งไม่ต้องผ่าน 3:1 (ไม่ใช่ขอบเขตของ control) แต่ต้องมองเห็นว่ามีเส้น */
    --color-border:        #2A3652;
    /* ‼️ ตัวนี้เป็นขอบของช่องกรอกและปุ่ม จึงต้องผ่าน 1.4.11 ที่ 3:1
       #6B7A95 บนช่องกรอก = 3.43:1 · บนการ์ด = 3.75:1 · บนพื้นแอป = 4.17:1 */
    --color-border-strong: #6B7A95;
    --color-text:          #E7ECF5;   /* บนการ์ด 13.73:1 */
    --color-text-muted:    #A3B0C6;   /* บนการ์ด 7.43:1 · บนพื้นนุ่ม 6.79:1 */
    --color-text-muted-on-soft: #B3BFD3;   /* บนพื้นนุ่ม 8.02:1 */
    --color-text-inverse:  #FFFFFF;

    /* ---- สี semantic ----
       ‼️ ยังสงวนไว้สื่อสถานะเท่านั้น ห้ามเอาไปตกแต่ง เหมือนโหมดสว่างทุกประการ
          ค่าเดิมของโหมดสว่างเป็นเฉดเข้มทั้งชุด ซึ่งบนพื้นมืดอ่านไม่ออกเลย จึงต้องสว่างขึ้นทั้งชุด */
    --color-success:      #6FD6AE;   /* บนการ์ด 9.23:1 · บนพื้นของตัวเอง 9.03:1 */
    --color-success-soft: #10261E;
    --color-warning:      #F0BE5C;   /* 9.47:1 · 9.24:1 */
    --color-warning-soft: #2A2110;
    --color-danger:       #FF8A8A;   /* 7.17:1 · 7.53:1 */
    --color-danger-soft:  #2E1418;
    --color-info:         #7FB6EA;   /* 7.58:1 · 7.30:1 */
    --color-info-soft:    #12243A;
    --color-neutral:      #B3BFD3;   /* 8.77:1 · 7.98:1 */
    --color-neutral-soft: #1E2839;

    /* ---- เงา ----
       ‼️ เงาสีเทาโปร่งบนพื้นมืดมองไม่เห็นเลย ต้องเป็นสีดำและทึบกว่าเดิม
          ไม่งั้นการ์ดทุกใบจะดูแบนติดกันไปหมดจนแยกไม่ออกว่าอะไรซ้อนอยู่บนอะไร */
    --shadow-sm:     0 1px 2px rgba(0, 0, 0, .40);
    --shadow-base:   0 2px 8px rgba(0, 0, 0, .45);
    --shadow-lg:     0 12px 32px rgba(0, 0, 0, .55);
    --shadow-device: 0 24px 60px rgba(0, 0, 0, .65);
    --shadow-card:   0 1px 2px rgba(0, 0, 0, .30), 0 1px 3px rgba(0, 0, 0, .35);
    --shadow-pop:    0 8px 24px rgba(0, 0, 0, .50);

    /* ---- โทนสีของชิปไอคอน ----
       ‼️ ข้อยกเว้นที่ผู้ใช้อนุมัติไว้ (CLAUDE.md ข้อ 1.5) ยังเป็นแบบเดิม: ต่างกันได้เฉพาะชิปไอคอน
          พื้นการ์ดทุกใบยังเป็นสีเดียวกันหมด และในโหมดนี้คือ --color-surface */
    --tint-brand-bg:  #33200F;  --tint-brand-fg:  #FF8A3D;
    --tint-green-bg:  #10261E;  --tint-green-fg:  #6FD6AE;
    --tint-violet-bg: #1E1938;  --tint-violet-fg: #B7A6F5;
    --tint-blue-bg:   #12243A;  --tint-blue-fg:   #7FB6EA;
    --tint-slate-bg:  #1E2839;  --tint-slate-fg:  #B3BFD3;

    /* ---- สีของกราฟ ----
       ‼️ ลำดับต้องเหมือนโหมดสว่างเป๊ะ ๆ (ส้ม → ม่วง → เขียว → น้ำเงิน → เทา)
          ผู้ใช้ที่จำได้ว่า "เส้นส้มคือผู้เข้าชม" ต้องจำแบบเดิมได้ในทั้งสองธีม */
    --chart-1: #FF8A3D;
    --chart-2: #A48BF5;
    --chart-3: #6FD6AE;
    --chart-4: #7FB6EA;
    --chart-5: #64728C;
    --chart-grid: #26314A;

    /* ---- ค่าที่ยกขึ้นมาเป็น token ---- */
    /* ‼️ ทึบขึ้นกว่าโหมดสว่าง เพราะพื้นข้างหลังเข้มอยู่แล้ว ถ้าใช้ความทึบเท่าเดิม
          จะแยกไม่ออกว่าอะไรอยู่หน้าอะไร แล้ว modal จะดูเหมือนเป็นส่วนหนึ่งของหน้า */
    --color-backdrop:        rgba(4, 8, 16, .70);
    --color-backdrop-strong: rgba(4, 8, 16, .76);
    /* แผงแบรนด์ของหน้าล็อกอิน — พื้นครีมกลายเป็นกรมท่าไล่เฉด ยังเป็นแบรนด์เดิม */
    --auth-aside-bg:   linear-gradient(160deg, #16223C 0%, #101A2E 46%, #1D2438 100%);
    --auth-aside-glow: radial-gradient(circle, rgba(232, 89, 12, .22), transparent 64%);
}

/* ‼️ ปุ่มหลักเป็นจุดเดียวที่ใช้สีแบรนด์เป็น "พื้น" ไม่ใช่ "ตัวอักษร"
      จึงต้องมี token ของตัวเอง ไม่งั้นในโหมดมืดปุ่มจะกลายเป็นส้มสว่างพร้อมตัวอักษรขาว = 2.1:1
      ค่าของโหมดสว่างเท่ากับพฤติกรรมเดิมทุกประการ หน้าตาโหมดสว่างจึงไม่เปลี่ยนแม้แต่พิกเซลเดียว */
:root {
    --btn-primary-bg:       var(--color-primary-strong);
    --btn-primary-bg-hover: var(--color-primary-hover);
    --btn-primary-fg:       var(--color-text-inverse);
    /* สีรองของแบรนด์เมื่อใช้เป็นตัวอักษร — ค่าเท่ากับพฤติกรรมเดิมทุกประการ */
    --color-secondary-text: var(--color-secondary);
    /* สี semantic เมื่อใช้เป็น "พื้นที่มีตัวอักษรทับ" — ค่าเท่ากับพฤติกรรมเดิมทุกประการ */
    --solid-danger-bg:  var(--color-danger);
    --solid-danger-fg:  var(--color-text-inverse);
    --solid-warning-bg: var(--color-warning);
    --solid-warning-fg: var(--color-text-inverse);
    --solid-info-bg:    var(--color-info);
    --solid-info-fg:    var(--color-text-inverse);
}

:root[data-theme="dark"] {
    /* ส้มแบรนด์เต็ม ๆ กับตัวอักษรเกือบดำ = 5.29:1 (hover 7.28:1)
       เลือกทางนี้แทนการทำให้ปุ่มมืดลง เพราะปุ่มหลักต้องเด่นที่สุดในหน้าเสมอ */
    --btn-primary-bg:       #E8590C;
    --btn-primary-bg-hover: #FF7A2E;
    --btn-primary-fg:       #1A0E04;
    /* ‼️ สีรองของแบรนด์เมื่อใช้เป็นตัวอักษร ต้องสว่างขึ้นจนอ่านออกบนพื้นมืด
          ส่วนที่ใช้เป็นพื้น (ปุ่มลอย, บล็อกโค้ด) ยังเป็นกรมท่าเหมือนเดิม */
    --color-secondary-text: #C6D3EA;
    /* ‼️ ยังเป็นเฉดเข้มเหมือนโหมดสว่าง เพราะมีตัวอักษรขาวทับอยู่
          ถ้าใช้เฉดสว่างเดียวกับตัวอักษร (--color-danger ฯลฯ) ปุ่มลบจะได้ 2.27:1
          สว่างขึ้นเล็กน้อยเฉพาะเท่าที่ยังคุมตัวอักษรขาวให้ผ่าน AA ได้ */
    --solid-danger-bg:  #D13B3B;   /* ขาวบนพื้นนี้ 4.77:1 */
    --solid-danger-fg:  #FFFFFF;
    --solid-warning-bg: #92610F;   /* 5.33:1 */
    --solid-warning-fg: #FFFFFF;
    --solid-info-bg:    #2A6FB5;   /* 5.20:1 */
    --solid-info-fg:    #FFFFFF;
}

.btn-primary {
    background: var(--btn-primary-bg);
    border-color: var(--btn-primary-bg);
    color: var(--btn-primary-fg);
}

.btn-primary:hover {
    background: var(--btn-primary-bg-hover);
    border-color: var(--btn-primary-bg-hover);
    color: var(--btn-primary-fg);
}

/* ================================================================ ปุ่มสลับธีม
   ‼️ ไอคอนทั้งสองอยู่ในหน้าพร้อมกันตั้งแต่แรก แล้วซ่อนทีละตัวตาม data-theme
      ถ้าให้ JavaScript สร้างไอคอนตอนกด จะเห็นไอคอนหายไปหนึ่งเฟรมทุกครั้ง */
.theme-toggle { flex: none; }
.theme-toggle .theme-toggle-sun,
.theme-toggle .theme-toggle-moon { display: none; line-height: 0; }

/* โหมดสว่างอยู่ → โชว์ดวงจันทร์ เพราะปุ่มบอก "ผลลัพธ์หลังกด" ไม่ใช่สถานะตอนนี้ */
:root:not([data-theme="dark"]) .theme-toggle .theme-toggle-moon { display: inline-flex; }
:root[data-theme="dark"] .theme-toggle .theme-toggle-sun { display: inline-flex; }

/* ‼️ ปุ่มนี้อยู่บนแถบบนของหน้าที่ยังไม่ล็อกอินด้วย ซึ่งไม่มีพื้นการ์ดรองอยู่
      จึงต้องมีสีตัวอักษรของตัวเองไม่พึ่งบริบท */
.auth-topbar .theme-toggle { color: var(--color-text-muted); }
.auth-topbar .theme-toggle:hover { color: var(--color-text); background: var(--color-neutral-soft); }

/* ============================================ ช่องเลือกที่ค้นหาได้ (combobox)
   ‼️ ส่วนประกอบกลางตัวเดียวของทั้งระบบ · ห้ามสร้างแบบอื่นกระจายตามหน้า
   ‼️ ทุกค่าเป็น token — โหมดมืดจึงเปลี่ยนตามเองโดยไม่มีกฎเพิ่มแม้แต่บรรทัดเดียว
   ‼️ .is-enhanced ถูกใส่โดย JS เท่านั้น · ปิด JS แล้วจะเหลือ <select> ปกติที่ใช้งานได้ครบ */
.combobox { position: relative; }

/* ‼️ ห้ามใช้ display:none กับ <select> ตัวจริง
      เบราว์เซอร์ปฏิเสธการ submit เมื่อ field ที่ required อยู่ในสภาพ "โฟกัสไม่ได้"
      แล้วขึ้นแค่ error ใน console โดยผู้ใช้ไม่เห็นอะไรเลย
      จึงย่อให้เหลือ 1px โปร่งใสแทน — ยังโฟกัสได้ ยัง validate ได้ ยังถูกส่งไปกับฟอร์ม */
.combobox.is-enhanced > select {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

.combobox-control {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    width: 100%;
    min-height: var(--height-input);
    padding: 0 var(--space-1) 0 var(--space-2);
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-base);
    background: var(--color-surface);
    cursor: text;
    transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.combobox-control:hover { border-color: var(--color-text-muted); }

.combobox.is-open .combobox-control,
.combobox-control:focus-within {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-soft);
}

.combobox.has-error .combobox-control { border-color: var(--color-danger); }

/* ‼️ ปิดใช้งานต้องดูออกว่ากดไม่ได้ โดยไม่พึ่งสีอย่างเดียว — เคอร์เซอร์เปลี่ยนด้วย */
.combobox.is-disabled .combobox-control {
    background: var(--color-neutral-soft);
    border-color: var(--color-border);
    cursor: not-allowed;
}

.combobox-input {
    flex: 1 1 auto;
    min-width: 0;
    height: calc(var(--height-input) - 2px);
    border: 0;
    outline: none;
    background: transparent;
    color: var(--color-text);
    font-family: inherit;
    font-size: var(--font-size-sm);
    text-overflow: ellipsis;
}

.combobox-input:disabled { cursor: not-allowed; }

/* ‼️ ตอนยังไม่พิมพ์ค้นหา ช่องนี้แสดง "ค่าที่เลือกอยู่" เป็น placeholder
      จึงต้องเข้มเท่าข้อความจริง ไม่ใช่สีจาง ๆ แบบ placeholder ทั่วไป
      ถ้าจางผู้ใช้จะอ่านว่ายังไม่ได้เลือกอะไร ทั้งที่เลือกไว้แล้ว */
.combobox-input::placeholder { color: var(--color-text-muted); opacity: 1; }
.combobox-input.has-selection::placeholder { color: var(--color-text); opacity: 1; }

.combobox-button,
.combobox-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 32px ผ่านเกณฑ์เป้าสัมผัสของ WCAG 2.2 AA (24px) พร้อมระยะเผื่อ */
    width: 32px;
    height: 32px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
}

.combobox-button:hover,
.combobox-clear:hover { background: var(--color-neutral-soft); color: var(--color-text); }

.combobox-button:focus-visible,
.combobox-clear:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }

.combobox.is-disabled .combobox-button,
.combobox.is-disabled .combobox-clear { cursor: not-allowed; }

.combobox-button .icon,
.combobox-clear .icon { width: var(--font-size-sm); height: var(--font-size-sm); }

.combobox.is-open .combobox-button .icon { transform: rotate(180deg); }

.combobox-list {
    position: absolute;
    z-index: 60;
    left: 0;
    right: 0;
    top: calc(100% + var(--space-1));
    max-height: 280px;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    box-shadow: var(--shadow-pop);
    padding: var(--space-1);
    list-style: none;
    margin: 0;
}

.combobox-list[hidden] { display: none; }

/* ‼️ JS เปลี่ยนเป็น fixed ตอนเปิด แล้วคำนวณตำแหน่งเอง (วิธีเดียวกับเมนูประจำแถวของตาราง)
      เพราะรายการอาจอยู่ในการ์ด แผง หรือ modal ที่ overflow ตัดขอบ
      และต้องพลิกขึ้นบนเองเมื่อที่ด้านล่างไม่พอ — ตำแหน่งจริงมาจาก JS ไม่ใช่ที่นี่ */
.combobox-list.is-floating { position: fixed; right: auto; }

.combobox-option {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-sm);
    color: var(--color-text);
    cursor: pointer;
    min-height: 36px;
}

.combobox-option:hover,
.combobox-option.is-active { background: var(--color-surface-muted); }

/* ‼️ ตัวที่เลือกอยู่ต้องดูออกโดยไม่พึ่งสีอย่างเดียว จึงมีเครื่องหมายถูกกำกับด้วย */
.combobox-option.is-selected {
    background: var(--color-primary-soft);
    color: var(--color-primary-strong);
    font-weight: var(--font-weight-medium);
}

.combobox-option-check { flex: none; width: var(--font-size-sm); height: var(--font-size-sm); opacity: 0; }
.combobox-option.is-selected .combobox-option-check { opacity: 1; }

.combobox-option-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ‼️ เน้นเฉพาะส่วนที่ตรงกับที่พิมพ์ ให้เห็นว่าทำไมรายการนี้ถึงขึ้นมา
      สร้างด้วย DOM node ไม่ใช่ innerHTML — ป้ายชื่อจากภายนอกจึงกลายเป็นแท็กไม่ได้ */
.combobox-option mark {
    background: transparent;
    color: inherit;
    font-weight: var(--font-weight-bold);
    text-decoration: underline;
}

.combobox-status {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

@media (max-width: 640px) {
    /* ‼️ บนมือถือรายการต้องไม่ล้นจอ — จำกัดตามความสูงจอจริง ไม่ใช่ค่าคงที่
          และแต่ละแถวสูงขึ้นเพราะกดด้วยนิ้ว ไม่ใช่เมาส์ */
    .combobox-list { max-height: min(50dvh, 280px); }
    .combobox-option { min-height: 44px; }
}

/* ============================================ ตัวเลือกรูปภาพ (media picker)
   ‼️ ใช้ token ชุดเดียวกับทั้งระบบ แต่มี class เป็นของตัวเอง ไม่ยืม .combobox-*
      เพราะ combobox ถูก freeze แล้ว — ถ้าผูกกัน การแก้หน้าตาฝั่งรูปภาพจะทำ dropdown ทั้งระบบพัง
   ‼️ .is-enhanced ถูกใส่โดย JS เท่านั้น · ปิด JS แล้วจะเหลือ <select> + รูปที่เลือกอยู่ ซึ่งส่งฟอร์มได้ครบ */
.media-picker { position: relative; }

/* ‼️ เหตุผลเดียวกับ combobox: ห้าม display:none กับ <select> ที่ required
      ไม่งั้นเบราว์เซอร์จะปฏิเสธการ submit เงียบ ๆ โดยผู้ใช้ไม่เห็นอะไรเลย */
.media-picker.is-enhanced > select {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

/* ปิด JS = ไม่มีปุ่ม ต้องบอกตรง ๆ · เปิด JS = ซ่อนคำอธิบายนั้นเพราะกดปุ่มได้แล้ว */
.media-picker.is-enhanced ~ .media-picker-nojs,
.field:has(.media-picker.is-enhanced) > .media-picker-nojs { display: none; }

.media-picker-current {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    min-height: 64px;
    padding: var(--space-2);
    border: var(--border-width) solid var(--color-border-strong);
    border-radius: var(--radius-base);
    background: var(--color-surface);
}

.media-picker.has-error .media-picker-current { border-color: var(--color-danger); }

.media-picker-thumb {
    flex: none;
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background: var(--color-surface-muted);
}

.media-picker-thumb-empty {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-muted);
}

.media-picker-current-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.media-picker-current-label { font-size: var(--font-size-sm); color: var(--color-text); }

.media-picker-actions { display: flex; gap: var(--space-1); flex: none; }

/* ---------------------------------------------------------------- แผงเลือก */
.media-picker-panel {
    position: absolute;
    z-index: 60;
    left: 0;
    right: 0;
    top: calc(100% + var(--space-1));
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    max-height: 380px;
    padding: var(--space-2);
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    box-shadow: var(--shadow-pop);
}

.media-picker-panel[hidden] { display: none; }

/* ‼️ JS เปลี่ยนเป็น fixed แล้วคำนวณตำแหน่งเอง — แผงอาจอยู่ในการ์ดที่ overflow ตัดขอบ
      และต้องพลิกขึ้นบนเมื่อที่ด้านล่างไม่พอ (วิธีเดียวกับเมนูประจำแถวของตาราง) */
.media-picker-panel.is-floating { position: fixed; right: auto; }

.media-picker-results {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.media-picker-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    cursor: pointer;
    min-height: 48px;
}

.media-picker-item:hover,
.media-picker-item.is-active { background: var(--color-surface-muted); }

/* ‼️ ตัวที่เลือกอยู่ต้องดูออกโดยไม่พึ่งสีอย่างเดียว จึงมีเครื่องหมายถูกกำกับ */
.media-picker-item.is-selected {
    background: var(--color-primary-soft);
    color: var(--color-primary-strong);
    font-weight: var(--font-weight-medium);
}

.media-picker-item-check { flex: none; width: var(--font-size-sm); height: var(--font-size-sm); opacity: 0; }
.media-picker-item.is-selected .media-picker-item-check { opacity: 1; }

.media-picker-item-thumb {
    flex: none;
    width: 36px;
    height: 36px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background: var(--color-surface-muted);
}

.media-picker-item-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.media-picker-item-label { font-size: var(--font-size-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.media-picker-item-hint { font-size: var(--font-size-xs); color: var(--color-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.media-picker-item mark {
    background: transparent;
    color: inherit;
    font-weight: var(--font-weight-bold);
    text-decoration: underline;
}

/* ------------------------------------------------------- สถานะของเครือข่าย */
.media-picker-status {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-3);
    text-align: center;
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.media-picker-status.is-error { color: var(--color-danger); }
.media-picker-status[hidden] { display: none; }

.media-picker-more { flex: none; }

@media (max-width: 640px) {
    /* ‼️ บนมือถือแผงต้องไม่ล้นจอ และแต่ละแถวใหญ่พอให้กดด้วยนิ้ว */
    .media-picker-panel { max-height: min(60dvh, 380px); }
    .media-picker-item { min-height: 56px; }
}

/* ------------------------------------------ แถบรายละเอียดของงานตามเวลา
   ‼️ อยู่ในตารางเดียวกับแถวของงาน จึงต้องแยกออกจากแถวปกติด้วยพื้นหลัง
      ไม่ใช่ด้วยเส้นขอบเพิ่ม — ตารางนี้มีเส้นแบ่งแถวอยู่แล้ว การเพิ่มเส้นทำให้อ่านยากขึ้น */
.cron-toggle-col { width: var(--height-button); }

.cron-toggle .icon { transition: transform var(--transition-base); }
.cron-toggle.is-open .icon { transform: rotate(90deg); }

.cron-detail-row > td {
    background: var(--color-surface-muted);
    padding: var(--space-4);
}

.cron-panel {
    background: var(--color-surface);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-base);
    padding: var(--space-3);
    min-width: 0;
}

.cron-panel-title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-bold);
    margin: 0 0 var(--space-2);
}

.cron-rate { margin-top: var(--space-3); display: flex; flex-direction: column; gap: var(--space-1); }

.cron-recent { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }

.cron-recent li {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    justify-content: space-between;
    flex-wrap: wrap;
}

/* ‼️ ผลลัพธ์ของงานเป็นข้อความยาวคำเดียวได้ (เช่น key=value ต่อกันรัว ๆ)
      ต้องบังคับตัดคำ ไม่งั้นการ์ดจะยืดจนดันการ์ดใบอื่นเสียทรง */
.cron-output {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-xs);
    margin: 0;
    overflow-wrap: anywhere;
}

.cron-output.is-error { color: var(--color-danger); }

.cron-panel-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-4);
}

.cron-panel-footer-end { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }

.cron-schedule-form { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }

/* ‼️ ช่อง cron ยาวแค่ห้าช่อง ไม่ต้องกินความกว้างทั้งแถว
      ถ้าปล่อยให้ยืดเต็ม ปุ่มบันทึกจะถูกดันตกบรรทัดบนจอแคบโดยไม่จำเป็น */
.cron-schedule-input { max-width: 220px; font-family: var(--font-family-mono); }

@media (max-width: 640px) {
    .cron-detail-row > td { padding: var(--space-3); }
    .cron-schedule-form { width: 100%; }
    .cron-schedule-input { max-width: none; flex: 1 1 100%; }
}