/* ชุดสีกลางของหน้า IOC — ที่เดียวของทั้งระบบ (งาน 004 · ใบงานเรียก tokens.css แต่ชื่อนั้นชนด่านกันไฟล์ความลับของคิว *token* จึงใช้ theme.css)
 *
 * **งาน 335 (โจ 5 ต.ค. 2569): ค่าสีจริงย้ายไปอยู่ที่ระบบดีไซน์ PANN แล้ว** (`/pann-design.css` ตัวแปร `--pann-*`)
 *   ไฟล์นี้กลายเป็น **แผนที่ชื่อ**: ชื่อเดิมที่ 49 หน้าของ IOC ใช้อยู่ (`--primary` `--bg` `--text` …) ชี้มาที่ตัวแปรของระบบดีไซน์
 *   เปลี่ยนสีทั้งระบบจึงทำที่เดียว ไม่ต้องไล่แก้ทีละหน้า · **ห้ามเขียนเลขสี/ฟอนต์/รัศมีตรง ๆ ที่นี่อีก**
 *   ยกเว้นที่มีหมายเหตุกำกับว่าระบบดีไซน์ยังไม่มีชิ้นนั้น (ชุดสีประจำสำนักงาน · ฟอนต์ตัวเลขคงความกว้าง)
 *   สีประจำสินค้าของเรา = `account` (ระบบดีไซน์ v1.2 ของใบ 354: เขียวเข้มจากโลโก้ MSP + มัสตาร์ด PANN)
 *   ตั้งที่ `<html data-product="account">` — ค่าจริงอยู่ใน `pann-design.css` ที่เดียว ห้ามเขียนซ้ำที่นี่
 *
 * หน้าใหม่ห้ามตั้งสีเอง: ใช้ var(--ชื่อ) จากไฟล์นี้หรือ `--pann-*` ตรง ๆ (tests/test_color_tokens.py ตรวจ) · คู่มือ docs/ชุดสีและตัวอักษร.md
 * หน้าบัญชี (msp-deploy/ledger/ ของ msp-ledger) มีชุดสีของตัวเองใน ledger/design.css — ไฟล์นี้ไม่ได้ใช้ที่นั่น
 *   (ใบคู่กันคือ Ledger 323 · nav.css ที่ใช้ร่วมกันจึงยังเขียนแบบ var(--ชื่อเดิม, ค่าสำรอง) ไว้เหมือนเดิม)
 */
:root {
  /* แบรนด์ — มาจากระบบดีไซน์ (data-product="account") ห้ามตั้งค่าเองที่นี่ */
  --primary: var(--pann-brand);
  --primary-light: var(--pann-brand);        /* เดิมเขียวอ่อนกว่า ใช้เป็นขอบตอนโฟกัส — ระบบดีไซน์ใช้สีแบรนด์ตัวเดียว */
  --primary-dark: var(--pann-brand-dark);    /* ปุ่มตอนชี้ */
  --primary-bg: var(--pann-brand-tint);
  --brand-tint: var(--pann-brand-soft);      /* พื้นไล่สีหน้าเข้าสู่ระบบ */
  --on-primary: var(--pann-on-brand);        /* ตัวอักษรบนปุ่มสีแบรนด์/แดง */
  --primary-ink: var(--pann-brand);          /* สีแบรนด์ตอนเป็นตัวอักษร (nav.css เรียกชื่อนี้) */

  /* พื้นและเส้น */
  --bg: var(--pann-bg);
  --surface: var(--pann-surface);            /* การ์ด */
  --surface-2: var(--pann-neutral-tint);     /* หัวตาราง แถบเครื่องมือ แถวที่ชี้ */
  --border: var(--pann-line);                /* ระบบดีไซน์มีเส้นเดียว 1px --pann-line */
  --border-soft: var(--pann-line);

  /* ตัวอักษร */
  --text: var(--pann-fg);
  --text-muted: var(--pann-fg-muted);
  --text-soft: var(--pann-fg-muted);         /* เดิมจางกว่า — ระบบดีไซน์มีสองระดับ ไม่มีระดับที่สาม */
  --font: var(--pann-font);                  /* nav.css และ bell เรียกชื่อนี้ */

  /* สถานะ — ความหมายเดิมตรงกับระบบดีไซน์: เขียว = สำเร็จ · เหลือง = ต้องทำ · แดง = ผิดพลาด */
  --ok: var(--pann-success);
  --ok-bg: var(--pann-success-tint);
  /* ใบ 335: ตัวอักษรสีเตือนใช้ **อำพันเข้ม** ของระบบดีไซน์ (`--pann-accent-ink` = "อำพันแบบอ่านได้บนพื้นขาว")
     เพราะสีเตือนของระบบดีไซน์ได้ความต่างของสีไม่ถึงด่าน 4.5:1 บนพื้นขาวตอนที่ตั้งกฎนี้ (v1.0)
     ใบ 354 (v1.2) เปลี่ยนค่าให้เข้มขึ้นแล้ว แต่ยังใช้ทางเดิมไว้ก่อน — เปลี่ยนการแมปเป็นงานของใบที่สั่งเรื่องนั้น
     สีเตือนแบบเข้ม (ขอบ · จุด · เส้น) ยังใช้ `--pann-attention` ตรง ๆ ได้ (ดู --honey · --warn-line) */
  --warn: var(--pann-accent-ink);
  --warn-bg: var(--pann-attention-tint);
  --danger: var(--pann-danger);
  --danger-bg: var(--pann-danger-tint);
  --honey: var(--pann-attention);            /* ใกล้ครบกำหนด — ใช้กับจุด/แถบเท่านั้น (ตัวอักษรใช้ --warn) */
  --info: var(--pann-fg);                    /* งาน 335: ป้าย "ข้อมูล" ไม่ใช่คำเตือน → เทาอุ่นตามกฎสีข้อ 2 (เลิกใช้น้ำเงิน) */
  --info-bg: var(--pann-neutral-tint);
  --highlight: var(--pann-attention-tint);   /* พื้นไฮไลต์คำที่ค้นเจอ — ระบบดีไซน์ยังไม่มีชิ้นนี้ ใช้พื้น "ต้องทำ" ไปก่อน */

  /* งาน 168 — สีประจำสำนักงาน: สำนักงานที่ยังไม่มีโลโก้ ใช้ป้ายรหัสย่อ (SP · JAY · AUD) บนสีของตัวเอง
     **ระบบดีไซน์ PANN ยังไม่มีชุดนี้** (เป็นชุดสีสำหรับแยกข้อมูล ไม่ใช่สีแบรนด์) — ส่งต่อห้อง Design แล้วในสรุปใบ 335
     เลือกสีจากรหัสสำนักงาน (firm-switch.js: firmColor) — รหัสเดิมได้สีเดิมทุกหน้า ทุกเครื่อง ไม่ผูกกับลำดับในรายการ
     ตัวอักษรบนป้ายเป็น --on-primary (ขาว) ทุกสีจึงต้องต่างจากขาวอย่างน้อย 4.5:1 (tests/test_color_tokens.py ตรวจ)
     MSP ไม่ใช้ชุดนี้ — ใช้โลโก้และสีแบรนด์เดิม (ห้ามเอาโลโก้/ชื่อ MSP ไปใส่สำนักงานอื่น) */
  --firm-1: #1F5C8B;             /* น้ำเงิน */
  --firm-2: #7A3E9D;             /* ม่วง */
  --firm-3: #A03A5E;             /* ชมพูเข้ม */
  --firm-4: #14657A;             /* ฟ้าอมเขียว */
  --firm-5: #8A4B12;             /* น้ำตาลส้ม */
  --firm-6: #3F4E9E;             /* คราม */
  --firm-7: #5F6B18;             /* เขียวมะกอก */
  --firm-8: #9B3226;             /* แดงอิฐ */

  /* ชื่อเดิมที่หน้าเก่าใช้ — ชี้ไปที่ชื่อใหม่ */
  --success: var(--ok);
  --success-bg: var(--ok-bg);
  --warning: var(--warn);
  --warning-bg: var(--warn-bg);

  --radius: var(--pann-r-ctl);

  /* งาน 320 (โจ 3 ต.ค. 2569 ค่ำ: "จอซ้ายขวาเว้นไว้ทำไม") — ความกว้างของเนื้อหามีกติกาเดียวทั้งระบบ
     หน้าเครื่องมือ (ตาราง · กระดานลาก · แผงผู้ดูแลระบบ) กว้างได้เต็มจอ · หน้าอ่านคุมบรรทัดไว้ให้อ่านสบาย
     ใช้ที่ main ของแต่ละหน้า: max-width: var(--page-max-tool) หรือ var(--page-max-read)
     (ระบบดีไซน์มี --pann-maxw 1180px สำหรับหน้าอ่านบนมือถือก่อน · IOC เป็นหน้าเครื่องมือจอใหญ่ จึงมีสองค่าของตัวเอง) */
  --page-max-tool: 1800px;
  --page-max-read: 1100px;
  --page-gutter: 24px;

  /* งาน 222: ส่วนประกอบกลางจาก msp-ledger (ledger/combo.js) เขียน CSS ด้วยสเกลของ ledger
   *   และ **ไม่มีค่าสำรอง** (ต่างจาก datefield.js ที่ใส่ไว้ครบ) — หน้า IOC ไม่เคยมี token ชุดนี้
   *   ช่องเลือกที่ค้นหาได้จึงจะได้ padding/ขนาดตัวอักษรที่ประกาศไม่ผ่านแล้วตกหายทั้งบรรทัด
   *   งาน 335: ชี้มาที่สเกลของระบบดีไซน์ (ระยะ 4/8/12/16 ตรงกันพอดี · ขนาดตัวอักษรขึ้นเป็นอย่างน้อย 14px ตามกฎข้อ 3)
   *   (ห้ามแก้ ledger/design.css ที่นี่ — เป็นของ repo msp-ledger) */
  /* ค่าชุดนี้ต้องตรงกับ ledger/design.css **ตัวอักษรต่อตัวอักษร** (tests/test_shared_pickers.py ตรวจ)
     เพราะ combo.js ของ msp-ledger วาดด้วยสเกลนี้ — ของชิ้นเดียวกันต้องหน้าตาเหมือนกันทั้งสองระบบ
     เป็นระยะ/ขนาด ไม่ใช่สี · เปลี่ยนพร้อมกันทั้งสองฝั่งในใบ Ledger 323 */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
  --fs-xs: 11px; --fs-sm: 13px; --fs-md: 14px; --fs-lg: 18px;
  --fw-medium: 600;
  --radius-sm: 6px;
  --warning-text: var(--warn);
  --shadow: var(--pann-shadow);
  --shadow-lg: var(--pann-shadow-float);

  /* งาน 066: ชุดออกแบบ Claude Design (design_handoff_msp_redesign)
     งาน 335: ชุดนี้ถูกแทนด้วยระบบดีไซน์ PANN ทั้งก้อน — เหลือไว้เป็นชื่อให้ nav.css และหน้าเก่าเรียก
     **แถบซ้ายไม่ใช่เขียวเข้มแล้ว** — ระบบดีไซน์กำหนดว่าแถบซ้ายเป็นพื้น tint อ่อน เมนูที่เลือก = สีแบรนด์ตัวขาว (ข้อ 5) */
  /* งาน 386 (ระบบดีไซน์ v1.3 · โจตัดสิน 13 ต.ค. 2569): **แบบ A (รางซ้ายเขียวทึบ) ถูกแทนด้วยโครงร่วมพื้นขาว**
     รางและแผงเมนูเป็นพื้นขาว เส้นคั่นเทา · เมนูที่เลือก = พื้นเขียวอ่อน (tint) + ตัวหนังสือสีแอป (ink) + ขีดสีแอป
     ห้ามย้อมรางทั้งแผงด้วยสีแอป (README ข้อ 2.1) · ชื่อตัวแปรเดิมของ nav.css คงไว้ — เปลี่ยนเฉพาะค่าที่ชี้ */
  --nav-grad-top: var(--pann-surface);       /* ราง: พื้นขาว */
  --nav-grad-bottom: var(--pann-surface);
  --nav-panel: var(--pann-surface);          /* แผงเมนู: พื้นขาว */
  --nav-text: var(--pann-fg-muted);          /* ป้ายบนราง */
  --nav-item: var(--pann-fg);                /* รายการในแผง */
  --nav-sub: var(--pann-fg-muted);           /* หัวข้อย่อย · บทบาท */
  --nav-fold: var(--pann-fg-muted);          /* หมวดที่พับ */
  --nav-dim: var(--pann-fg-muted);           /* ตัวเลขจำนวนเมนู */
  --nav-field: var(--pann-bg);               /* ช่องค้นหา / ปุ่มปักหมุดบนแผง */
  --nav-logo-bg: var(--pann-surface);        /* พื้นรองโลโก้บนราง */
  --nav-strong: var(--pann-fg);              /* ตัวอักษรเน้นบนราง/แผง */
  --nav-hover: var(--pann-bg);               /* พื้นตอนชี้ */
  --nav-active-bg: var(--pann-brand-tint);   /* เมนูที่เลือกอยู่ = พื้น tint */
  --nav-active-ink: var(--pann-brand-ink);   /*   ตัวหนังสือสีแอป (ink) */
  /* ตัวเลขแจ้งเตือนที่ยังไม่อ่าน = มิ้นต์ (จุดเน้นร่วม) ตัวหนังสือกรมท่า — ห้ามตัวขาวบนมิ้นต์ */
  --nav-count-bg: var(--pann-accent);
  --nav-count-ink: var(--pann-on-accent);
  --mint: var(--pann-accent);
  --mint-soft: var(--pann-brand-tint);       /* พื้นหมวดที่กำลังอยู่ในราง */
  --mint-line: var(--pann-line);             /* เส้นคั่น */
  --mint-text: var(--pann-brand-ink);        /* ตัวที่ "กำลังอยู่" บนราง = สีแอป (ink) */
  --accent-yellow: var(--pann-brand);        /* ขีดบอกตำแหน่งในราง = สีแอป (งาน 386) — เส้นเท่านั้น ไม่ใช่สีตัวอักษร */
  --border-strong: var(--pann-line);
  --table-head: var(--pann-brand-soft);      /* งาน 336: หัวตารางมีน้ำหนักขึ้น (พื้นอ่อนของแบรนด์) */
  --table-head-line: var(--pann-brand-line);
  --table-head-ink: var(--pann-brand-dark);  /* งาน 336: ตัวหนังสือหัวตาราง */
  --row-line: var(--pann-line);
  --tint-ok: var(--pann-success-tint);
  --tint-info: var(--pann-brand-tint);
  --tint-warn: var(--pann-attention-tint);
  --warn-line: var(--pann-attention);
  --text-strong: var(--pann-fg);
  --text-mid: var(--pann-fg);
  --text-dim: var(--pann-fg-muted);
  --radius-card: var(--pann-r-card);
  --radius-shell: var(--pann-r-card);
  --shadow-card: var(--pann-shadow);
  --shadow-panel: var(--pann-shadow-float);
  --ease-nav: cubic-bezier(.22,.61,.36,1);
  /* ฟอนต์ความกว้างคงที่สำหรับรหัส/เลขอ้างอิง — ระบบดีไซน์ยังไม่มีชุดนี้ (ส่งต่อห้อง Design แล้ว) */
  --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
}

/* ฟอนต์ของทั้งระบบมาจากระบบดีไซน์ที่เดียว (IBM Plex Sans Thai) — หน้าไหนเขียนชื่อฟอนต์เองถือว่าผิดกติกาข้อ 7 ของใบ 335 */
html, body { font-family: var(--pann-font); }

/* ตัวเลขในตารางและช่องกรอกตัวเลข กว้างเท่ากันทุกตัว — ยอดเงิน/จำนวนเรียงตรงกันทุกแถว (งาน 004 ข้อ 11) */
table, input[type="number"], .num, .money, .amount { font-variant-numeric: tabular-nums; }

/* จอเล็ก: ปุ่ม/ช่องกรอก/แท็บทุกอันสูงอย่างน้อย 44px ให้นิ้วกดโดน (งาน 027 ข้อ 22) */
@media (max-width: 900px) {
  .btn, button, select, [role="button"], .tab, .chip,
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="hidden"]):not([type="color"]) { min-height: 44px; }
  a.btn { display: inline-flex; align-items: center; justify-content: center; }
}

/* งาน 036: กล่องแจ้งเตือน (toast) ลอยทับกลางล่างของจอ — เดิมรับคลิกแม้ตอนมองไม่เห็น (opacity 0)
   จึงบังปุ่มที่อยู่ข้างใต้ เช่น ปุ่มบันทึกในกล่องสิทธิ์ (กดลองใหม่หลังบันทึกล้มไม่ติด) */
.toast { pointer-events: none; }

/* งาน 037: ทุกคลิกต้องมีเสียงตอบ (คู่กับ /shell.js)
   - มีเซสชันในเครื่อง → ข้ามจอ "กำลังโหลด..." เต็มจอ วาดโครงหน้าทันที (เซสชันใช้ไม่ได้ หน้าเปิดจอเข้าสู่ระบบทับเอง)
   - แถบความคืบหน้าบางบนสุด · skeleton ระหว่างรอข้อมูล */
html.msp-shell .loading { display: none !important; }
/* งาน 145: กดเมนู (เปลี่ยนหน้าในโดเมนเดียวกัน) = ภาพหน้าเดิมค้างไว้จนหน้าใหม่วาดเสร็จ แล้วค่อยสลับ — ไม่มีจอขาวระหว่างหน้า
 *   Chrome/Edge 126+ · เบราว์เซอร์อื่นไม่รู้จักกฎนี้ = เหมือนเดิม · รางเมนูไม่ขยับ (มีชื่อของตัวเอง) · คนตั้งลดการเคลื่อนไหว = สลับทันที */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 120ms; }
.msp-sidebar { view-transition-name: msp-nav; }
::view-transition-group(msp-nav), ::view-transition-old(msp-nav), ::view-transition-new(msp-nav) { animation: none; }
@media (prefers-reduced-motion: reduce) { ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; } }
html.msp-shell #app { display: block; }
/* งาน 335 ข้อ 5: หลอดความคืบหน้าเป็นจุดที่สีอุ่น (มัสตาร์ด) โผล่ได้ตามกฎสีของระบบดีไซน์ */
html.msp-busy body::before {
  content: ""; position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 10000; pointer-events: none;
  background: linear-gradient(90deg, transparent 0, var(--pann-accent) 35%, var(--pann-accent) 65%, transparent 100%) no-repeat;
  background-size: 40% 100%; animation: msp-progress 1.1s ease-in-out infinite;
}
@keyframes msp-progress { from { background-position: -40% 0; } to { background-position: 140% 0; } }
@media (prefers-reduced-motion: reduce) {
  html.msp-busy body::before { animation: none; background: var(--pann-accent); background-size: 100% 100%; opacity: .5; }
}
.msp-skel { color: transparent !important; position: relative; min-height: 150px; }
.msp-skel::before {
  content: ""; position: absolute; inset: 14px 16px; border-radius: var(--pann-r-ctl); pointer-events: none;
  background: repeating-linear-gradient(to bottom, var(--surface-2) 0 14px, transparent 14px 30px);
  animation: msp-skel 1.4s ease-in-out infinite;
}
@keyframes msp-skel { 50% { opacity: .55; } }
@media (prefers-reduced-motion: reduce) { .msp-skel::before { animation: none; } }

/* งาน 037: ไม่มีข้อมูล ≠ จอเปล่า (emptyHtml / failHtml ใน states.js) */
.msp-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; padding: 24px 16px; color: var(--text-muted); }
.msp-empty-icon { width: 52px; height: 52px; border-radius: 50%; display: grid; place-items: center; font-size: 26px; line-height: 1; background: var(--surface-2); }
.msp-empty-text { font-size: var(--pann-t-small); line-height: 1.6; max-width: 46ch; }
/* งาน 268: บรรทัดอธิบายเหตุใต้สถานะว่าง (เช่น "ว่างเพราะไม่มีสิทธิ์") — งาน 335: ไม่มีตัวหนังสือเล็กกว่า 14px แล้ว (กฎข้อ 3) */
.msp-empty-note { font-size: var(--pann-t-small); line-height: 1.55; max-width: 52ch; color: var(--text-muted); }
.msp-fail .msp-empty-text { color: var(--text); }

/* งาน 221z (ความปลอดภัย + หน้าตา): หน้าเข้าสู่ระบบ .auth-screen ไม่เคยมี z-index เลยสักหน้า
 *   (33 หน้าเขียน position:fixed;inset:0 เหมือนกันหมด แต่ไม่มีใครใส่ลำดับชั้น)
 *   → เมนูซ้าย (nav.css 790–900) · แถบบนของหน้า (10) · หัวตาราง sticky · แถบความคืบหน้า (10000)
 *     ลอยทับกล่องล็อกอินได้ทั้งหมด · ต่ำกว่าด่าน 2FA หนึ่งขั้น เพราะด่านนั้นต้องอยู่เหนือทุกอย่าง (งาน 219b)
 *   html.auth-locked = ยังไม่ล็อกอิน ซ่อนทุกอย่างที่ไม่ใช่กล่องล็อกอิน (auth-guard.js เป็นคนใส่/ถอดให้)
 *   เว้น .loading ไว้ ให้ยังเห็นว่ากำลังโหลด — วงกลมหมุนไม่ใช่ "แอป" และไม่มีข้อมูลอะไรให้เห็น */
.auth-screen { z-index: 2147482000; }
html.auth-locked, html.auth-locked body { overflow: hidden !important; }
html.auth-locked body > *:not(.auth-screen):not(.loading):not(#mfa-gate):not(#pw-gate) { display: none !important; }

/* ================= ปุ่ม · ช่องกรอก · กล่องเข้าสู่ระบบ — ใช้ร่วมทุกหน้า =================
 * ใบ 315z (3 ต.ค. 2569) ย้ายชุดนี้มาไว้ที่นี่ เพราะเดิมถูกก๊อปวางใน <style> ของแต่ละหน้า (~40 หน้า)
 * **งาน 335 (5 ต.ค. 2569): ลบสำเนาในหน้าทั้ง 42 หน้าออกแล้ว** — ของจริงอยู่ที่นี่ที่เดียว
 *   จึงเปลี่ยนหน้าตาปุ่มทั้งระบบได้ที่เดียวตามระบบดีไซน์ PANN (ข้อ 5 "ชิ้นส่วน"):
 *   ปุ่มหลัก = พื้นสีแบรนด์ตัวขาว (1 ปุ่มต่อหน้า) · ปุ่มรอง = ขอบสีแบรนด์ตัวสีแบรนด์ · ปุ่มลบ = พื้นแดง
 *   รัศมีและน้ำหนักตัวอักษรมาจากระบบดีไซน์ · **ขนาด/ระยะคงเดิม** เพราะใบ 335 สั่งว่าทุกอย่างต้องอยู่ที่เดิม
 *   (ความสูง 48/44px ของระบบดีไซน์ = ใบขั้นถัดไป ไม่ใช่ใบนี้)
 * ชื่อคลาสใหม่ `.pann-btn` / `.pann-card` / `.pann-pill` ใช้ได้แล้วจาก /pann-design.css สำหรับของใหม่
 */
  .auth-screen { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, var(--primary-bg) 0%, var(--brand-tint) 100%); padding: 16px; }
  .auth-card { background: var(--surface); border-radius: var(--pann-r-card); padding: 32px 28px; max-width: 400px; width: 100%; box-shadow: var(--shadow-lg); }
  .auth-logo { width: 200px; height: 74px; margin: 0 auto 16px; display: block; background-image: url("/v/0152c06/msp-logo.png"); background-size: contain; background-repeat: no-repeat; background-position: center; }
  .auth-title { text-align: center; font-size: var(--pann-t-h1); font-weight: 700; color: var(--primary); margin-bottom: 4px; }
  .auth-sub { text-align: center; color: var(--text-muted); font-size: var(--pann-t-small); margin-bottom: 24px; }
  .form-row { margin-bottom: 14px; }
  .form-row label { display: block; font-size: var(--pann-t-small); font-weight: 500; color: var(--text); margin-bottom: 6px; }
  input, select, textarea { font-family: inherit; font-size: var(--pann-t-small); width: 100%; padding: 9px 12px; border: 1px solid var(--border); border-radius: var(--pann-r-ctl); background: var(--surface); color: var(--text); }
  input:focus, select:focus, textarea:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--pann-brand-tint); }
  textarea { min-height: 60px; resize: vertical; }
  .btn { background: var(--primary); color: var(--on-primary); border: 1px solid transparent; padding: 10px 18px; border-radius: var(--pann-r-ctl); font-size: var(--pann-t-small); font-weight: 600; cursor: pointer; font-family: inherit; transition: background .15s; }
  .btn:hover { background: var(--primary-dark); }
  .btn:disabled { opacity: .45; cursor: not-allowed; }
  .btn-full { width: 100%; padding: 12px 20px; font-size: var(--pann-t-body); }
  .btn-sm { padding: 6px 12px; font-size: var(--pann-t-small); }
  .btn-secondary { background: var(--surface); color: var(--primary); border: 1px solid var(--primary); }
  .btn-secondary:hover { background: var(--primary-bg); }
  .btn-danger { background: var(--danger); border-color: transparent; color: var(--on-primary); }
  .btn-danger:hover { background: var(--danger); }
  .btn-success { background: var(--success); border-color: transparent; color: var(--on-primary); }
  .error-msg { background: var(--danger-bg); color: var(--danger); padding: 10px 12px; border-radius: var(--pann-r-ctl); font-size: var(--pann-t-small); margin-top: 10px; display: none; }
  .error-msg.show { display: block; }
