/* ⛔ ไฟล์นี้สร้างจาก ดีไซน์รวม/design-system/ + src/ui.css + src/motion.css — ห้ามแก้ที่นี่
   แก้ที่ต้นฉบับแล้วรัน: node build.mjs · ใช้กับหน้า /login/ เท่านั้น */

/* ── tokens.css ── */
/* ต้นฉบับค่าดีไซน์ของทุกเว็บในเวิร์กสเปซนี้ — แก้ที่นี่ที่เดียว
   ชุดนี้ = รายรับรายจ่าย/DESIGN.md ฉบับ 2 "กระจกน้ำแข็ง" (operator อนุมัติ 13 ก.ย. 69)
   ฉบับแรกเก็บไว้ที่ รายรับรายจ่าย/docs/เก่า/DESIGN-v1.md
   โปรเจกต์ได้ไฟล์นี้ผ่าน build.mjs → src/shared.css */

:root {
  color-scheme: light;

  /* ── พื้นและกระจก (DESIGN.md §1.1) ── */
  --bg: #F2F7FD;
  --bg-ice: #D9E5F5;
  --bg-periwinkle: #94AEFB;   /* แสงฟุ้ง ใช้ความโปร่ง 35–45% */
  --bg-sky: #88D2F9;          /* แสงฟุ้ง ใช้ความโปร่ง 30–40% */
  --glass: rgb(255 255 255 / 58%);
  --glass-strong: rgb(255 255 255 / 78%);   /* ตัวหนังสือเยอะ · ช่องพิมพ์ · ตาราง */
  --glass-edge: rgb(255 255 255 / 90%);
  --glass-line: rgb(15 32 57 / 8%);
  --glass-shadow:
    inset 0 1px 0 rgb(255 255 255 / 70%),
    0 18px 40px -22px rgb(26 49 79 / 35%),
    0 2px 6px -2px rgb(26 49 79 / 10%);

  /* ── ตัวอักษร (§1.2) — ดำและเทาเกือบดำ
        ตัวเลขท้ายบรรทัด = คอนทราสต์บนกระจกจุดแย่สุด (กระจก 58% บนแสงฟุ้ง --bg-ice) ── */
  --ink: #000000;          /* 19.00 */
  --ink-2: #111827;        /* 16.05 */
  --ink-3: #1F2937;        /* 13.28 */
  --placeholder: #374151;  /* 9.33 */

  /* ── สีเน้น · แสง · โลหะ (§1.3) ── */
  --accent-from: #94AEFB;  /* พื้นปุ่มหลัก ไล่ 135° */
  --accent-to: #88D2F9;
  --accent-ink: #000000;   /* ป้ายบนปุ่มหลัก 9.71 — ห้ามใช้ขาว ได้แค่ 1.66 */
  --accent-dot: #81DDFF;   /* ตกแต่งเท่านั้น ห้ามส่งความหมาย */
  --glow-blue: #326AB5;    /* เส้นขอบเรือง 5.05 */
  --glow-violet: #6E5AE6;  /* เส้นขอบเรือง + วงโฟกัส 4.57 */
  --glow-cyan: #47B8D5;    /* ไฮไลต์ในแสงเท่านั้น 2.15 — ห้ามเป็นเส้นขอบหลัก */
  --glow-lilac: #CCABE0;   /* ไฮไลต์ในแสงเท่านั้น 1.86 — ห้ามเป็นเส้นขอบหลัก */
  --chrome-1: #394150;     /* ตัวเลขโลหะเงิน ไล่บน → ล่าง · จุดจางสุด 9.29 */
  --chrome-2: #111827;
  --chrome-3: #000000;

  /* ── สถานะ (§1.4) — ใช้คู่ไอคอน + คำเสมอ ── */
  --good: #0B7076;         /* 5.29 */
  --warning: #8F5E10;      /* 5.03 */
  --critical: #B3325C;     /* 5.39 */

  /* ── สีหมวด 8 ช่อง (§1.5) — ลำดับตายตัว ห้ามสลับ ห้ามวนซ้ำ
        หมวดใหม่รับช่องว่างตามลำดับ 1 → 4 → 7 → 8 · หมวดที่ 9 ขึ้นไปพับเข้า "อื่นๆ" ── */
  --series-1: #8C3287;
  --series-2: #C1611B;     /* ค่าอาหาร */
  --series-3: #1E85BF;     /* ค่าเดินทาง */
  --series-4: #8D6300;
  --series-5: #5C44A2;     /* ค่า AI */
  --series-6: #2E7A21;     /* ค่าของใช้จำเป็น */
  --series-7: #5185E9;
  --series-8: #8F3F55;
  --series-other: #6E798C; /* "อื่นๆ" ไม่ใช่ช่องหมวด */

  /* รายรับ/รายจ่ายในกราฟเดียวกัน */
  --flow-income: #0D9299;
  --flow-expense: #970C45;

  /* ไล่ระดับปริมาณ อ่อน → เข้ม · กราฟแบบลำดับขั้นเริ่มที่ 400 */
  --seq-100: #DDE8FD;
  --seq-200: #BCD2F9;
  --seq-300: #98B8F2;
  --seq-400: #729BE6;
  --seq-500: #507ED3;
  --seq-600: #3B63B0;
  --seq-700: #284A8B;

  /* บวก/ลบรอบศูนย์ · แท่งแยกชิ้นใช้ 400–600 · "near" ใช้เฉพาะกราฟไล่สีต่อเนื่อง */
  --div-neg-600: #A22751;
  --div-neg-500: #C04D6D;
  --div-neg-400: #DC728C;
  --div-neg-near: #F7BBC7;
  --div-mid: #E8E8E8;
  --div-pos-near: #9FCED2;
  --div-pos-400: #429CA2;
  --div-pos-500: #0A7E85;
  --div-pos-600: #005E64;

  /* toast (§6) — ขาวบนกรมท่า 88% ≈ 11.6 */
  --toast-bg: rgb(15 32 57 / 88%);
  --toast-ink: #FFFFFF;

  /* ── ฟอนต์ (§2.1) — ห้ามมีตระกูลที่สาม ── */
  --font-ui: "Prompt", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* ยอดเงินที่เรียงเป็นคอลัมน์ · สิ่งที่พิมพ์ในช่อง — Prompt ตัวเลขกว้างไม่เท่ากัน จุดทศนิยมจะเหลื่อม */
  --font-num: "IBM Plex Mono", ui-monospace, "SF Mono", monospace;

  /* ── ขนาดตัวอักษร (§2.2) ── */
  --fs-hero: clamp(40px, 11vw, 52px);
  --fs-h1: 16px;
  --fs-h2: 14px;
  --fs-body: 15px;
  --fs-amount: 15px;
  --fs-small: 13px;
  --fs-meta: 12px;

  /* ── มุม (§3) ── */
  --r-panel: 22px;
  --r-field: 18px;
  --r-pill: 999px;
  --r-dot: 50%;

  /* ── ขนาด (§3) ── */
  --maxw: 520px;
  --tap: 40px;

  /* ── การเคลื่อนไหว (§5.2 · §8) ── */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --glow-lap: 2.4s;        /* แสงวิ่ง 1 รอบ */
  --glow-once: 1.6s;       /* บันทึกสำเร็จ วิ่งรอบเดียว */

  /* ของที่เบราว์เซอร์วาดให้เอง */
  --focus-ring: var(--glow-violet);
}

/* โหมดมืด — ยังคงวัสดุกระจกน้ำแข็งและสีหมวดเดิม แต่เพิ่มความสว่างให้ข้อความ/กราฟบนพื้นกรมท่า */
html[data-theme="dark"] {
  color-scheme: dark;

  --bg: #081321;
  --bg-ice: #17283E;
  --bg-periwinkle: #6174D5;
  --bg-sky: #2B83B1;
  --glass: rgb(13 27 46 / 72%);
  --glass-strong: rgb(16 32 53 / 88%);
  --glass-edge: rgb(185 216 255 / 20%);
  --glass-line: rgb(205 226 252 / 12%);
  --glass-shadow:
    inset 0 1px 0 rgb(255 255 255 / 9%),
    0 20px 46px -24px rgb(0 5 14 / 82%),
    0 2px 8px -2px rgb(0 5 14 / 56%);

  --ink: #FFFFFF;
  --ink-2: #F1F5F9;
  --ink-3: #D5DFEB;
  --placeholder: #C5D1DF;

  --accent-from: #91A9FF;
  --accent-to: #71D2F6;
  --accent-ink: #091525;
  --accent-dot: #73E0FF;
  --glow-blue: #79AEFF;
  --glow-violet: #AA9BFF;
  --glow-cyan: #6DDAF3;
  --glow-lilac: #D1AEF1;
  --chrome-1: #FFFFFF;
  --chrome-2: #E2E8F0;
  --chrome-3: #C7D2E1;

  --good: #71D9D0;
  --warning: #F8C66F;
  --critical: #FF88AA;

  --series-1: #E185DB;
  --series-2: #F09A59;
  --series-3: #6CC8F2;
  --series-4: #E1BD62;
  --series-5: #A994F3;
  --series-6: #7BCB72;
  --series-7: #8AB4FF;
  --series-8: #E28CA4;
  --series-other: #A7B5C8;
  --flow-income: #58D5D5;
  --flow-expense: #FF6F9F;

  --toast-bg: rgb(3 9 18 / 94%);
  --toast-ink: #FFFFFF;
  --focus-ring: var(--glow-cyan);
}

/* ── base.css ── */
/* reset + ฐานตัวอักษร + ของที่เบราว์เซอร์วาดเอง + วัสดุ (กระจก · ขอบเรือง · โลหะเงิน) — ใช้ร่วมทุกเว็บ
   ค่าทุกตัวมาจาก tokens.css · สูตรวัสดุตาม รายรับรายจ่าย/DESIGN.md ฉบับ 2 §4–5 */

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

/* 🔴 ต้องมาก่อนทุกกฎ display — ไม่งั้น .x{display:flex} จะทับ [hidden] ของเบราว์เซอร์
   แล้วกล่องที่สั่งซ่อนไว้จะโผล่ออกมาเปล่าๆ */
[hidden] { display: none !important; }

/* มุมของแสงวิ่ง — ต้องลงทะเบียนชนิดไว้ ไม่งั้นเบราว์เซอร์ไล่ค่าไม่ได้ แสงจะกระโดดแทนที่จะวิ่ง */
@property --glow-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

html {
  -webkit-text-size-adjust: 100%;
  scrollbar-color: color-mix(in srgb, var(--ink-2) 30%, transparent) transparent;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* วงแสงหลังกระจก — กระจกต้องมีอะไรให้เบลอ ไม่งั้นดูเป็นกล่องขาวธรรมดา
   ตรึงอยู่กับที่ ไม่ขยับ (§4 · §8) */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(38rem 30rem at 88% -6%, color-mix(in srgb, var(--bg-periwinkle) 42%, transparent), transparent 70%),
    radial-gradient(32rem 26rem at -8% 34%, color-mix(in srgb, var(--bg-sky) 34%, transparent), transparent 70%),
    radial-gradient(40rem 30rem at 70% 92%, color-mix(in srgb, var(--bg-ice) 95%, transparent), transparent 72%),
    radial-gradient(26rem 22rem at 18% 96%, color-mix(in srgb, var(--glow-lilac) 26%, transparent), transparent 70%);
}

h1, h2, h3 { text-wrap: balance; }

button, input, textarea, select {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

button:disabled { cursor: not-allowed; }

/* 🔴 ยอดเงินที่เรียงเป็นคอลัมน์ต้องใช้ mono และหลักต้องตรงกัน
   Prompt ตัวเลขกว้างไม่เท่ากัน (วัดที่ 40px: 1111 = 59.8px · 0000 = 109.1px) tabular-nums ช่วยไม่ได้ */
.num {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

table { border-collapse: collapse; width: 100%; }

/* ── ของที่เบราว์เซอร์วาดให้เอง ถ้าไม่สั่งก็หลุดจากระบบสี ── */

::selection {
  background: color-mix(in srgb, var(--bg-periwinkle) 38%, transparent);
  color: var(--ink);
}

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 3px;
}

a {
  color: var(--ink);
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink-2) 30%, transparent);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: var(--ink-3); background-clip: content-box; }

textarea, input { caret-color: var(--glow-violet); }

::placeholder {
  color: var(--placeholder);
  opacity: 1; /* Firefox หรี่ placeholder ให้เอง */
}

/* ── วัสดุ: กระจก (§4) ── */

.glass {
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-panel);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  box-shadow: var(--glass-shadow);
}

/* แผงที่มีตัวหนังสือเยอะ · ช่องพิมพ์ · ตาราง */
.glass-strong { background: var(--glass-strong); }

/* จอเล็กเบลอน้อยลง มือถือรุ่นเก่าจะได้ไม่กระตุก */
@media (max-width: 520px) {
  .glass {
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    backdrop-filter: blur(14px) saturate(140%);
  }
}

/* เครื่องที่เบลอไม่ได้ ใช้กระจกทึบขึ้นแทน ตัวหนังสือจะยังอ่านออก */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: var(--glass-strong); }
}

/* ── วัสดุ: ขอบเรืองนิ่ง + แสงวิ่ง (§5) ──
   .glow                     เรืองนิ่งตลอด + เส้นแสงใต้ขอบล่าง
   แสงวิ่งเมื่อ               มีโฟกัสข้างใน · .is-live (กำลังบันทึก) · .run-on-press ตอนกดค้าง
   บันทึกสำเร็จ               ใส่ .is-live.is-live-once → วิ่ง 1 รอบแล้วหยุด
   🔴 ห้ามวิ่งตอนเฉยๆ ตอนเอาเมาส์ชี้ หรือหลายจุดพร้อมกัน */

.glow {
  position: relative;
  isolation: isolate;
  --glow-static: linear-gradient(135deg, var(--glass-edge) 0%, var(--glow-blue) 55%, var(--glow-violet) 100%);
}

/* เส้นขอบ 1.5px วาดด้วยมาสก์ (มาสก์ใช้แค่ความทึบ ไม่ได้ใช้สี) */
.glow::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1.5px;
  background: var(--glow-static);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  pointer-events: none;
  z-index: 2;
}

/* เส้นแสงใต้ขอบล่าง แบบเรฟ 2 */
.glow::after {
  content: "";
  position: absolute;
  left: 14%;
  right: 14%;
  bottom: -2px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--glow-cyan) 30%, var(--glow-violet) 70%, transparent);
  box-shadow: 0 2px 14px 1px color-mix(in srgb, var(--glow-violet) 40%, transparent);
  pointer-events: none;
  z-index: 2;
}

/* ปิดใช้งาน = ไม่เรือง */
.glow:disabled::before,
.glow:disabled::after { display: none; }

/* แสงวิ่ง — มีเฉพาะเครื่องที่ไม่ได้เปิด "ลดการเคลื่อนไหว" · เปิดไว้ = เหลือเรืองนิ่ง */
@media (prefers-reduced-motion: no-preference) {
  .glow:is(:focus-within, .is-live, .run-on-press:active)::before {
    padding: 2px;
    background:
      conic-gradient(from var(--glow-angle), transparent 0 58%, var(--glow-lilac) 66%, var(--glow-cyan) 74%, var(--glass-edge) 78%, var(--glow-violet) 84%, transparent 94%),
      var(--glow-static);
    animation: glow-run var(--glow-lap) linear infinite;
  }
  /* ต้องเจาะจงกว่ากฎบน ไม่งั้นรอบเดียวไม่ชนะ */
  .glow.is-live.is-live-once::before {
    animation-duration: var(--glow-once);
    animation-iteration-count: 1;
  }
}

@keyframes glow-run { to { --glow-angle: 360deg; } }

/* ── วัสดุ: ตัวเลขโลหะเงิน (§1.3 · §6) — ตัวเลขที่ใหญ่ที่สุดของหน้าจุดเดียวเท่านั้น ── */

.chrome { color: var(--ink); }

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .chrome {
    background: linear-gradient(180deg, var(--chrome-1) 8%, var(--chrome-2) 52%, var(--chrome-3) 92%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}

/* ── ตัวช่วย ── */

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition: none !important;
  }
}

/* ── src/ui.css ── */
/* ชิ้นส่วนหน้าจอที่ใช้ร่วมทุกหน้า — ปุ่ม แท็บ ชิป ช่องตั้งชื่อ ป้าย สถานะ toast (DESIGN.md ฉบับ 2 ข้อ 6)
   🔴 ห้ามเขียนเลข hex หรือ rgb() ที่นี่ — ใช้โทเคนจาก src/shared.css เท่านั้น
   🔴 หน้า /login/ ได้ไฟล์นี้ผ่าน login/bundle.css ที่ build.mjs สร้าง — แก้ไฟล์นี้แล้วต้องรัน node build.mjs */

.status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 6px 8px;
  font-size: var(--fs-small);
  color: var(--critical);
  text-align: right;
}
.status:empty { display: none; }
.status svg { width: 15px; height: 15px; flex: none; }
.status .btn { min-height: 34px; padding: 0 12px; font-size: var(--fs-small); }

/* ── ปุ่ม ───────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 42px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--r-pill);
  font-size: 14.5px;
  font-weight: 600;
  white-space: nowrap;
  letter-spacing: -0.01em;
}
.btn svg { width: 16px; height: 16px; flex: none; }

.btn-primary {
  color: var(--accent-ink);
  border: 1px solid color-mix(in srgb, var(--glow-blue) 22%, var(--glass-edge));
  background:
    linear-gradient(165deg, color-mix(in srgb, var(--glass-edge) 48%, transparent), transparent 42%),
    linear-gradient(135deg, var(--accent-from), var(--accent-to));
  box-shadow: 0 14px 28px -15px color-mix(in srgb, var(--glow-blue) 66%, transparent), inset 0 1px 0 var(--glass-edge), inset 0 -1px 0 color-mix(in srgb, var(--glow-violet) 28%, transparent);
  transition: transform 120ms var(--ease-out), box-shadow 120ms var(--ease-out);
}
.btn-primary:hover { box-shadow: 0 18px 32px -15px color-mix(in srgb, var(--glow-blue) 75%, transparent), inset 0 1px 0 var(--glass-edge), inset 0 -1px 0 color-mix(in srgb, var(--glow-violet) 34%, transparent); }
.btn-primary:active { transform: translateY(1px); }
.btn-primary:disabled { opacity: 0.45; box-shadow: none; }

.btn-ghost {
  color: var(--ink-2);
  background: linear-gradient(145deg, color-mix(in srgb, var(--glass-edge) 22%, transparent), transparent), var(--glass);
  border: 1px solid var(--glass-edge);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 9px 20px -16px color-mix(in srgb, var(--ink) 46%, transparent), inset 0 1px 0 color-mix(in srgb, var(--glass-edge) 78%, transparent);
}
.btn-ghost:hover { color: var(--ink); background: var(--glass-strong); }
.btn-ghost:disabled { color: var(--ink-3); background: var(--glass); }
.btn-danger:hover:not(:disabled) { color: var(--critical); }

.btn-icon {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: var(--tap);
  height: var(--tap);
  padding: 0;
  border: 1px solid var(--glass-edge);
  border-radius: 50%;
  color: var(--ink);
  background: linear-gradient(145deg, var(--glass-edge), var(--glass-strong));
  box-shadow: 0 10px 22px -15px color-mix(in srgb, var(--ink) 52%, transparent), inset 0 1px 0 color-mix(in srgb, var(--glass-edge) 76%, transparent);
}
.btn-icon svg { width: 16px; height: 16px; }
.btn-icon:disabled { color: var(--ink-3); }

/* ── แท็บเดือน ─────────────────────────────────────────── */

.month-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 22px;
}

.tabs {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  gap: 2px;
  padding: 4px;
  border-radius: var(--r-pill);
  overflow-x: auto;
  scrollbar-width: none;
  border: 1px solid color-mix(in srgb, var(--glass-edge) 78%, transparent);
  background-image: linear-gradient(145deg, color-mix(in srgb, var(--glass-edge) 30%, transparent), transparent 54%);
  box-shadow: 0 12px 24px -20px color-mix(in srgb, var(--ink) 55%, transparent), inset 0 1px 0 var(--glass-edge);
}
.tabs::-webkit-scrollbar { display: none; }

.tab {
  position: relative;
  flex: none;
  min-height: 36px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--ink-2);
  font-size: 14px;
  font-weight: 500;
}
.tab:hover { color: var(--ink); }
.tab[aria-pressed="true"] {
  background: var(--glass-strong);
  color: var(--ink);
  font-weight: 600;
  box-shadow: 0 9px 18px -13px color-mix(in srgb, var(--glow-blue) 68%, transparent), inset 0 1px 0 var(--glass-edge);
}
.tab[aria-pressed="true"]::after {
  content: "";
  position: absolute;
  left: 22%;
  right: 22%;
  bottom: 3px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--glow-cyan), var(--glow-violet));
}

/* จุดสีหมวด 10px — จุดสีไฮไลต์แบบ ข ที่ operator เลือกในด่าน A (DESIGN.md ข้อ 6 ยังเขียน 8px · รออนุมัติแก้) */
.dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: var(--r-dot);
  flex: none;
}

.chips { display: flex; flex-wrap: wrap; gap: 8px; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: var(--tap);
  padding: 0 14px;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: linear-gradient(145deg, color-mix(in srgb, var(--glass-edge) 24%, transparent), transparent), var(--glass);
  color: var(--ink-2);
  font-size: 14px;
  font-weight: 500;
  box-shadow: 0 8px 18px -16px color-mix(in srgb, var(--ink) 45%, transparent), inset 0 1px 0 color-mix(in srgb, var(--glass-edge) 70%, transparent);
}
.chip:hover { color: var(--ink); }
.chip[aria-pressed="true"] { background: var(--glass-strong); color: var(--ink); font-weight: 600; }
.chip svg { width: 14px; height: 14px; flex: none; }
.chip-add {
  background: transparent;
  border: 1px dashed color-mix(in srgb, var(--ink-2) 45%, transparent);
  color: var(--ink-2);
}
.chip:disabled { color: var(--ink-3); cursor: not-allowed; }

.name-form { display: flex; align-items: center; gap: 6px; flex: 1 1 100%; min-width: 0; }
/* width: 0 — ช่อง input มีความกว้างตั้งต้นของมันเอง ถ้าไม่ศูนย์ ปุ่มยืนยันจะถูกดันหลุดขอบ */
.name-input {
  flex: 1;
  width: 0;
  min-width: 0;
  min-height: var(--tap);
  padding: 0 14px;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: var(--glass-strong);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 16px;
}
.name-input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }

.form-err {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: var(--fs-small);
  color: var(--critical);
}
.form-err svg { width: 15px; height: 15px; flex: none; }

/* ── กล่องยืนยันของเว็บ ─────────────────────────────────── */

.confirm-dialog {
  width: min(430px, calc(100vw - 32px));
  max-width: none;
  padding: 0;
  border: 1px solid var(--glass-edge);
  color: var(--ink);
  overflow: hidden;
}
.confirm-dialog::backdrop {
  background: color-mix(in srgb, var(--ink) 38%, transparent);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.confirm-shell { display: grid; gap: 18px; padding: 24px; }
.confirm-head { display: flex; align-items: center; gap: 12px; }
.confirm-head h2 { margin: 0; font-size: 18px; font-weight: 600; line-height: 1.35; }
.confirm-mark {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  border: 1px solid var(--glass-edge);
  border-radius: 50%;
  color: var(--glow-blue);
  background: var(--glass-strong);
}
.confirm-dialog[data-tone="danger"] .confirm-mark { color: var(--critical); }
.confirm-mark svg { width: 19px; height: 19px; }
.confirm-message {
  margin: 0;
  color: var(--ink-2);
  line-height: 1.7;
  white-space: pre-line;
}
.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding-top: 2px;
}
.confirm-danger {
  color: var(--critical);
  background: color-mix(in srgb, var(--critical) 10%, var(--glass-strong));
  border: 1px solid color-mix(in srgb, var(--critical) 55%, transparent);
  box-shadow: 0 10px 22px -16px color-mix(in srgb, var(--critical) 65%, transparent);
}
.confirm-danger:hover { background: color-mix(in srgb, var(--critical) 16%, var(--glass-strong)); }

@media (max-width: 420px) {
  .confirm-shell { padding: 22px 18px 18px; }
  .confirm-actions { display: grid; grid-template-columns: 1fr 1fr; }
  .confirm-actions .btn { width: 100%; padding-inline: 12px; }
}

.tool-hint { font-size: var(--fs-meta); color: var(--ink-3); }

.cat-tag {
  flex: none;
  padding: 0 8px;
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: var(--glass-strong);
  color: var(--ink-3);
  font-size: 11.5px;
  white-space: nowrap;
}
.cat-tag.is-extra { border-style: dashed; }

.btn-ghost.is-accent { color: var(--ink); background: var(--glass-strong); outline: 1.5px solid var(--glow-violet); outline-offset: -1.5px; }

/* ── toast ──────────────────────────────────────────────── */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(22px + env(safe-area-inset-bottom));
  translate: -50% 0;
  z-index: 20;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: calc(100vw - 32px);
  padding: 11px 18px;
  border-radius: var(--r-pill);
  color: var(--toast-ink);
  background: var(--toast-bg);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  box-shadow: 0 16px 34px -18px color-mix(in srgb, var(--ink) 70%, transparent);
  font-size: 14px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms;
}
.toast svg { width: 16px; height: 16px; flex: none; color: var(--accent-dot); }
.toast.show { opacity: 1; }

/* ── เพิ่มในขั้น C (โครงเว็บ) ─────────────────────────────── */

a.btn { text-decoration: none; }
.btn.is-wide { width: 100%; }
.tool-hint a { color: var(--ink-2); }

/* โลโก้เว็บ — สี่เหลี่ยมมนสีเดียวกับปุ่มหลัก ข้างในเป็นแท่งกราฟ */
.brand-mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 11px;
  color: var(--accent-ink);
  background: linear-gradient(135deg, var(--accent-from), var(--accent-to));
  box-shadow: inset 0 1px 0 var(--glass-edge);
}
.brand-mark svg { width: 20px; height: 20px; }
.brand-mark.is-big { width: 58px; height: 58px; border-radius: 18px; }
.brand-mark.is-big svg { width: 30px; height: 30px; }

/* ปุ่ม "เลิกทำ" ใน toast — toast ปกติกดไม่ได้ (pointer-events: none) มีปุ่มเมื่อไหร่ถึงเปิดให้กด */
.toast.show.has-action { pointer-events: auto; }
.toast-action {
  margin-left: 4px;
  min-height: 32px;
  padding: 0 12px;
  border: 1px solid color-mix(in srgb, var(--toast-ink) 40%, transparent);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--toast-ink);
  font-size: 13.5px;
  font-weight: 600;
}
.toast-action:hover { background: color-mix(in srgb, var(--toast-ink) 14%, transparent); }
.toast-action:focus-visible { outline-color: var(--accent-dot); }

/* ── src/motion.css ── */
/* การเคลื่อนไหวทั้งเว็บ — เปิดตลอด มีแบบเดียว
   operator 13 ก.ย. 69: "อย่าลืมการใส่อนิเมชั่นเข้าไปในการทำเว็บ อันนี้มันดูแข็งไปมากๆ"
                        "ให้ทำเว็บแบบมีโมชั่น ไม่เอาแบบแข็งทื่อ"
   🔴 ห้ามทำปุ่มเลือกระดับ หรือตัวเลือก "นิ่ง" ในเว็บ — เคยใส่ไว้หน้าพรีวิว operator: "อะไรเนี่ย ใส่มาทำไมก่อน"
   🔴 ขยับแค่ transform กับ opacity (ยกเว้นสีกะพริบของแถว) · เครื่องที่เปิด "ลดการเคลื่อนไหว" = นิ่งหมด (base.css ตัดทุกอนิเมชัน)
   🔴 ห้ามขยับ .side .top .toast ทั้งกล่องด้วย transform ค้าง — เป็นกล่อง sticky/fixed
   🔴 ใช้ fill-mode backwards ไม่ใช่ both — both ค้าง transform หลังจบแล้วทับ :hover / :active
   ยอดเงินวิ่งนับอยู่ใน dom.js countUp · แถวกะพริบอยู่ใน dom.js flash
   🔴 ห้ามเขียนเลข hex หรือ rgb() */

:root { --m-rise: 16px; --m-dur: 520ms; --m-step: 65ms; }

@keyframes m-rise { from { opacity: 0; transform: translateY(var(--m-rise)); } to { opacity: 1; transform: none; } }
@keyframes m-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes m-slide { from { opacity: 0; transform: translateX(-12px); } to { opacity: 1; transform: none; } }
@keyframes m-drop { from { opacity: 0; transform: translateY(-6px) scale(0.97); } to { opacity: 1; transform: none; } }
@keyframes m-pop { 0% { transform: scale(0.94); } 60% { transform: scale(1.04); } 100% { transform: none; } }
@keyframes m-grow { from { transform: scaleX(0); } to { transform: none; } }
@keyframes m-chart-bar { from { opacity: .28; transform: scaleY(0); } to { opacity: 1; transform: none; } }
@keyframes m-flash {
  from { background-color: color-mix(in srgb, var(--c, var(--accent-from)) 24%, transparent); }
  to { background-color: transparent; }
}
@keyframes m-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(-3%, 2%, 0) scale(1.08); }
}
@keyframes m-glow-breathe {
  from { opacity: .58; }
  to { opacity: 1; }
}
@keyframes login-sphere-drift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  38% { transform: translate3d(-13px, -9px, 0) scale(1.04); }
  72% { transform: translate3d(7px, -17px, 0) scale(.98); }
}
@keyframes login-orbit { to { transform: rotate(360deg); } }
@keyframes login-ripple {
  0% { opacity: .2; transform: scale(.82); }
  48% { opacity: .68; }
  100% { opacity: 0; transform: scale(1.16); }
}
@keyframes login-mark-breathe {
  0%, 100% { transform: translateY(2px) scale(.97); }
  50% { transform: translateY(-3px) scale(1.03); }
}
@keyframes login-chip-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

/* ลำดับของชิ้นในกลุ่ม ใช้หน่วงเวลาให้ขึ้นทีละชิ้น */
:is(.nb-panels, .set-col, .pv-grid, .panel, .set-list, .nav) > :nth-child(2) { --m-i: 1; }
:is(.nb-panels, .set-col, .pv-grid, .panel, .set-list, .nav) > :nth-child(3) { --m-i: 2; }
:is(.nb-panels, .set-col, .pv-grid, .panel, .set-list, .nav) > :nth-child(4) { --m-i: 3; }
:is(.nb-panels, .set-col, .pv-grid, .panel, .set-list, .nav) > :nth-child(5) { --m-i: 4; }
:is(.nb-panels, .set-col, .pv-grid, .panel, .set-list, .nav) > :nth-child(6) { --m-i: 5; }
:is(.nb-panels, .set-col, .pv-grid, .panel, .set-list, .nav) > :nth-child(n + 7) { --m-i: 6; }
:is(.nb-panels, .set-col + .set-col) > * { --m-base: 90ms; }
:is(.dash-stats, .dash, .minis) > :nth-child(2) { --m-i: 1; }
:is(.dash-stats, .dash, .minis) > :nth-child(3) { --m-i: 2; }
:is(.dash-stats, .dash, .minis) > :nth-child(4) { --m-i: 3; }
:is(.dash-stats, .dash, .minis) > :nth-child(5) { --m-i: 4; }
:is(.dash-stats, .dash, .minis) > :nth-child(n + 6) { --m-i: 5; }
.account-cards > :nth-child(2) { --m-i: 1; }
.account-cards > :nth-child(3) { --m-i: 2; }
.account-cards > :nth-child(4) { --m-i: 3; }
.account-cards > :nth-child(5) { --m-i: 4; }

@media (prefers-reduced-motion: no-preference) {

  /* กรอบหลักของแต่ละหน้า: จุดแสงเดินรอบขอบช้าๆ แบบเรฟ
     ใช้ .glow-flow แยกจาก .glow เพื่อไม่ให้ทุกปุ่มบนหน้าวิ่งพร้อมกัน */
  .glow.glow-flow::before {
    padding: 2px;
    background:
      conic-gradient(from var(--glow-angle), transparent 0 50%, var(--glow-lilac) 60%, var(--glow-cyan) 69%, var(--glass-edge) 74%, var(--glow-violet) 82%, transparent 94%),
      var(--glow-static);
    filter: drop-shadow(0 0 8px color-mix(in srgb, var(--glow-violet) 44%, transparent));
    animation: glow-run 5.4s linear infinite;
    animation-delay: var(--glow-delay, 0s);
  }
  .glow.glow-flow::after {
    animation: m-glow-breathe 2.8s ease-in-out infinite alternate;
    animation-delay: var(--glow-delay, 0s);
  }

  /* หน้าเข้า: ของในหน้าลอยขึ้นทีละชิ้น */
  :is(.crumb, .pv-lead, .nb-write, .nb-panels > *, .set-col > *, .soon-card, .pv-group-head, .pv-grid > *, .login-hero, .login-card, .account-map, .importer, .import-history) {
    animation: m-rise var(--m-dur) var(--ease-out) backwards;
    animation-delay: calc(var(--m-base, 0ms) + var(--m-i, 0) * var(--m-step));
  }
  .login-card { --m-i: 1; }
  .account-map { --m-i: 1; }
  .importer { --m-i: 2; }
  .import-history { --m-i: 3; }
  .account-cards > * {
    animation: m-rise 420ms var(--ease-out) backwards;
    animation-delay: calc(120ms + var(--m-i, 0) * 55ms);
  }
  :is(.file-zone, .scan-panel, .review-stage) { animation: m-drop 260ms var(--ease-out) backwards; }

  /* หน้าล็อกอินต้องมีชีวิตแม้ยืนดูเฉยๆ: ขยับเฉพาะของตกแต่ง ไม่โยกข้อความหรือปุ่ม */
  .login-sphere { animation: login-sphere-drift 11s ease-in-out infinite; }
  .login-sphere::before { animation: login-orbit 13s linear infinite; }
  .login-sphere::after {
    transform-origin: 0 130px;
    animation: login-orbit 8s linear infinite reverse;
  }
  .login-emblem::before { animation: login-ripple 3.8s ease-out infinite; }
  .login-emblem::after { animation: login-ripple 3.8s 1.9s ease-out infinite; }
  .login-orbit-dot { animation: login-orbit 7s linear infinite; }
  .login-emblem .brand-mark { animation: login-mark-breathe 3.2s ease-in-out infinite; }
  .login-chip { animation: login-chip-float 4.6s ease-in-out infinite; }
  .login-chip:nth-child(2) { animation-delay: -1.55s; animation-duration: 5.2s; }
  .login-chip:nth-child(3) { animation-delay: -3.1s; animation-duration: 5.8s; }
  :is(.dash-stats > *, .dash > :not(.dash-stats)) {
    animation: m-rise var(--m-dur) var(--ease-out) backwards;
    animation-delay: calc(var(--m-i, 0) * var(--m-step));
  }

  /* เส้นแสงใต้แท็บ/เมนูที่เลือก ค่อยๆ ยืดออก */
  :is(.tab[aria-pressed="true"], .nav-item[aria-current="page"])::after {
    animation: m-grow 380ms var(--ease-out) backwards;
  }

  /* ชี้แล้วยก — การ์ดลอยขึ้น ปุ่มขยับขึ้นนิดหน่อย (เฉพาะเครื่องที่มีเมาส์) */
  :is(.btn, .chip, .btn-icon, .tab, .profile-btn, .toast-action) {
    transition: transform 160ms var(--ease-out), background-color 160ms, color 160ms, box-shadow 160ms;
  }
  :is(.card, .pv-card, .soon-card) {
    transition: transform 280ms var(--ease-out), box-shadow 280ms var(--ease-out);
  }
  @media (hover: hover) {
    :is(.card, .pv-card, .soon-card):hover {
      transform: translateY(-3px);
      box-shadow: var(--glass-shadow), 0 22px 40px -26px color-mix(in srgb, var(--glow-blue) 45%, transparent);
    }
    :is(.btn-ghost, .chip, .btn-icon):hover:not(:disabled) { transform: translateY(-1px); }
  }

  /* กด = ยุบ (อยู่หลังกฎชี้ ตอนกดจะได้ชนะ) */
  :is(.btn, .chip, .btn-icon, .tab, .profile-btn, .toast-action):active:not(:disabled) {
    transform: scale(0.95);
  }
  :is(.nav-item, .pm-item, .cat-row, .sub-del) {
    transition: background-color 180ms, color 180ms;
  }

  /* ชิปที่เพิ่งเลือกเด้ง */
  .chip[aria-pressed="true"] { animation: m-pop 300ms var(--ease-out); }

  /* กางแผงหมวด · เมนูบัญชี · ข้อความผิดพลาด */
  .sub { animation: m-drop 240ms var(--ease-out) backwards; }
  .profile-menu:not([hidden]) { transform-origin: top right; animation: m-drop 220ms var(--ease-out) backwards; }
  .confirm-dialog[open] .confirm-shell { animation: m-drop 240ms var(--ease-out) backwards; }
  .confirm-dialog[open]::backdrop { animation: m-fade 180ms var(--ease-out) backwards; }
  .form-err { animation: m-drop 220ms var(--ease-out) backwards; }

  /* เปลี่ยนเดือน (notebook.js ใส่ .is-switching ชั่วคราว): แถวในแผงไล่ขึ้นใหม่ */
  .nb.is-switching .panel > * {
    animation: m-rise 360ms var(--ease-out) backwards;
    animation-delay: calc(var(--m-i, 0) * 40ms);
  }

  /* แถวที่เพิ่งบันทึก / เพิ่งเพิ่ม / เพิ่งกู้คืน กะพริบสีหมวดแล้วจางหาย */
  .is-flash { animation: m-flash 1300ms var(--ease-out) backwards; }

  /* กราฟและแท่งสัดส่วนโตจากฐานเมื่อโหลดหรือเปลี่ยนเดือน */
  .chart-bar {
    animation: m-chart-bar 620ms var(--ease-out) backwards;
    animation-delay: calc(180ms + var(--bar-i, 0) * 65ms);
  }
  .share-track i {
    transform-origin: left center;
    animation: m-grow 560ms var(--ease-out) backwards;
  }

  /* toast ลอยขึ้นจากล่าง */
  .toast { translate: -50% 14px; transition: opacity 200ms, translate 380ms var(--ease-out); }
  .toast.show { translate: -50% 0; }

  /* เมนูมือถือ: พื้นหลังจาง + รายการเมนูไล่เข้ามา */
  .app.is-open .scrim { animation: m-fade 220ms var(--ease-out) backwards; }
  .app.is-open .nav-item {
    animation: m-slide 380ms var(--ease-out) backwards;
    animation-delay: calc(80ms + var(--m-i, 0) * 50ms);
  }

  /* จอคอม: แสงหลังกระจกลอยช้าๆ · มือถือไม่ทำ กระจกต้องเบลอใหม่ตลอดจะกินแรงเครื่อง */
  @media (min-width: 1025px) and (hover: hover) {
    body::before { animation: m-drift 24s ease-in-out infinite alternate; }
  }
}

