/* Budget Book — self-hosted. No external fonts or CDNs. */
:root{
  /* Colour themes: "blue" (navy blue, default) and "sky" (light blue) - the super admin picks one under
     Admin > Home and settings. Change the palettes here; everything else uses these variables. */
  /* palette aligned to the SFT Hospitality logo: navy ink, teal brand accent, warm cream surface, gold hero highlight */
  --bg:#f5f2ea; --surface:#ffffff; --surface-2:#ece5d5; --ink:#1f3b47; --ink-2:#3c6473; --ink-3:#6f7f89;
  --line:#ddd4bd; --brand:#1f6b78; --brand-ink:#ffffff; --on-capex:#ffffff;
  --capex:#1d5fc0; --capex-soft:#dbe7fa; --opex:#c98a12; --opex-soft:#f6ead0;
  --good:#2b7a4b; --good-soft:#dbeee2; --warn:#9a5a08; --warn-soft:#f8e8cf;
  --bad:#b3372f; --bad-soft:#f6dcd9; --info:#2a5fa8; --info-soft:#dde7f8;
  --mute:#556584; --mute-soft:#e4e9f3; --focus:#2b8a97; --overlay:rgba(23,50,62,.55);
  /* per-hotel colours for the timeline (Gantt) chart — a fixed cycling palette so each hotel keeps the same colour
     everywhere, chosen to stay clear of the semantic colours above (capex/opex/good/warn/bad/mute) */
  --h1:#0f7a72; --h2:#4338ca; --h3:#7c3aed; --h4:#a3298f; --h5:#b3316f; --h6:#6b7a12;
  --shadow:0 1px 2px rgba(13,26,51,.06),0 4px 14px rgba(13,26,51,.06);
  --hero:linear-gradient(120deg,#1f3b47 0%,#1f6b78 60%,#e5b578 100%);
  --tile-a:linear-gradient(135deg,#1f3b47,#2f8a92); --tile-b:linear-gradient(135deg,#1650a8,#2f8fd8);
  --tile-c:linear-gradient(135deg,#0f766e,#14b8a6); --tile-d:linear-gradient(135deg,#3a4d70,#64748b);
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --sans:'Sarabun','Noto Sans Thai','Leelawadee UI',Tahoma,system-ui,-apple-system,'Segoe UI',sans-serif;
  color-scheme:light;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
  --bg:#0e1c22; --surface:#15282f; --surface-2:#1c343d; --ink:#eef2ee; --ink-2:#b7c8c8; --ink-3:#8aa0a0;
  --line:#2b4650; --brand:#5fb8c4; --brand-ink:#062024; --on-capex:#06132a;
  --capex:#6da6f0; --capex-soft:#142b52; --opex:#e3ac3b; --opex-soft:#3b3015;
  --good:#6fcf97; --good-soft:#153224; --warn:#e6a655; --warn-soft:#3a2b14;
  --bad:#f0837a; --bad-soft:#3e1f1d; --info:#8ab4f2; --info-soft:#172d54;
  --mute:#9fb0cf; --mute-soft:#1f3050; --focus:#5fb8c4; --overlay:rgba(4,10,12,.65);
  --h1:#4fd6c7; --h2:#93a6f5; --h3:#b79cf7; --h4:#e28bd4; --h5:#f090b6; --h6:#c3d66a;
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#123039 0%,#1f6b78 55%,#e0a95c 100%);
  --tile-a:linear-gradient(135deg,#123039,#2a7078); --tile-b:linear-gradient(135deg,#1a4a9a,#2b88d0);
  --tile-c:linear-gradient(135deg,#0d5c54,#1aa393); --tile-d:linear-gradient(135deg,#334562,#7c8bab);
  color-scheme:dark;
  }
}
:root[data-theme="dark"]{
  --bg:#0e1c22; --surface:#15282f; --surface-2:#1c343d; --ink:#eef2ee; --ink-2:#b7c8c8; --ink-3:#8aa0a0;
  --line:#2b4650; --brand:#5fb8c4; --brand-ink:#062024; --on-capex:#06132a;
  --capex:#6da6f0; --capex-soft:#142b52; --opex:#e3ac3b; --opex-soft:#3b3015;
  --good:#6fcf97; --good-soft:#153224; --warn:#e6a655; --warn-soft:#3a2b14;
  --bad:#f0837a; --bad-soft:#3e1f1d; --info:#8ab4f2; --info-soft:#172d54;
  --mute:#9fb0cf; --mute-soft:#1f3050; --focus:#5fb8c4; --overlay:rgba(4,10,12,.65);
  --h1:#4fd6c7; --h2:#93a6f5; --h3:#b79cf7; --h4:#e28bd4; --h5:#f090b6; --h6:#c3d66a;
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#123039 0%,#1f6b78 55%,#e0a95c 100%);
  --tile-a:linear-gradient(135deg,#123039,#2a7078); --tile-b:linear-gradient(135deg,#1a4a9a,#2b88d0);
  --tile-c:linear-gradient(135deg,#0d5c54,#1aa393); --tile-d:linear-gradient(135deg,#334562,#7c8bab);
  color-scheme:dark;
}
:root[data-palette="sky"]{
  --bg:#e8f5fd; --surface:#ffffff; --surface-2:#d9edf9; --ink:#0c2537; --ink-2:#385a73; --ink-3:#4a6a82;
  --line:#bfdcee; --brand:#0a6cae; --brand-ink:#ffffff; --on-capex:#ffffff;
  --capex:#0872b0; --capex-soft:#d3ebf8; --info:#0a6aa8; --info-soft:#d6ecf9;
  --mute:#4c6a7f; --mute-soft:#dfeaf2; --focus:#1596e6; --overlay:rgba(6,28,44,.55);
  --shadow:0 1px 2px rgba(12,37,55,.06),0 4px 14px rgba(12,37,55,.06);
  --hero:linear-gradient(120deg,#08639f 0%,#0b7cc0 65%,#38a9e8 100%);
  --tile-a:linear-gradient(135deg,#08639f,#1a8fd6); --tile-b:linear-gradient(135deg,#0b7cc0,#38a9e8);
  --tile-c:linear-gradient(135deg,#0e7a6b,#1fbfa6); --tile-d:linear-gradient(135deg,#355070,#6b8299);
}
@media (prefers-color-scheme: dark){
  :root[data-palette="sky"]:not([data-theme="light"]){
  --bg:#07151f; --surface:#0e2230; --surface-2:#153142; --ink:#e3f3fc; --ink-2:#a5c6da; --ink-3:#7fa3ba;
  --line:#1f3f54; --brand:#5ec3f6; --brand-ink:#032131; --on-capex:#032131;
  --capex:#4db8ee; --capex-soft:#103449; --info:#7ac4ee; --info-soft:#123a52;
  --mute:#9fbccf; --mute-soft:#1b3547; --focus:#4db8ee; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#0b4f7d 0%,#1274b5 60%,#2a97d4 100%);
  --tile-a:linear-gradient(135deg,#0b4f7d,#1a86c4); --tile-b:linear-gradient(135deg,#1274b5,#2a97d4);
  --tile-c:linear-gradient(135deg,#0d5c54,#1aa393); --tile-d:linear-gradient(135deg,#2d4256,#6f89a0);
  color-scheme:dark;
  }
}
:root[data-palette="sky"][data-theme="dark"]{
  --bg:#07151f; --surface:#0e2230; --surface-2:#153142; --ink:#e3f3fc; --ink-2:#a5c6da; --ink-3:#7fa3ba;
  --line:#1f3f54; --brand:#5ec3f6; --brand-ink:#032131; --on-capex:#032131;
  --capex:#4db8ee; --capex-soft:#103449; --info:#7ac4ee; --info-soft:#123a52;
  --mute:#9fbccf; --mute-soft:#1b3547; --focus:#4db8ee; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#0b4f7d 0%,#1274b5 60%,#2a97d4 100%);
  --tile-a:linear-gradient(135deg,#0b4f7d,#1a86c4); --tile-b:linear-gradient(135deg,#1274b5,#2a97d4);
  --tile-c:linear-gradient(135deg,#0d5c54,#1aa393); --tile-d:linear-gradient(135deg,#2d4256,#6f89a0);
  color-scheme:dark;
}
:root[data-palette="green"]{
  --bg:#eaf6f0; --surface:#ffffff; --surface-2:#dbeee3; --ink:#0e2a1c; --ink-2:#33543f; --ink-3:#4a6a58;
  --line:#c2ddc9; --brand:#0e7a49; --brand-ink:#ffffff; --on-capex:#ffffff;
  --capex:#178a55; --capex-soft:#d6f0e0; --info:#0f7a5e; --info-soft:#d6f0e5;
  --mute:#4f7361; --mute-soft:#dfece3; --focus:#1ea868; --overlay:rgba(9,30,20,.55);
  --shadow:0 1px 2px rgba(14,42,28,.06),0 4px 14px rgba(14,42,28,.06);
  --hero:linear-gradient(120deg,#0d5c37 0%,#127a4a 65%,#2fa86e 100%);
  --tile-a:linear-gradient(135deg,#0d5c37,#1f9c5f); --tile-b:linear-gradient(135deg,#127a4a,#2fa86e);
  --tile-c:linear-gradient(135deg,#0e6b74,#1fa6b0); --tile-d:linear-gradient(135deg,#38553f,#6b9980);
}
@media (prefers-color-scheme: dark){
  :root[data-palette="green"]:not([data-theme="light"]){
  --bg:#08170f; --surface:#0f2519; --surface-2:#163722; --ink:#e6f7ec; --ink-2:#a9d3b8; --ink-3:#82ac93;
  --line:#254a34; --brand:#7fd9a8; --brand-ink:#052014; --on-capex:#052014;
  --capex:#5fce93; --capex-soft:#143a26; --info:#6fd0ab; --info-soft:#123a2c;
  --mute:#a0c2ac; --mute-soft:#1c3527; --focus:#5fce93; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#0d4a2e 0%,#146b3f 60%,#219259 100%);
  --tile-a:linear-gradient(135deg,#0d4a2e,#1c8752); --tile-b:linear-gradient(135deg,#146b3f,#219259);
  --tile-c:linear-gradient(135deg,#0d5c54,#1aa393); --tile-d:linear-gradient(135deg,#2d4a3a,#6f9a80);
  color-scheme:dark;
  }
}
:root[data-palette="green"][data-theme="dark"]{
  --bg:#08170f; --surface:#0f2519; --surface-2:#163722; --ink:#e6f7ec; --ink-2:#a9d3b8; --ink-3:#82ac93;
  --line:#254a34; --brand:#7fd9a8; --brand-ink:#052014; --on-capex:#052014;
  --capex:#5fce93; --capex-soft:#143a26; --info:#6fd0ab; --info-soft:#123a2c;
  --mute:#a0c2ac; --mute-soft:#1c3527; --focus:#5fce93; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#0d4a2e 0%,#146b3f 60%,#219259 100%);
  --tile-a:linear-gradient(135deg,#0d4a2e,#1c8752); --tile-b:linear-gradient(135deg,#146b3f,#219259);
  --tile-c:linear-gradient(135deg,#0d5c54,#1aa393); --tile-d:linear-gradient(135deg,#2d4a3a,#6f9a80);
  color-scheme:dark;
}
:root[data-palette="orange"]{
  --bg:#fdf1e4; --surface:#ffffff; --surface-2:#fae3ca; --ink:#331d08; --ink-2:#6a4322; --ink-3:#83583a;
  --line:#f0d1a8; --brand:#9a4407; --brand-ink:#ffffff; --on-capex:#ffffff;
  --capex:#c05f0d; --capex-soft:#fbe4cb; --info:#b85a12; --info-soft:#f9e5cd;
  --mute:#8a6a4b; --mute-soft:#f3e6d3; --focus:#e07b1f; --overlay:rgba(46,24,4,.55);
  --shadow:0 1px 2px rgba(51,29,8,.06),0 4px 14px rgba(51,29,8,.06);
  --hero:linear-gradient(120deg,#9a4407 0%,#c2620f 65%,#e89a3d 100%);
  --tile-a:linear-gradient(135deg,#9a4407,#d3720f); --tile-b:linear-gradient(135deg,#c2620f,#e89a3d);
  --tile-c:linear-gradient(135deg,#8a6408,#c99a16); --tile-d:linear-gradient(135deg,#5c4a35,#997d5e);
}
@media (prefers-color-scheme: dark){
  :root[data-palette="orange"]:not([data-theme="light"]){
  --bg:#1c1006; --surface:#2b1a0c; --surface-2:#3c2712; --ink:#fbeadb; --ink-2:#dcb98d; --ink-3:#b8926a;
  --line:#4a3016; --brand:#f3ac5e; --brand-ink:#1c0f04; --on-capex:#1c0f04;
  --capex:#f0a24e; --capex-soft:#3e2712; --info:#e6a35f; --info-soft:#3a2712;
  --mute:#c9ab84; --mute-soft:#37270f; --focus:#f0a24e; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#7a3706 0%,#a35310 60%,#c97b2c 100%);
  --tile-a:linear-gradient(135deg,#7a3706,#b3630f); --tile-b:linear-gradient(135deg,#a35310,#c97b2c);
  --tile-c:linear-gradient(135deg,#6b4f08,#a67f14); --tile-d:linear-gradient(135deg,#4a3a28,#8a7052);
  color-scheme:dark;
  }
}
:root[data-palette="orange"][data-theme="dark"]{
  --bg:#1c1006; --surface:#2b1a0c; --surface-2:#3c2712; --ink:#fbeadb; --ink-2:#dcb98d; --ink-3:#b8926a;
  --line:#4a3016; --brand:#f3ac5e; --brand-ink:#1c0f04; --on-capex:#1c0f04;
  --capex:#f0a24e; --capex-soft:#3e2712; --info:#e6a35f; --info-soft:#3a2712;
  --mute:#c9ab84; --mute-soft:#37270f; --focus:#f0a24e; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#7a3706 0%,#a35310 60%,#c97b2c 100%);
  --tile-a:linear-gradient(135deg,#7a3706,#b3630f); --tile-b:linear-gradient(135deg,#a35310,#c97b2c);
  --tile-c:linear-gradient(135deg,#6b4f08,#a67f14); --tile-d:linear-gradient(135deg,#4a3a28,#8a7052);
  color-scheme:dark;
}
:root[data-palette="yellow"]{
  --bg:#fdf8e2; --surface:#ffffff; --surface-2:#f8edc0; --ink:#332b06; --ink-2:#6a5a17; --ink-3:#83702a;
  --line:#ecdd94; --brand:#7a6008; --brand-ink:#ffffff; --on-capex:#221a02;
  --capex:#a1830e; --capex-soft:#f6ecc0; --info:#8a7410; --info-soft:#f4ecc8;
  --mute:#7d6f3d; --mute-soft:#f0e8c8; --focus:#c9a316; --overlay:rgba(41,33,4,.55);
  --shadow:0 1px 2px rgba(51,43,6,.06),0 4px 14px rgba(51,43,6,.06);
  --hero:linear-gradient(120deg,#8a6d06 0%,#b3900d 65%,#dfbb3a 100%);
  --tile-a:linear-gradient(135deg,#8a6d06,#c19a10); --tile-b:linear-gradient(135deg,#b3900d,#dfbb3a);
  --tile-c:linear-gradient(135deg,#6f7a0c,#a3b31c); --tile-d:linear-gradient(135deg,#5c5430,#95875a);
}
@media (prefers-color-scheme: dark){
  :root[data-palette="yellow"]:not([data-theme="light"]){
  --bg:#1a1504; --surface:#28210a; --surface-2:#3a2f0e; --ink:#faf3d6; --ink-2:#dccb85; --ink-3:#b8a95e;
  --line:#4a3f14; --brand:#e6c14a; --brand-ink:#241c04; --on-capex:#241c04;
  --capex:#dcb93f; --capex-soft:#3c3210; --info:#d3b54e; --info-soft:#382f0e;
  --mute:#c4b686; --mute-soft:#332b0e; --focus:#e6c14a; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#5c4a05 0%,#82680c 60%,#a88e24 100%);
  --tile-a:linear-gradient(135deg,#5c4a05,#8a710f); --tile-b:linear-gradient(135deg,#82680c,#a88e24);
  --tile-c:linear-gradient(135deg,#4f5808,#7f8f16); --tile-d:linear-gradient(135deg,#463e20,#847653);
  color-scheme:dark;
  }
}
:root[data-palette="yellow"][data-theme="dark"]{
  --bg:#1a1504; --surface:#28210a; --surface-2:#3a2f0e; --ink:#faf3d6; --ink-2:#dccb85; --ink-3:#b8a95e;
  --line:#4a3f14; --brand:#e6c14a; --brand-ink:#241c04; --on-capex:#241c04;
  --capex:#dcb93f; --capex-soft:#3c3210; --info:#d3b54e; --info-soft:#382f0e;
  --mute:#c4b686; --mute-soft:#332b0e; --focus:#e6c14a; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#5c4a05 0%,#82680c 60%,#a88e24 100%);
  --tile-a:linear-gradient(135deg,#5c4a05,#8a710f); --tile-b:linear-gradient(135deg,#82680c,#a88e24);
  --tile-c:linear-gradient(135deg,#4f5808,#7f8f16); --tile-d:linear-gradient(135deg,#463e20,#847653);
  color-scheme:dark;
}
/* Kang, 2026-09-29: "เพิ่มธีมสีหลายๆ สีผสมกัน" -- the 5 themes above are each a single hue in a few shades; these
   3 new ones ("sunset"/"ocean"/"berry") each blend TWO distinct hues instead (one for --brand/--capex, a second
   for --info and half of --hero/--tile-*), so the theme picker swatch visibly shows two colours blending together.
   good/warn/bad/opex/h1-h6 stay untouched here too, same as every palette above -- those always mean the same
   thing regardless of theme. */
:root[data-palette="sunset"]{
  --bg:#fdf2ec; --surface:#ffffff; --surface-2:#f7ded0; --ink:#3a1f1a; --ink-2:#6b4238; --ink-3:#8a5f52;
  --line:#f0d3bf; --brand:#c2410c; --brand-ink:#ffffff; --on-capex:#ffffff;
  --capex:#c2410c; --capex-soft:#fbe1cb; --info:#7c3aed; --info-soft:#ece2fc;
  --mute:#8a6a5a; --mute-soft:#f3e6da; --focus:#d9480f; --overlay:rgba(50,22,10,.55);
  --shadow:0 1px 2px rgba(58,31,26,.06),0 4px 14px rgba(58,31,26,.06);
  --hero:linear-gradient(120deg,#9a3412 0%,#c2410c 45%,#7c3aed 100%);
  --tile-a:linear-gradient(135deg,#9a3412,#e0672c); --tile-b:linear-gradient(135deg,#6d28d9,#a855f7);
  --tile-c:linear-gradient(135deg,#a3170f,#e0672c); --tile-d:linear-gradient(135deg,#7a5c52,#ab8a7a);
}
@media (prefers-color-scheme: dark){
  :root[data-palette="sunset"]:not([data-theme="light"]){
  --bg:#1c110c; --surface:#2a1810; --surface-2:#3a2216; --ink:#fbe9df; --ink-2:#dcb6a3; --ink-3:#b89383;
  --line:#4a2c1c; --brand:#f3966a; --brand-ink:#241205; --on-capex:#241205;
  --capex:#f0a25c; --capex-soft:#3e2612; --info:#c4a0f5; --info-soft:#33234a;
  --mute:#cba896; --mute-soft:#37271b; --focus:#f3966a; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#6b230a 0%,#9a4412 55%,#7c3aed 100%);
  --tile-a:linear-gradient(135deg,#6b230a,#c2601f); --tile-b:linear-gradient(135deg,#5b21b6,#8b5cf6);
  --tile-c:linear-gradient(135deg,#7a1210,#c2601f); --tile-d:linear-gradient(135deg,#4a352b,#8a6f5f);
  color-scheme:dark;
  }
}
:root[data-palette="sunset"][data-theme="dark"]{
  --bg:#1c110c; --surface:#2a1810; --surface-2:#3a2216; --ink:#fbe9df; --ink-2:#dcb6a3; --ink-3:#b89383;
  --line:#4a2c1c; --brand:#f3966a; --brand-ink:#241205; --on-capex:#241205;
  --capex:#f0a25c; --capex-soft:#3e2612; --info:#c4a0f5; --info-soft:#33234a;
  --mute:#cba896; --mute-soft:#37271b; --focus:#f3966a; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#6b230a 0%,#9a4412 55%,#7c3aed 100%);
  --tile-a:linear-gradient(135deg,#6b230a,#c2601f); --tile-b:linear-gradient(135deg,#5b21b6,#8b5cf6);
  --tile-c:linear-gradient(135deg,#7a1210,#c2601f); --tile-d:linear-gradient(135deg,#4a352b,#8a6f5f);
  color-scheme:dark;
}
:root[data-palette="ocean"]{
  --bg:#e9f4f2; --surface:#ffffff; --surface-2:#d7ece7; --ink:#0c2733; --ink-2:#2f5468; --ink-3:#4a6f7e;
  --line:#c0dcd8; --brand:#0e4d64; --brand-ink:#ffffff; --on-capex:#ffffff;
  --capex:#0f7a6b; --capex-soft:#d3f0e5; --info:#3730a3; --info-soft:#e2e0f8;
  --mute:#4c6a72; --mute-soft:#dceae6; --focus:#0f9488; --overlay:rgba(6,30,38,.55);
  --shadow:0 1px 2px rgba(12,39,51,.06),0 4px 14px rgba(12,39,51,.06);
  --hero:linear-gradient(120deg,#0c3a4d 0%,#0f7a6b 55%,#3730a3 100%);
  --tile-a:linear-gradient(135deg,#0c3a4d,#0f7a6b); --tile-b:linear-gradient(135deg,#312e81,#4f46e5);
  --tile-c:linear-gradient(135deg,#0e6b5c,#1fbfa6); --tile-d:linear-gradient(135deg,#355064,#6b8f99);
}
@media (prefers-color-scheme: dark){
  :root[data-palette="ocean"]:not([data-theme="light"]){
  --bg:#061a1f; --surface:#0d272e; --surface-2:#133941; --ink:#dff3ef; --ink-2:#a0c9c2; --ink-3:#78a39c;
  --line:#1f4750; --brand:#5fc9b8; --brand-ink:#03211c; --on-capex:#03211c;
  --capex:#4fd6b0; --capex-soft:#0f3a2e; --info:#a5a0f2; --info-soft:#26234a;
  --mute:#93b8b0; --mute-soft:#173832; --focus:#5fc9b8; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#0a2d3c 0%,#116b5a 55%,#4338ca 100%);
  --tile-a:linear-gradient(135deg,#0a2d3c,#178a6f); --tile-b:linear-gradient(135deg,#312e81,#6d5ff0);
  --tile-c:linear-gradient(135deg,#0d5c54,#1aa393); --tile-d:linear-gradient(135deg,#2c4650,#6f9089);
  color-scheme:dark;
  }
}
:root[data-palette="ocean"][data-theme="dark"]{
  --bg:#061a1f; --surface:#0d272e; --surface-2:#133941; --ink:#dff3ef; --ink-2:#a0c9c2; --ink-3:#78a39c;
  --line:#1f4750; --brand:#5fc9b8; --brand-ink:#03211c; --on-capex:#03211c;
  --capex:#4fd6b0; --capex-soft:#0f3a2e; --info:#a5a0f2; --info-soft:#26234a;
  --mute:#93b8b0; --mute-soft:#173832; --focus:#5fc9b8; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#0a2d3c 0%,#116b5a 55%,#4338ca 100%);
  --tile-a:linear-gradient(135deg,#0a2d3c,#178a6f); --tile-b:linear-gradient(135deg,#312e81,#6d5ff0);
  --tile-c:linear-gradient(135deg,#0d5c54,#1aa393); --tile-d:linear-gradient(135deg,#2c4650,#6f9089);
  color-scheme:dark;
}
:root[data-palette="berry"]{
  --bg:#fbeef5; --surface:#ffffff; --surface-2:#f5dcea; --ink:#341b30; --ink-2:#623a58; --ink-3:#805876;
  --line:#eeccdf; --brand:#a3216d; --brand-ink:#ffffff; --on-capex:#ffffff;
  --capex:#a3216d; --capex-soft:#f6dcec; --info:#5b21b6; --info-soft:#e6def8;
  --mute:#7d5a72; --mute-soft:#f0e0ea; --focus:#c2368c; --overlay:rgba(40,10,30,.55);
  --shadow:0 1px 2px rgba(52,27,48,.06),0 4px 14px rgba(52,27,48,.06);
  --hero:linear-gradient(120deg,#701a4d 0%,#a3216d 55%,#5b21b6 100%);
  --tile-a:linear-gradient(135deg,#701a4d,#c2368c); --tile-b:linear-gradient(135deg,#4c1d95,#7c3aed);
  --tile-c:linear-gradient(135deg,#9d174d,#db2777); --tile-d:linear-gradient(135deg,#5c4055,#95738a);
}
@media (prefers-color-scheme: dark){
  :root[data-palette="berry"]:not([data-theme="light"]){
  --bg:#1e0f1a; --surface:#2c1727; --surface-2:#3c1f35; --ink:#f8e6f1; --ink-2:#d3a8c4; --ink-3:#ac82a0;
  --line:#4a2740; --brand:#e880bb; --brand-ink:#2a0f22; --on-capex:#2a0f22;
  --capex:#e880bb; --capex-soft:#3c1f34; --info:#b79cf7; --info-soft:#332355;
  --mute:#c79cbc; --mute-soft:#37232f; --focus:#e880bb; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#5c1440 0%,#8b1f63 55%,#5b21b6 100%);
  --tile-a:linear-gradient(135deg,#5c1440,#a3306f); --tile-b:linear-gradient(135deg,#3c1a7a,#7c3aed);
  --tile-c:linear-gradient(135deg,#6b0f38,#b83a6f); --tile-d:linear-gradient(135deg,#4a3040,#8a6a7c);
  color-scheme:dark;
  }
}
:root[data-palette="berry"][data-theme="dark"]{
  --bg:#1e0f1a; --surface:#2c1727; --surface-2:#3c1f35; --ink:#f8e6f1; --ink-2:#d3a8c4; --ink-3:#ac82a0;
  --line:#4a2740; --brand:#e880bb; --brand-ink:#2a0f22; --on-capex:#2a0f22;
  --capex:#e880bb; --capex-soft:#3c1f34; --info:#b79cf7; --info-soft:#332355;
  --mute:#c79cbc; --mute-soft:#37232f; --focus:#e880bb; --overlay:rgba(0,0,0,.65);
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 14px rgba(0,0,0,.3);
  --hero:linear-gradient(120deg,#5c1440 0%,#8b1f63 55%,#5b21b6 100%);
  --tile-a:linear-gradient(135deg,#5c1440,#a3306f); --tile-b:linear-gradient(135deg,#3c1a7a,#7c3aed);
  --tile-c:linear-gradient(135deg,#6b0f38,#b83a6f); --tile-d:linear-gradient(135deg,#4a3040,#8a6a7c);
  color-scheme:dark;
}

*{box-sizing:border-box}
body{
  background:var(--bg); color:var(--ink); font-family:var(--sans); font-size:14px; line-height:1.5;
  padding-inline:calc(16px + env(safe-area-inset-left,0px)) calc(16px + env(safe-area-inset-right,0px));
  padding-block:calc(22px + env(safe-area-inset-top,0px)) calc(64px + env(safe-area-inset-bottom,0px));
}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer}
:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.num,.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}

.app{max-width:1120px;margin:0 auto;display:grid;gap:18px}

/* header */
.top{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:14px}
/* flex-basis:0 (instead of the default auto) keeps a long title+description (e.g. Capex's) from being sized by
   its own unwrapped text width when the browser decides whether it and .actions fit on the same line -- that
   used to shove .actions down onto its own row below a long title, unlike shorter titles (e.g. Projects), where
   it stayed put top-right next to the title. With a 0 basis the title simply grows to fill whatever's left of
   the row after .actions claims its space, and its own text wraps inside that width instead. */
.hdr-title{flex:1 1 0%;min-width:260px}
.top h1{margin:0;font-size:26px;line-height:1.2;font-weight:700;letter-spacing:-.01em;text-wrap:balance}
.top p{margin:4px 0 0;color:var(--ink-2)}
.role{display:inline-block;margin-left:8px;font-size:12px;padding:1px 9px;border-radius:999px;background:var(--surface-2);color:var(--ink-2)}
.actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.field-inline{display:flex;flex-direction:column;gap:2px}
.field-inline label{font-size:11px;color:var(--ink-3);letter-spacing:.04em}

.btn{
  height:38px;padding:0 14px;border-radius:9px;border:1px solid var(--line);background:var(--surface);
  font-weight:500;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
}
.btn:hover{background:var(--surface-2)}
.btn.primary{background:var(--brand);color:var(--brand-ink);border-color:transparent}
.btn.primary:hover{filter:brightness(1.08)}
.btn.danger{background:var(--bad);color:#fff;border-color:transparent}
.btn.ok{background:var(--good);color:#fff;border-color:transparent}
.btn.danger:hover,.btn.ok:hover{filter:brightness(1.08);background:inherit}
.btn.danger-o{background:#fff;color:var(--bad);border-color:var(--bad)}
.btn.danger-o:hover{background:var(--bad);color:#fff}
.btn.ghost{border-color:transparent;background:transparent;color:var(--ink-2)}
.btn.ghost:hover{background:var(--surface-2);color:var(--ink)}
.btn.sm{height:32px;padding:0 11px;font-size:13px}
.btn:disabled{opacity:.5;cursor:not-allowed}
.sel{
  height:38px;padding:0 10px;border-radius:9px;border:1px solid var(--line);background:var(--surface);min-width:150px;
}

/* notice */
.notice{padding:10px 14px;border-radius:10px;background:var(--warn-soft);color:var(--warn);font-weight:500}

/* hotel tabs */
.seg{display:inline-flex;flex-wrap:wrap;gap:2px;padding:3px;border-radius:11px;background:var(--surface-2)}
.seg button{border:0;background:transparent;padding:7px 14px;border-radius:8px;font-weight:500;color:var(--ink-2)}
.seg button[aria-pressed="true"]{background:var(--surface);color:var(--ink);box-shadow:var(--shadow)}
.seg .code{font-family:var(--mono);font-size:11px;color:var(--ink-3);margin-right:6px}

/* segOrSelect() (app.js): a .seg row that wraps onto several lines on a phone once it has more than a couple of
   options (Capex register's ทั้งหมด/CapEx/OpEx, the project list's ทั้งหมด/ยังไม่ปิด/เสร็จสิ้น, the ticket list's
   เปิดอยู่/ปิดแล้ว/ทั้งหมด and มอบหมายให้ฉัน/...) shows as a native dropdown there instead -- same swap-the-whole-
   control trick as .tabs/.tab-menu above. Desktop is untouched: .seg-filter-sel only appears at the same width
   the rest of this file already treats as "phone" (see the .list-tools rules further down), and scoped to this
   one class pair so it never affects an unrelated .seg (the language switch, tabBar()'s own row). */
.seg-filter-sel{display:none}
@media (max-width:760px){
  .seg-filter{display:none}
  .seg-filter-sel{display:block;width:100%}
}

/* panels */
.panel{background:var(--surface);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow)}
.eyebrow{font-size:12px;letter-spacing:.05em;color:var(--ink-3);font-weight:500}

/* summary */
.sum{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);gap:0}
.sum-main{padding:22px 24px;display:grid;gap:10px;align-content:start}
.sum-side{padding:22px 24px;border-left:1px solid var(--line);display:grid;gap:14px;align-content:start}
.big{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:40px;line-height:1.1;font-weight:500;letter-spacing:-.02em}
.big .cur{font-size:22px;color:var(--ink-3);margin-right:6px}
.sub{color:var(--ink-2)}
.split{display:flex;height:12px;border-radius:6px;overflow:hidden;background:var(--surface-2);gap:2px;margin-top:6px}
.split i{display:block;min-width:0}
.cx{background:var(--capex)} .ox{background:var(--opex)}
.legend{display:flex;flex-wrap:wrap;gap:8px 22px;color:var(--ink-2)}
.legend .dot{display:inline-block;width:9px;height:9px;border-radius:3px;margin-right:7px}
.legend strong{font-family:var(--mono);font-weight:500;color:var(--ink);margin-left:6px}
.legend em{font-style:normal;color:var(--ink-3);margin-left:6px}
.side-rows{display:grid;gap:4px}
.srow{display:flex;justify-content:space-between;align-items:baseline;gap:10px;width:100%;border:0;background:transparent;
  padding:5px 8px;margin-inline:-8px;width:calc(100% + 16px);border-radius:8px;text-align:left}
button.srow:hover{background:var(--surface-2)}
.srow .lab{display:flex;align-items:center;gap:8px;color:var(--ink-2)}
.srow .val{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:500}
.sdot{display:inline-block;width:9px;height:9px;border-radius:50%}
.side-act{display:grid;gap:8px;border-top:1px solid var(--line);padding-top:14px}
.prog{height:8px;border-radius:5px;background:var(--surface-2);overflow:hidden}
.prog i{display:block;height:100%;background:var(--brand);border-radius:5px}
.prog.over i{background:var(--bad)}
.progtxt{color:var(--ink-3);font-size:12px}

/* overview */
.ov{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(0,1fr);gap:18px}
.ov .panel{padding:18px 20px}
.ph{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-bottom:14px;flex-wrap:wrap}
.ph h2{margin:0;font-size:15px;font-weight:600}
.mini-legend{display:flex;flex-wrap:wrap;row-gap:6px;gap:14px;color:var(--ink-3);font-size:12px}
.mini-legend .dot{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:5px}
.chart-scroll{overflow-x:auto}
.chart{display:flex;align-items:flex-end;gap:6px;min-width:440px;padding-top:6px}
.mc{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:4px}
.mc.sep{margin-left:8px;padding-left:8px;border-left:1px dashed var(--line)}
.mv{font-family:var(--mono);font-size:10px;color:var(--ink-3);height:14px}
.mbwrap{height:122px;width:100%;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:3px}
.mb{width:70%;max-width:30px;display:flex;flex-direction:column;justify-content:flex-end;border-radius:4px 4px 2px 2px;overflow:hidden;gap:1px}
.mb i{display:block;flex-basis:0;min-height:0}
.ml{font-size:10.5px;color:var(--ink-2);white-space:nowrap}
.hb{display:grid;grid-template-columns:34px 1fr auto;column-gap:10px;row-gap:6px;align-items:center;width:100%;text-align:left;
  padding:10px 10px;border:1px solid transparent;border-radius:10px;background:transparent}
.hb+.hb{margin-top:2px}
.hb:hover{background:var(--surface-2)}
.hb.sel-h{border-color:var(--line);background:var(--surface-2)}
.hb .chip{justify-self:start}
.hb .hn{font-weight:500}
.hb .ha{font-family:var(--mono);font-variant-numeric:tabular-nums}
.hbar{grid-column:2 / 4;height:8px;border-radius:4px;background:var(--surface-2);overflow:hidden}
.hb.sel-h .hbar{background:var(--surface)}
.hfill{display:flex;height:100%;gap:1px}
.hfill i{display:block;flex-basis:0}
.chip{display:inline-block;font-family:var(--mono);font-size:11px;font-weight:500;padding:2px 7px;border-radius:6px;background:var(--mute-soft);color:var(--mute)}
.hint{font-size:12px;color:var(--ink-3)}

/* list */
.list-tools{display:flex;flex-wrap:wrap;gap:10px;align-items:center;justify-content:space-between}
.list-tools .left{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.search{height:38px;padding:0 12px;border-radius:9px;border:1px solid var(--line);background:var(--surface);min-width:220px}
.count{color:var(--ink-3);font-size:12.5px}
.group{overflow:hidden}
.group+.group{margin-top:14px}
.gh{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;border-bottom:1px solid var(--line);flex-wrap:wrap}
.gh .t{display:flex;align-items:center;gap:9px;font-weight:600}
.gh .t small{font-weight:400;color:var(--ink-3)}
.gh .dot{width:10px;height:10px;border-radius:3px}
.gh .sumv{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:500}
.lh,.row{
  display:grid;column-gap:12px;align-items:center;padding:11px 16px;
  grid-template-columns:minmax(200px,2.6fr) 64px 132px 110px 100px 150px 84px;
}
.lh{font-size:11.5px;color:var(--ink-3);letter-spacing:.03em;padding-block:8px;background:var(--surface-2);border-radius:12px;margin-bottom:10px}
.row+.row{border-top:1px solid var(--line)}
.row:hover{background:color-mix(in srgb,var(--surface-2) 55%,transparent)}
.r-name strong{display:block;font-weight:600;word-break:break-word}
.r-name small{display:block;color:var(--ink-3);font-size:12px;word-break:break-word}
.row.cancelled .r-name strong{text-decoration:line-through;color:var(--ink-3)}
.row.cancelled{opacity:.7}
.ex{display:inline-block;margin-left:8px;font-size:10.5px;font-weight:500;padding:1px 7px;border-radius:999px;background:var(--info-soft);color:var(--info);vertical-align:1px}
.r-calc{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:12.5px;color:var(--ink-2)}
.r-budget{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:500;text-align:right}
.r-actual{font-family:var(--mono);font-variant-numeric:tabular-nums;text-align:right;color:var(--ink-2)}
.pill{display:inline-block;border:1px solid transparent;border-radius:999px;padding:4px 11px;font-size:12px;font-weight:500;white-space:nowrap}
.st-draft{background:var(--mute-soft);color:var(--mute)}
.st-pending{background:var(--warn-soft);color:var(--warn)}
.st-approved{background:var(--info-soft);color:var(--info)}
.st-rejected{background:var(--bad-soft);color:var(--bad)}
.st-done{background:var(--good-soft);color:var(--good)}
.st-cancelled{background:var(--mute-soft);color:var(--mute)}
.r-act{display:flex;justify-content:flex-end;gap:2px}
.r-act .btn{height:30px;padding:0 10px;font-size:12.5px}
.empty{padding:34px 20px;text-align:center;color:var(--ink-2);display:grid;gap:12px;justify-items:center}

/* modal */
.overlay{position:fixed;inset:0;background:var(--overlay);display:grid;place-items:center;padding:16px;z-index:70;overflow:auto}
.modal{width:min(660px,100%);max-height:calc(100dvh - 32px);overflow:auto;background:var(--surface);border:1px solid var(--line);border-radius:16px;box-shadow:0 20px 60px rgba(0,0,0,.35)}
.modal.small{width:min(420px,100%)}
.mh{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid var(--line)}
.mh h2{margin:0;font-size:17px;font-weight:600}
.mbody{padding:18px 20px;display:grid;gap:16px}
/* a grid item's automatic min-width is its content's min-content size, so a wide table/grid deep inside a modal
   section (nothing unusual about the section itself, just a table that doesn't wrap on a narrow screen) can force
   the whole modal wider than the viewport instead of scrolling within its own .tbl-wrap -- min-width:0 here lets
   each direct section shrink to the modal's real width so that inner overflow:auto containers do the scrolling */
.mbody>*{min-width:0}
.mf{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:14px 20px;border-top:1px solid var(--line);flex-wrap:wrap}
.fg{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.fg .full{grid-column:1 / -1}
.f{display:grid;gap:5px;align-content:start}
.f>label,.f>.lbl{font-size:12.5px;color:var(--ink-2);font-weight:500}
.in{height:40px;width:100%;padding:0 11px;border-radius:9px;border:1px solid var(--line);background:var(--surface);color:var(--ink)}
textarea.in{height:auto;min-height:72px;padding:9px 11px;resize:vertical}
.typepick{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.typepick label{display:block;border:1.5px solid var(--line);border-radius:11px;padding:10px 12px;cursor:pointer}
.typepick label b{display:flex;align-items:center;gap:8px;font-weight:600}
.typepick label span{display:block;color:var(--ink-3);font-size:12px;margin-top:2px}
.typepick input{position:absolute;opacity:0;pointer-events:none}
.typepick label.on.t-capex{border-color:var(--capex);background:var(--capex-soft)}
.typepick label.on.t-opex{border-color:var(--opex);background:var(--opex-soft)}
.typepick label:focus-within{outline:2px solid var(--focus);outline-offset:2px}
.totalbox{display:flex;align-items:baseline;gap:10px}
.totalbox .num{font-size:22px;font-weight:500}

/* Kang, 2026-10-06: repeatable line-items builder in the Capex add/edit form (openForm() in app.js), replacing
   the old single qty/unit_price pair -- see server.item_total()'s own comment for the discount/VAT math. */
.lineitems{display:grid;gap:8px}
.lineitem{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,.7fr) minmax(0,1fr) auto;gap:6px 8px;align-items:center}
.discrow{display:grid;grid-template-columns:1fr auto;gap:8px}
.discrow select{width:auto}
/* the read-only breakdown in the item detail drawer (drawerBody() in app.js) */
.lineitems-ro{display:grid;gap:4px}
.lineitem-ro{display:flex;justify-content:space-between;gap:10px}
.lineitem-ro .num{color:var(--ink-2);white-space:nowrap}
@media (max-width:560px){
  .lineitem{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .discrow{grid-template-columns:minmax(0,1fr)}
}

/* project expense payment schedule (expenseScheduleModal() in projects.js) -- same shape as .lineitems/.lineitem
   above, one row per installment (date + amount + remove) */
.payrows{display:grid;gap:8px}
.payrow{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr) auto;gap:6px 8px;align-items:center}
@media (max-width:560px){
  .payrow{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
}

/* drawer */
.drawer-ov{position:fixed;inset:0;background:var(--overlay);z-index:60;display:flex;justify-content:flex-end}
.drawer{width:min(540px,100%);height:100%;overflow:auto;background:var(--surface);border-left:1px solid var(--line);box-shadow:-10px 0 40px rgba(0,0,0,.25)}
.dh{padding:16px 20px;border-bottom:1px solid var(--line);display:grid;gap:8px;position:sticky;top:0;background:var(--surface);z-index:1;padding-top:calc(16px + env(safe-area-inset-top,0px))}
.dh .row1{display:flex;justify-content:space-between;gap:10px;align-items:flex-start}
.dh h2{margin:0;font-size:17px;font-weight:600;word-break:break-word}
.dbody{padding:18px 20px;display:grid;gap:22px;padding-bottom:calc(28px + env(safe-area-inset-bottom,0px))}
.sec{display:grid;gap:8px}
.sec h3,.box h3{margin:0;font-size:13.5px;font-weight:600}
.kv{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 16px}
.kv .k{font-size:11.5px;color:var(--ink-3);letter-spacing:.03em}
.kv .v{word-break:break-word}
.kv .full{grid-column:1 / -1}
.box{border:1px solid var(--line);border-radius:12px;padding:14px;display:grid;gap:12px;background:var(--surface-2)}
.btnrow{display:flex;flex-wrap:wrap;gap:8px}
.tl{list-style:none;margin:0;padding:0}
.tl li{position:relative;padding:0 0 16px 22px;border-left:2px solid var(--line);margin-left:5px}
.tl li::before{content:"";position:absolute;left:-7px;top:4px;width:12px;height:12px;border-radius:50%;background:var(--ev,var(--mute));border:2px solid var(--surface)}
.tl li:last-child{border-left-color:transparent}
.tl li.none{border-left-color:transparent;padding-left:0;margin-left:0;color:var(--ink-3)}
.tl li.none::before{display:none}
.tl .t{font-weight:500}
.tl .m{font-size:12px;color:var(--ink-3)}
.tl .x{margin-top:2px;color:var(--ink-2);word-break:break-word;white-space:pre-wrap}
.files{display:grid;gap:6px}
.file{display:flex;justify-content:space-between;gap:10px;align-items:center;padding:8px 10px;border:1px solid var(--line);border-radius:9px;word-break:break-all}
.file a{color:var(--info);font-weight:500}
.file small{color:var(--ink-3);white-space:nowrap}

.toast{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(20px + env(safe-area-inset-bottom,0px));background:var(--ink);color:var(--bg);
  padding:10px 16px;border-radius:10px;font-weight:500;z-index:90;max-width:calc(100% - 32px);box-shadow:0 8px 30px rgba(0,0,0,.3)}
.toast.err{background:var(--bad);color:#fff}

/* responsive */
@media (max-width:1040px){
  .lh{display:none}
  .row{grid-template-columns:repeat(2,minmax(0,1fr));row-gap:10px;padding:14px 16px}
  .row>.r-name,.row>.r-act{grid-column:1 / -1}
  .row>div[data-l]::before{content:attr(data-l);display:block;font-size:11px;color:var(--ink-3);letter-spacing:.03em;margin-bottom:1px}
  .r-budget,.r-actual{text-align:left}
  .r-act{justify-content:flex-start}
}
@media (max-width:820px){
  .sum,.ov{grid-template-columns:minmax(0,1fr)}
  .sum-side{border-left:0;border-top:1px solid var(--line)}
  .big{font-size:34px}
}
@media (max-width:560px){
  .fg,.kv{grid-template-columns:minmax(0,1fr)}
  .search{min-width:0;width:100%}
  .list-tools .left{width:100%}
  .top h1{font-size:23px}
  .drawer{border-left:0}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* ===== additions for the multi-department system ===== */
[hidden]{display:none!important}
/* the hotel logo strip, inside the profile panel (its own section, above the signature/password/logout
   buttons) -- see hotelStrip() in app.js */
.hdr-hotels{display:flex;flex-wrap:wrap;align-items:center;gap:10px;color:var(--ink-2)}
.profile-hotels{flex-wrap:wrap;border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:10px 0}
.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--line)}
.tabs button{border:0;background:transparent;padding:10px 16px;font-weight:500;color:var(--ink-2);border-bottom:2px solid transparent;margin-bottom:-1px;display:inline-flex;gap:8px;align-items:center}
.tabs button:hover{color:var(--ink)}
.tabs button[aria-selected="true"]{color:var(--ink);border-bottom-color:var(--brand)}
.badge{display:inline-block;min-width:20px;padding:0 7px;border-radius:999px;background:var(--bad);color:#fff;font-size:11.5px;font-weight:600;text-align:center;line-height:20px}
.badge.zero{background:var(--surface-2);color:var(--ink-3)}

/* announcement bell -- kept for any standalone use; the header itself now shows the bell inside profileMenu()'s
   panel instead (see B.announceMenuItem() in announcements.js and .profile-actions below) */
.announce-bell{position:relative;padding:0;width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;flex:none}
.bell-ico{width:19px;height:19px}
.announce-bell .badge{position:absolute;top:1px;right:1px;min-width:16px;height:16px;line-height:16px;padding:0 4px;font-size:10px}

/* profile/account menu (app.js's profileMenu()) -- the same single widget in .top's top-right corner at every
   screen width: a normal flex child of .actions on desktop (where .top's row already keeps .actions pinned to
   the right), pinned to .top's own corner via absolute positioning on a phone instead, where the header can
   wrap onto two lines (see the corner-pin override inside the mobile media query further below). Houses the
   account's own actions (signature/password/logout/language/hotels) plus the announcement bell, so a phone and
   a desktop window get the identical menu (Kang, 2026-09-25: previously desktop-only inline actions + a
   standalone bell icon). */
.profile-menu{position:relative;flex:none}
.profile-btn{
  width:38px;height:38px;border-radius:50%;background:var(--brand);color:var(--brand-ink);
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12.5px;
  border:0;cursor:pointer;list-style:none;
}
.profile-btn::-webkit-details-marker{display:none}
.profile-menu[open] .profile-btn{outline:2px solid var(--focus);outline-offset:2px}
.profile-btn-badge{position:absolute;top:-3px;right:-3px;min-width:16px;height:16px;line-height:16px;padding:0 4px;font-size:10px}
.profile-panel{
  position:absolute;top:calc(100% + 8px);right:0;z-index:40;background:var(--surface);border:1px solid var(--line);
  border-radius:12px;box-shadow:var(--shadow);padding:14px;min-width:240px;display:grid;gap:12px;
}
.profile-who{display:flex;gap:10px;align-items:center}
.profile-avatar{
  width:40px;height:40px;border-radius:50%;background:var(--surface-2);color:var(--ink-2);flex:none;
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12.5px;
}
.profile-name{font-weight:600}
.profile-role{font-size:12px;color:var(--ink-2)}
.profile-lang{border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:10px 0}
.profile-actions{display:grid;gap:6px}
.profile-actions .btn{justify-content:flex-start;width:100%}

/* login */
.login-wrap{min-height:calc(100dvh - 90px);display:grid;place-items:center}
.login{width:min(400px,100%);padding:28px 26px;display:grid;gap:16px}
.login-logo{display:block;margin:0 auto 4px;height:132px;width:auto}
.login h1{margin:0;font-size:22px;line-height:1.25;text-align:center}
.login .login-sub{margin:2px 0 0;color:var(--ink-2);text-align:center;font-size:13px}
.login p{margin:0;color:var(--ink-2)}
.err{color:var(--bad);background:var(--bad-soft);padding:9px 12px;border-radius:9px;font-weight:500}
.okmsg{color:var(--good);background:var(--good-soft);padding:9px 12px;border-radius:9px;font-weight:500}

/* approval chain */
.chain{display:grid;gap:0}
.step{display:grid;grid-template-columns:28px 1fr;column-gap:12px;position:relative;padding-bottom:14px}
.step:last-child{padding-bottom:0}
.step::before{content:"";position:absolute;left:13px;top:28px;bottom:0;width:2px;background:var(--line)}
.step:last-child::before{display:none}
.step .ico{width:28px;height:28px;border-radius:50%;display:grid;place-items:center;font-size:13px;font-weight:700;background:var(--mute-soft);color:var(--mute)}
.step.approved .ico,.step.done .ico{background:var(--good);color:#fff}
.step.skipped .ico{background:var(--mute-soft);color:var(--mute)}
.step.rejected .ico{background:var(--bad);color:#fff}
.step.current .ico{background:var(--warn);color:#fff;box-shadow:0 0 0 4px var(--warn-soft)}
.step .st-t{font-weight:600}
.step .st-m{font-size:12.5px;color:var(--ink-3)}
.step .st-x{font-size:13px;color:var(--ink-2);margin-top:2px;white-space:pre-wrap;word-break:break-word}
.tag{display:inline-block;font-size:10.5px;font-weight:600;padding:1px 7px;border-radius:999px;background:var(--warn-soft);color:var(--warn);margin-left:6px;vertical-align:1px}

/* inbox / my requests */
.cards{display:grid;gap:10px}
.card{padding:14px 16px;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px 16px;align-items:center}
.card .c-name{font-weight:600;word-break:break-word}
.card .c-sub{color:var(--ink-2);font-size:13px;display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:2px}
.card .c-amt{font-family:var(--mono);font-variant-numeric:tabular-nums;font-weight:500;font-size:16px;text-align:right}
.card .c-act{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end}
.sect-h{margin:18px 0 8px;font-size:14px;font-weight:600;display:flex;gap:10px;align-items:baseline;flex-wrap:wrap}
.sect-h small{font-weight:400;color:var(--ink-3)}
.dot-t{display:inline-block;width:9px;height:9px;border-radius:3px;margin-right:6px}

/* admin */
.tbl{width:100%;border-collapse:collapse}
.tbl th{font-size:11.5px;color:var(--ink-3);letter-spacing:.03em;text-align:left;padding:8px 12px;background:var(--surface-2);font-weight:500}
.tbl td{padding:10px 12px;border-top:1px solid var(--line);vertical-align:top}
.tbl tr.off td{opacity:.55}
.tbl-wrap{overflow-x:auto;padding:0}
.scope-row{display:grid;grid-template-columns:1fr 1fr auto;gap:8px;align-items:center}
.scope-list{display:grid;gap:8px}
.chk{display:flex;gap:8px;align-items:center}
.chk input{width:18px;height:18px}
.secret{font-family:var(--mono);font-size:20px;letter-spacing:.06em;background:var(--surface-2);border:1px dashed var(--line);border-radius:10px;padding:12px 14px;user-select:all;word-break:break-all}
.help{font-size:12.5px;color:var(--ink-3)}
.loading{padding:40px;text-align:center;color:var(--ink-3)}
@media (max-width:640px){
  .card{grid-template-columns:minmax(0,1fr)}
  .card .c-amt{text-align:left}
  .card .c-act{justify-content:flex-start}
  .scope-row{grid-template-columns:1fr}
}

/* ===== dashboard / register / timeline ===== */
.pad{padding:18px 20px}
.kpis{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-bottom:18px}
.kpi{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:14px 16px;box-shadow:var(--shadow);display:grid;gap:2px;align-content:start}
.kpi .k{font-size:12px;color:var(--ink-3);letter-spacing:.03em}
.kpi .v{font-size:22px;font-weight:500;line-height:1.25;word-break:break-word}
.kpi .s{font-size:12px;color:var(--ink-2)}
.kpi.main{background:var(--brand);border-color:transparent;color:var(--brand-ink)}
.kpi.main .k,.kpi.main .s{color:inherit;opacity:.8}
.grid2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr);gap:18px;margin-bottom:18px}
.grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}
.donut{display:flex;align-items:center;gap:22px;flex-wrap:wrap}
.dlegend{display:grid;gap:7px;min-width:170px;flex:1}
.dl{display:grid;grid-template-columns:12px 1fr auto;gap:9px;align-items:center}
.dl i{width:11px;height:11px;border-radius:3px;display:block}
.bars{display:grid;gap:10px}
.bar-row{display:grid;grid-template-columns:minmax(110px,1.1fr) minmax(0,2fr) auto;gap:12px;align-items:center}
.bar-row .bn{color:var(--ink-2);word-break:break-word}
.bar-row .bt{height:12px;border-radius:6px;background:var(--surface-2);overflow:hidden}
.bar-row .bt i{display:block;height:100%;background:var(--brand);border-radius:6px}
/* ภาพรวม (Overview): "ค่าใช้จ่ายที่ใช้ไป" 2-colour split bar (static/overview.js's cmpBarRowSplit()) -- two <i>
   segments side by side with a thin gap between them, same 2px-gap convention the budget bar above already uses. */
.bar-row .bt.split{display:flex;gap:2px}
.bar-row .bt.split i{border-radius:4px;flex:none;min-width:2px}
.bar-row .bv{font-size:13px;min-width:88px;text-align:right}
.kv2{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:10px}
.kv2 .k{font-size:11.5px;color:var(--ink-3)}
.kv2 .v{font-size:22px;font-weight:500}
.chips{display:flex;flex-wrap:wrap;gap:6px}
.chipbtn{border:1px solid var(--line);background:var(--surface-2);border-radius:8px;padding:3px 9px;font-size:12px;font-family:var(--mono);color:var(--ink-2)}
.chipbtn:hover{background:var(--surface);color:var(--ink)}
.revchart{width:100%;height:auto;display:block}
.ov-monthly-chart{width:100%;height:auto;display:block}
.seasons{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:4px;margin-top:10px}
.sn{border-radius:8px;padding:5px 2px;text-align:center;font-size:11px;background:var(--surface-2);color:var(--ink-3);display:grid;line-height:1.3}
.sn b{font-weight:600}
.prio{display:inline-flex;align-items:center;gap:6px;font-size:13px}
.prio i{width:9px;height:9px;border-radius:50%;display:inline-block}
.tag.co{background:var(--info-soft);color:var(--info)}

/* register table — the row itself needs more width than the page usually has to give it (fixed-width columns
   plus a roomy name column), so it scrolls horizontally inside .reg-scroll instead of getting silently clipped */
.reg-scroll{overflow-x:auto;max-width:100%}
.reg-scroll .group{overflow:visible;min-width:1156px}
.rlh,.rrow{display:grid;column-gap:12px;align-items:center;padding:11px 16px;min-width:1118px;
  grid-template-columns:140px minmax(200px,2.4fr) 120px 150px 100px 106px 106px 80px}
/* "picking" (not "sel") on purpose — .sel is already the generic <select> look used elsewhere on this page
   (see the year/department dropdowns above), and reusing it here forced every checkbox-mode row down to a
   single-line select's height, squashing the multi-line name/description text into the row above and below it */
.rlh.picking,.rrow.picking{min-width:1156px;grid-template-columns:26px 140px minmax(200px,2.4fr) 120px 150px 100px 106px 106px 80px}
.rlh{font-size:11.5px;color:var(--ink-3);letter-spacing:.03em;padding-block:8px;background:var(--surface-2);border-radius:12px;margin-bottom:10px}
.rrow .ck{cursor:pointer}
.rrow{cursor:pointer}
.rrow+.rrow{border-top:1px solid var(--line)}
.rrow:hover{background:color-mix(in srgb,var(--surface-2) 55%,transparent)}
.rrow.cancelled{opacity:.6}
.rcode{font-size:11.5px;color:var(--ink-2);white-space:nowrap}
.rdates small{display:block;color:var(--ink-3)}
.rrow .r-name small{display:block}

/* timeline */
.tl-scroll{overflow-x:auto}
.gantt{min-width:900px}
.tl-row{display:grid;grid-template-columns:230px minmax(0,1fr);align-items:stretch;cursor:pointer}
.tl-row+.tl-row{border-top:1px solid var(--line)}
.tl-row:hover:not(.tl-head){background:color-mix(in srgb,var(--surface-2) 55%,transparent)}
.tl-head{cursor:default;position:sticky;top:0;background:var(--surface);z-index:2}
.tl-scroll.cap{max-height:440px;overflow-y:auto}
.tl-today{position:absolute;top:0;bottom:0;width:2px;margin-left:-1px;background:var(--bad);opacity:.55;pointer-events:none;z-index:1}
.tl-bar{z-index:0}
.tl-label{padding:9px 10px 9px 2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:13px}
.tl-label .mono{color:var(--ink-3);font-size:11.5px}
.tl-track{position:relative;min-height:38px;
  background-image:repeating-linear-gradient(to right,transparent 0,transparent calc(100%/12 - 1px),var(--line) calc(100%/12 - 1px),var(--line) calc(100%/12))}
.tl-track.months{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));background:none;min-height:0;gap:2px}
.tl-m{text-align:center;padding:5px 0;font-size:12px;border-radius:6px;background:var(--surface-2);color:var(--ink-2);display:grid;line-height:1.25}
.tl-m small{font-size:10px}
.tl-bar{position:absolute;top:8px;height:22px;border-radius:6px;background:var(--capex);color:var(--on-capex);font-size:11px;overflow:hidden;white-space:nowrap;padding:3px 7px;font-family:var(--mono)}
/* bars are coloured by hotel (h0-h5, cycling — see hotelColorVar() in dash.js) so several hotels on one timeline
   are easy to tell apart at a glance; "done"/"cancel" still win over the hotel colour since those states matter more */
.tl-bar.h0{background:var(--h1)} .tl-bar.h1{background:var(--h2)} .tl-bar.h2{background:var(--h3)}
.tl-bar.h3{background:var(--h4)} .tl-bar.h4{background:var(--h5)} .tl-bar.h5{background:var(--h6)}
.tl-bar.done{background:var(--good)}
.tl-bar.cancel{background:var(--mute)}
/* Kang, 2026-10-01 (2nd round): "แบบจางๆ หมายถึงยังไม่อนุมัติ และเข้ม ที่อนุมัติแล้ว" -- plain opacity fade instead
   of a hatch texture, so the department colour itself reads as pale (not yet approved) vs full/dark (approved). */
.tl-bar.tentative{opacity:.42}
/* Kang, 2026-10-06 (3rd round): "โปรเจ็คที่ยังไม่ได้รับอนุมัติครั้งสุดท้าย ให้เป็นเส้นประ" -- a Project row with at
   least one expense still mid-approval-chain gets a dashed outline on top of its solid category-coloured fill,
   deliberately distinct from .tentative's pale/opacity treatment above (which only ever applies to Capex rows) --
   var(--on-capex) is the same contrast-safe token the bar's own text already uses, so the dashes stay visible
   against every category colour/theme without a colour rule of their own. */
.tl-bar.pending-exp{border:2px dashed var(--on-capex)}
.undated{margin-top:12px;display:flex;flex-wrap:wrap;gap:6px;align-items:center;font-size:13px}
.tlbox .ph{margin-bottom:10px}

/* ภาพรวม (Overview): the combined Capex + Projects timeline -- Kang, 2026-10-06: "ให้ Capex อยู่บนสุด และโปรเจ็ค
   โดยจับคู่แยกตามหมวด" -- rows are now grouped by หมวด (category) instead of แผนก (department), with the bar
   itself coloured by category (static/overview.js's catColorVar(), reusing the same .tl-bar.h0..h5 rules above
   that dash.js's own hotel-coloured timeline uses — no new colour rule needed here, and the existing
   .tl-bar.done/.tl-bar.cancel/.tl-bar.tentative rules above still win the same way they already do for that
   timeline). Within each category group, every Capex row is listed before any Project row (still each sorted by
   its own date). A category's own subtotal row (.tl-group-head) separates each group: no bar, just a label and a
   right-aligned total where the month grid would otherwise sit. Class names were ".tl-dept-head"/".tl-dept-total"
   back when the grouping axis was department; renamed here since that's no longer what they group by.
   Kang, 2026-10-06 (4th round): "ให้จับเข้ากลุ่มแผนก โดยด้านในเป็น หมวด" -- now nested two levels: แผนก
   (department) re-added as the OUTER group (reusing the ".tl-dept-head" name, now legitimately department-level
   again), หมวด (category, .tl-group-head below) as the INNER group within it. Both levels get their own
   "{ยอดเต็ม} / {ยอดคงเหลือ}" subtotal row; the category header and every item row underneath it get an extra
   left-indent (.tl-label.indent) so the two levels read as nested, not two flat lists back to back. */
.tl-row.tl-dept-head{cursor:default;background:color-mix(in srgb,var(--surface-2) 70%,transparent);font-weight:600}
.tl-dept-head .tl-label{display:flex;align-items:center;gap:6px}
.tl-dept-head .tl-track{background:none;display:flex;align-items:center;justify-content:flex-end;padding-right:10px}
.tl-row.tl-group-head{cursor:default;background:color-mix(in srgb,var(--surface-2) 45%,transparent)}
.tl-group-head .tl-label{display:flex;align-items:center;gap:6px}
.tl-group-head .tl-track{background:none;display:flex;align-items:center;justify-content:flex-end;padding-right:10px}
.tl-label.indent{padding-left:20px}
.tl-group-total{font-weight:600;color:var(--ink-2);font-size:12.5px}
/* Kang, 2026-10-06 (3rd round): "เพิ่มยอดเต็มไว้ข้างหน้า และ / ด้วยยอดคงเหลือ" -- .tl-group-total now holds two
   figures ("{ยอดเต็ม} / {ยอดคงเหลือ}"), so only the remaining-half <span> (overview.js's own .bad, not the whole
   row) turns red when it's gone negative -- was `.tl-group-total.bad` when the whole thing was one figure. */
.tl-group-total .bad{color:var(--bad)}
.ov-kind{display:inline-block;border-radius:5px;padding:1px 6px;margin-right:6px;font-size:10.5px;font-weight:600;color:var(--on-capex);vertical-align:1px}
.ov-cmp{display:grid;gap:18px}
.ov-cmp-group+.ov-cmp-group{padding-top:14px;border-top:1px solid var(--line)}
.ov-cmp-head{font-weight:600;margin-bottom:8px}

/* Capex budget usage -- a thin stacked bar: ในแผน Capex (เขียว, OV_INPLAN) then นอกงบประมาณ (เหลือง, OV_OFFPLAN),
   with a tick mark at the approved-budget boundary so "used vs. full" reads at a glance even once the bar itself
   overflows past it. Built for an older per-line view that no longer exists, then revived for the
   "งบประมาณตามแผนก" department/category rollup below -- Kang, 2026-10-08: "ข้างหลังแผนก ให้เป็นกราฟ แทงแนวนอน
   แสดงยอดที่อนุมัติ และ แสดงสี เวลายอดที่ใช้ไป และ ของหมวด ด้วย", then ("แล้วถ้านอก งป ละ") asking for the
   off-budget portion to show separately within the bar rather than folding silently into one colour. */
.budget-line{margin-bottom:0}
.bl-head{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;flex-wrap:wrap;margin-bottom:10px}
.bl-figs{display:flex;gap:18px;flex-wrap:wrap}
.bf-k{font-size:11px;color:var(--ink-3);display:flex;align-items:center}
.bf-k .dot{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:5px}
.bf-v{font-weight:600}
.bf-v.bad{color:var(--bad)}
.budget-bar-wrap{position:relative;padding:3px 0;flex:1;min-width:90px}
.budget-bar{height:10px;border-radius:5px;background:var(--surface-2);display:flex;gap:2px;overflow:hidden}
.budget-bar .seg{height:100%;border-radius:4px;min-width:2px}
.budget-mark{position:absolute;top:-2px;bottom:-2px;width:2px;background:var(--ink-3)}
.mtr-val{display:flex;align-items:center;gap:6px;flex:none;font-size:13px}
@media (max-width:560px){
  .bl-head{flex-direction:column}
  .bl-figs{gap:10px 16px}
}

/* ภาพรวม (Overview): "งบประมาณตามแผนก" -- per-department rollup (static/overview.js's ovDeptCategoryGroup()) --
   Kang, 2026-10-01 (2nd round): "ในรายการแผนก ให้แสดงหมวดหมูเรียงเป็นแถวลงมา" -- categories always stack one per
   row inside their department panel, never inline/side-by-side. Reuses .bf/.bf-k/.bf-v for the figures, same as
   the old per-line budget rows did. Kang, 2026-10-08: each department and category header now also carries the
   .budget-bar-wrap meter (overview.js's ovMeterParts()) right after its name, on the same line, with the
   breakdown figures (.bl-figs, ovBreakdownFigs()) stacked below -- always, not just at phone width, so the
   meter and its exact figures are never more than one line apart regardless of screen size. */
.dcg-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.dept-cat-list{display:grid;gap:10px}
.dept-cat-row{display:flex;flex-direction:column;gap:8px;padding:10px 0;border-top:1px solid var(--line)}
.dept-cat-row:first-child{border-top:none;padding-top:0}
.dcr-top{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.dcr-name{font-weight:500;flex:none}
@media (max-width:560px){
  .dcg-head,.dcr-top{flex-direction:column;align-items:stretch}
  .budget-bar-wrap{min-width:0}
}

@media (max-width:1180px){
  .reg-scroll{overflow-x:visible}
  .reg-scroll .group{min-width:0}
  .rlh{display:none}
  .rrow,.rrow.picking{grid-template-columns:repeat(2,minmax(0,1fr));row-gap:10px;padding:14px 16px;min-width:0}
  .rrow>.r-name,.rrow>.rcode,.rrow>.rsel{grid-column:1 / -1}
  .rrow>div[data-l]::before{content:attr(data-l);display:block;font-size:11px;color:var(--ink-3);letter-spacing:.03em;margin-bottom:1px}
  .rrow .r-budget{text-align:left}
}
@media (max-width:900px){
  .kpis{grid-template-columns:repeat(2,minmax(0,1fr))}
  .grid2,.grid3{grid-template-columns:minmax(0,1fr)}
}
@media (max-width:560px){
  .kpi .v{font-size:19px}
  .seasons{grid-template-columns:repeat(6,minmax(0,1fr))}
  .bar-row{grid-template-columns:minmax(0,1fr) auto}
  .bar-row .bt{grid-column:1 / -1;order:3}
}

#toast{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(20px + env(safe-area-inset-bottom,0px));display:grid;gap:8px;justify-items:center;z-index:90;max-width:calc(100% - 32px);pointer-events:none}
#toast .toast{position:static;transform:none;left:auto;bottom:auto}

/* ===== hotel Capex plan, bulk actions, bilingual UI, approvers, options ===== */
.seg.lang{padding:2px}
.seg.lang button{padding:5px 11px;font-size:12.5px}
.login-wrap{position:relative}
.login-lang{position:absolute;top:0;right:0}
.st-accent{background:var(--capex-soft);color:var(--capex)}
.notice.info{background:var(--info-soft);color:var(--info)}
.diff{font-family:var(--mono);font-size:12px;font-weight:600}
.diff.up{color:var(--bad)} .diff.down{color:var(--good)}
.tbl th.r,.tbl td.r{text-align:right}
.tbl tfoot td{font-weight:600;border-top:2px solid var(--line);background:var(--surface-2)}
.tbl.plan td{vertical-align:middle}
.tbl.appr td:nth-child(2),.tbl.appr td:nth-child(3){min-width:240px}
.tbl.appr td:nth-child(4){min-width:180px}
/* the on/off tick above each of a department's 3 step cells (Kang, 2026-09-29: 1-3 configurable approval steps) --
   smaller and more muted than a regular .chk so it reads as a toggle for the cell below it, not a form field of
   its own */
.stepchk{font-size:12px;color:var(--ink-2);margin-bottom:6px}
.stepchk input{width:15px;height:15px}
.tbl-wrap .in{min-width:120px}
.hist{margin-top:10px;border:1px solid var(--line);border-radius:10px}
.modal.wide{width:min(860px,100%)}
.kpis.k5{grid-template-columns:repeat(5,minmax(0,1fr))}
.in.sm{height:32px;font-size:13px}

.bulkbar{display:flex;flex-wrap:wrap;gap:10px 16px;align-items:center;justify-content:space-between;padding:10px 14px;margin-bottom:10px;position:sticky;top:8px;z-index:5}
.bulkbar .count{margin-right:auto}
.ck{width:18px;height:18px;accent-color:var(--brand)}
.card.hasck{grid-template-columns:auto minmax(0,1fr) auto}
.card.hasck .c-act{grid-column:1 / -1}
.ckwrap{display:flex;align-items:flex-start;padding-top:2px}
.faillist{margin:8px 0 0;padding-left:18px;display:grid;gap:6px}
.apprline{margin-top:-4px}

.scopebox{display:grid;gap:16px}
.pick{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:6px 12px;margin:6px 0;padding:10px;border:1px solid var(--line);border-radius:10px;max-height:190px;overflow:auto}
.pick .chk.off{opacity:.6}

/* Click-to-pick 1-N score buttons (evaluation.js scoreModal) -- replaces a plain number input per question. */
.score-pick{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.score-btn{
  width:40px;height:40px;border-radius:9px;border:1.5px solid var(--line);background:var(--surface);
  color:var(--ink-2);font-size:15px;font-weight:700;cursor:pointer;transition:.12s;
}
.score-btn:hover{border-color:var(--brand);color:var(--brand)}
.score-btn.sel{background:var(--brand);border-color:var(--brand);color:var(--brand-ink)}
.score-btn:disabled{cursor:not-allowed;opacity:.6}
.score-btn:disabled:hover{border-color:var(--line);color:var(--ink-2)}
.score-btn.sel:disabled{opacity:.85}
.score-scalehint{display:flex;justify-content:space-between;font-size:11.5px;color:var(--ink-3);max-width:280px;margin-top:4px}
/* a choice-type question's buttons carry a custom label (e.g. "ดีเยี่ยม") instead of a bare number, so they can't
   stay fixed 40x40 squares -- width follows content, same visual family otherwise. */
.score-btn.score-btn-choice{width:auto;min-width:64px;height:auto;min-height:40px;padding:8px 14px;border-radius:10px;white-space:normal;line-height:1.3;text-align:center}

/* Template builder's question list (evaluation.js templateModal) -- one card per question, closer to the familiar
   Google Forms layout Kang asked for (2026-10-08: "การสร้างแบบประเมิน ทำให้เหมือน google ฟอร์ม ได้ไหม"): a titled
   card per question with its own answer-type dropdown, rather than a flat list of fields. */
.eval-qcard{border:1px solid var(--line);border-radius:12px;padding:12px 14px;margin-top:10px;background:var(--surface)}
.eval-qcard-h{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid var(--line)}
.eval-choices{display:grid;gap:4px;width:100%}
.eval-choice-row{align-items:flex-end;padding:6px 8px;border:1px solid var(--line);border-radius:8px;background:var(--bg)}
/* Section header for a run of questions sharing one category (groupByCategory() in evaluation.js) -- shown
   above both the question-builder cards and the scoring screen's rows for that same category, e.g. the
   reference form's "สมรรถนะด้านการบริหาร (Managerial Competencies)" (Kang, 2026-10-08). */
.eval-qcat-h{margin-top:16px;padding:6px 10px;font-weight:700;font-size:13.5px;color:var(--ink-2);background:var(--bg);border-left:3px solid var(--brand);border-radius:0 8px 8px 0}
.eval-qcat-h:first-child{margin-top:4px}
/* Template builder's category container (evaluation.js templateModal, categoryBlock()) -- a category is its own
   named container holding sub-questions inside it, not a field repeated on every question card. Kang, 2026-10-08:
   "หมวดหมู่คำถาม คือ หัวข้อคำถาม ไม่ใช้คำถาม ดังนั้น หมวดหมู่คือ หมวดคำถาม และจะมีคำถามย่อยข้างใน". A heavier border
   than the plain .eval-qcard sub-question cards nested inside it, so the container reads as one level up. */
.eval-catblock{border:1.5px solid var(--brand);border-radius:14px;padding:12px 14px;margin-top:16px;background:var(--bg)}
.eval-catblock:first-child{margin-top:4px}
.eval-catblock-h{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}
.eval-catblock .eval-qcard{background:var(--surface)}
.mailbox{display:flex;flex-wrap:wrap;gap:10px 16px;align-items:center;justify-content:space-between}
.appr-cell .chips{margin-bottom:6px}
.achip{display:inline-flex;align-items:center;gap:6px;padding:3px 4px 3px 10px;border-radius:999px;background:var(--brand);color:var(--brand-ink);font-size:12.5px}
.achip button{border:0;background:rgba(255,255,255,.22);color:inherit;border-radius:50%;width:18px;height:18px;line-height:1;font-size:10px;padding:0}
.achip.dflt{background:var(--surface-2);color:var(--ink-2);padding:3px 10px;border:1px dashed var(--line)}
.warnline{color:var(--bad);font-size:12.5px}

.mrow{display:grid;gap:10px;align-items:center;padding:10px 16px;border-top:1px solid var(--line)}
.mrow.m-code{grid-template-columns:90px minmax(0,1fr) minmax(0,1fr) 400px}
.mrow.m-plain{grid-template-columns:minmax(0,1fr) minmax(0,1fr) 280px}
.mrow.m-dept{grid-template-columns:minmax(0,1fr) minmax(0,1fr) 190px 280px}
.mrow.m-cat{grid-template-columns:minmax(0,1.2fr) minmax(0,1.2fr) minmax(0,1fr) 280px}
.mrow.m-acat{grid-template-columns:minmax(0,1.1fr) minmax(0,1.1fr) minmax(0,0.9fr) minmax(0,1fr) 280px}
.mrow.m-cat-it{grid-template-columns:minmax(0,1.1fr) minmax(0,1.1fr) minmax(0,0.8fr) 130px minmax(0,1fr) 280px}
/* Kang, 2026-10-19: ticket_categories' own row -- same shape as m-cat but with one extra fixed-width cell for the
   "PM" checkbox (see admin.js's adminMaster()). */
.mrow.m-tcat{grid-template-columns:minmax(0,1.2fr) minmax(0,1.2fr) minmax(0,1fr) 110px 280px}
.mrow.m-opt{grid-template-columns:minmax(0,1fr) minmax(0,1fr) 120px 150px 280px}
.mrow.m-opt .pill{justify-self:start;max-width:100%;overflow:hidden;text-overflow:ellipsis}

@media (max-width:1040px){
  .kpis.k5{grid-template-columns:repeat(3,minmax(0,1fr))}
  .mrow.m-code,.mrow.m-plain,.mrow.m-dept,.mrow.m-cat,.mrow.m-acat,.mrow.m-cat-it,.mrow.m-tcat,.mrow.m-opt{grid-template-columns:minmax(0,1fr)}
}
@media (max-width:640px){
  .card.hasck{grid-template-columns:auto minmax(0,1fr)}
  .card.hasck .c-amt{grid-column:2}
  .kpis.k5{grid-template-columns:repeat(2,minmax(0,1fr))}
  .bulkbar{position:static}
  .login-lang{position:static;justify-self:end;margin-bottom:8px}
  .login-wrap{display:block}
  .login{margin-inline:auto}
}

.hlist{margin-top:10px;display:grid}
.hitem{padding:8px 0;border-top:1px solid var(--line)}
.hitem .hh{display:flex;flex-wrap:wrap;gap:2px 10px;align-items:baseline}
.hitem .hm{font-size:12px;color:var(--ink-3)}
.hitem .hx{font-size:13px;color:var(--ink-2)}
.hitem .hr{font-size:13px;color:var(--ink-2);white-space:pre-wrap;word-break:break-word}
.tbl td.mono{white-space:nowrap}
.app>*,#view{min-width:0}
.tbl-wrap{max-width:100%}

.actwrap{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end;min-width:120px;max-width:250px;margin-left:auto}
@media (max-width:720px){
  .tbl.stack thead{display:none}
  .tbl.stack,.tbl.stack tbody{display:block;width:100%}
  .tbl.stack tr{display:block;padding:10px 12px;border-top:1px solid var(--line)}
  .tbl.stack td{display:flex;justify-content:space-between;align-items:baseline;gap:14px;border:0;padding:3px 0;text-align:right;white-space:normal}
  .tbl.stack td[data-l]::before{content:attr(data-l);color:var(--ink-3);font-size:12px;text-align:left;flex:none}
  .tbl.stack td.mono{white-space:normal;word-break:break-all}
  .tbl.stack td.acts,.tbl.stack td:last-child:not([data-l]){justify-content:flex-end}
  .tbl.stack td:first-child:not([data-l]){justify-content:flex-start}
  .actwrap{max-width:none;min-width:0}
}

/* ---------- space switcher, hotel logos, start page ---------- */
.spaces{display:flex;flex-wrap:wrap;gap:6px}
.space-btn{border:1px solid var(--line);background:var(--surface);color:var(--ink-2);padding:7px 16px;border-radius:999px;font-weight:500}
.space-btn:hover{color:var(--ink);background:var(--surface-2)}
.space-btn[aria-current="page"]{background:var(--brand);color:var(--brand-ink);border-color:transparent}
.hbadge{display:inline-flex;align-items:center;gap:6px;vertical-align:middle}
.hlogo{width:18px;height:18px;border-radius:4px;object-fit:contain;background:#fff;border:1px solid var(--line);flex:none}
.hlogo.noimg{display:inline-grid;place-items:center;font-size:10px;font-weight:700;color:var(--ink-3);background:var(--surface-2)}
.hbadge.lg .hlogo{width:34px;height:34px;border-radius:8px}
.hbadge.lg{gap:10px;font-weight:500;font-size:15px}
.hbadge.only .hlogo{width:44px;height:44px;border-radius:9px;font-size:14px}
.sig-preview{padding:10px;border:1px dashed var(--line);border-radius:10px;display:grid;place-items:center;min-height:64px;background:var(--surface-2)}
.sig-preview img{max-width:220px;max-height:80px;object-fit:contain}
.mrow.m-hotel{grid-template-columns:52px 90px minmax(0,1fr) minmax(0,1fr) 470px}
@media (max-width:1040px){.mrow.m-hotel{grid-template-columns:minmax(0,1fr)}}

.hub-hero{margin-bottom:4px;display:flex;flex-wrap:wrap;gap:12px;align-items:flex-start;justify-content:space-between;
  padding:20px 24px;border-radius:18px;background:var(--hero);color:#fff;box-shadow:var(--shadow)}
.hub-hero h2{margin:0;font-size:22px;color:#fff}
.hub-hero p{margin:4px 0 0;color:#fff;opacity:.94;max-width:640px;white-space:pre-line}
.hub-hero .btn{background:rgba(255,255,255,.14);color:#fff;border-color:rgba(255,255,255,.45)}
.hub-hero .btn:hover{background:rgba(255,255,255,.26)}
.hub-hero-img{width:200px;max-width:40%;aspect-ratio:16/10;object-fit:cover;border-radius:12px;flex-shrink:0;box-shadow:0 4px 14px rgba(0,0,0,.18)}
.hub-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:18px}
.hub-card{background:var(--surface);border:1px solid var(--line);border-radius:18px;box-shadow:var(--shadow);overflow:hidden;display:grid;grid-template-rows:auto 1fr;cursor:pointer;transition:transform .15s,box-shadow .15s}
.hub-card:hover{transform:translateY(-2px);box-shadow:0 8px 26px rgba(19,35,43,.14)}
.hub-img{width:100%;aspect-ratio:16/6;object-fit:cover;display:block;background:var(--surface-2)}
.hub-img.noimg{display:grid;place-items:center;font-size:64px;font-weight:700;color:#fff;background:var(--tile-a)}
.hub-img.noimg.projects{background:var(--tile-b)}
.hub-img.noimg.tickets{background:var(--tile-c);font-size:40px}
.hub-img.noimg.admin{background:var(--tile-d);font-size:40px}
.hub-img.noimg.assets{background:var(--tile-b);font-size:40px}
.admin-ph{display:grid;place-items:center}
.admin-ph svg{width:44px;height:44px;stroke:rgba(255,255,255,.9);stroke-width:1.4;fill:none}
.gantt-ph{display:grid;gap:9px;width:56%}
.gantt-ph i{display:block;height:12px;border-radius:6px;background:rgba(255,255,255,.85)}
.gantt-ph i:nth-child(1){width:60%}.gantt-ph i:nth-child(2){width:80%;margin-left:20%}.gantt-ph i:nth-child(3){width:50%;margin-left:45%}
.ticket-ph{display:grid;place-items:center}
.ticket-ph svg{width:46px;height:46px;stroke:rgba(255,255,255,.9);stroke-width:1.6;fill:none}
.hub-body{padding:16px 20px 18px;display:grid;gap:8px;align-content:start}
.hub-body h3{margin:0;font-size:19px}
.hub-body p{margin:0;color:var(--ink-2);white-space:pre-line}
.hub-badges{display:flex;flex-wrap:wrap;gap:6px;min-height:6px}
.hub-badge{font-size:12px;font-weight:600;padding:2px 10px;border-radius:999px;background:var(--surface-2);color:var(--ink-2)}
.hub-badge.warn{background:var(--warn-soft);color:var(--warn)}
.hub-badge.bad{background:var(--bad-soft);color:var(--bad)}
.hub-go{margin-top:4px}
.hub-edit{padding:14px 16px;margin-bottom:12px;display:grid;gap:12px}
.hub-edit h3{margin:0;font-size:14px}
.hub-edit-img{display:grid;gap:8px;justify-items:start}
.hub-edit-img img{max-width:320px;width:100%;aspect-ratio:16/7;object-fit:cover;border-radius:10px;border:1px solid var(--line)}
.hub-edit-img .noimg{width:320px;max-width:100%;aspect-ratio:16/7;display:grid;place-items:center;border-radius:10px;border:1px dashed var(--line);color:var(--ink-3);font-size:12.5px;text-align:center}
.order-list{display:grid;gap:6px;max-width:420px}
.order-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 12px;background:var(--surface-2);border-radius:10px}
.order-name{font-weight:600;font-size:13.5px}
.order-row .btn.sm{width:32px;padding:0}
textarea.in{height:auto;padding:9px 11px;min-height:72px;resize:vertical}
@media (max-width:760px){.hub-cards{grid-template-columns:minmax(0,1fr)}}

/* ---------- Capex documents / quotations ---------- */
.tag.doc{background:var(--info-soft);color:var(--info)}
.tag.ok{background:var(--good-soft);color:var(--good)}
.tag.warnt,.warnt{color:var(--warn)}
.tag.warnt{background:var(--warn-soft)}
.tag.bad,.badt{color:var(--bad)}
.tag.bad{background:var(--bad-soft)}
.tag.lv{margin-left:0}
.tag.lv.view{background:var(--mute-soft);color:var(--mute)}
.tag.lv.edit{background:var(--info-soft);color:var(--info)}
.tag.lv.manage{background:var(--good-soft);color:var(--good)}
.quotes{display:grid;gap:8px}
.quote{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;padding:10px 12px;border:1px solid var(--line);border-radius:10px}
.quote.chosen{border-color:var(--good);background:color-mix(in srgb,var(--good-soft) 55%,transparent)}
.q-v{display:flex;flex-wrap:wrap;gap:4px 0;align-items:center}
.q-m{display:flex;flex-wrap:wrap;gap:2px 12px;font-size:12.5px;color:var(--ink-2)}
.q-m a{color:var(--info);word-break:break-all}
.q-amt{font-size:16px;font-weight:600;text-align:right}
.q-act{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:6px}
.docrow{justify-content:flex-start;flex-wrap:wrap}
.docrow .fn small{white-space:normal}
.docrow .fn{flex:1;display:grid;min-width:0}
.docrow select{flex:none;width:auto;max-width:170px}

/* ---------- projects ---------- */
.pbar{height:8px;border-radius:999px;background:var(--surface-2);overflow:hidden;flex:1}
.pbar i{display:block;height:100%;background:var(--capex);border-radius:999px}
.pbar.good i{background:var(--good)}
.pgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(310px,1fr));gap:14px}
.pcard{padding:16px 18px;display:grid;gap:8px;cursor:pointer;align-content:start}
.pcard:hover{box-shadow:0 6px 22px rgba(19,35,43,.12)}
.pcard h3{margin:0;font-size:16.5px;word-break:break-word}
.pc-h{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.pc-h .mono{font-size:12px;color:var(--ink-3)}
.pc-sub{display:flex;flex-wrap:wrap;gap:4px 12px;color:var(--ink-2);font-size:13px}
.pc-prog{display:flex;align-items:center;gap:10px}
.pc-meta{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:12.5px;color:var(--ink-2)}
.pc-ms{font-size:12.5px;color:var(--ink-2)}
.late{color:var(--bad)!important}
.mytasks{padding:4px 0}
.mt-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:12px;align-items:center;padding:9px 16px;cursor:pointer}
.mt-row+.mt-row{border-top:1px solid var(--line)}
.mt-row:hover{background:var(--surface-2)}
.mt-due{font-size:12.5px;color:var(--ink-2);white-space:nowrap}
.proj-head{padding:16px 20px;display:grid;gap:8px}
.proj-head h2{margin:0;font-size:22px;word-break:break-word}
.ph-top{display:flex;flex-wrap:wrap;gap:8px;justify-content:space-between}
.ph-meta{display:flex;flex-wrap:wrap;gap:8px 14px;align-items:center}
.ptabs{overflow-x:auto;flex-wrap:nowrap;margin-top:6px}
.ptabs button{white-space:nowrap}
.ptab{display:grid;gap:12px;margin-top:6px}
.two-col{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(0,1fr);gap:18px}
@media (max-width:820px){.two-col{grid-template-columns:minmax(0,1fr)}}
.ms-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;gap:10px;align-items:center;padding:6px 0}
.ms-row+.ms-row{border-top:1px solid var(--line)}
.ms-row.done b{text-decoration:line-through;color:var(--ink-3)}
.ms-dot{color:var(--capex);font-weight:700;width:18px;text-align:center}
.ms-due{font-size:12.5px;color:var(--ink-2);white-space:nowrap}
.cx-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;gap:10px;align-items:center;padding:8px 0;cursor:pointer}
.cx-row+.cx-row{border-top:1px solid var(--line)}
.cx-row:hover{background:var(--surface-2)}
.cx-pick{display:grid;gap:2px;max-height:340px;overflow:auto;border:1px solid var(--line);border-radius:10px;padding:4px}
.cx-opt{display:grid;grid-template-columns:auto auto minmax(0,1fr) auto;gap:10px;align-items:center;padding:6px 8px;border-radius:8px;cursor:pointer}
.cx-opt:hover{background:var(--surface-2)}
.board{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;align-items:start}
.b-col{background:var(--surface-2);border-radius:12px;padding:8px;display:grid;gap:8px;align-content:start}
.b-h{display:flex;justify-content:space-between;align-items:center;padding:4px 6px;font-weight:600;border-left:4px solid var(--c);}
.t-card{background:var(--surface);border:1px solid var(--line);border-radius:10px;padding:10px 12px;display:grid;gap:6px;cursor:pointer;box-shadow:var(--shadow)}
.t-card.late{border-color:var(--bad)}
.t-title{font-weight:600;word-break:break-word}
.t-meta{display:flex;flex-wrap:wrap;gap:4px 10px;align-items:center;font-size:12.5px}
.t-meta .who{background:var(--info-soft);color:var(--info);border-radius:999px;padding:1px 9px;font-weight:500}
.t-foot{display:flex;flex-wrap:wrap;gap:6px 10px;align-items:center}
.t-foot select{width:auto}
@media (max-width:1040px){.board{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.board{grid-template-columns:minmax(0,1fr)}}
.late-row td{background:color-mix(in srgb,var(--bad-soft) 40%,transparent)}
.range{display:flex;gap:10px;align-items:center}
.range input{flex:1;padding:0;height:24px}
.note{display:grid;gap:6px}
.note.closed{opacity:.7}
.note h3{margin:0;font-size:15px}
.n-h{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.cm{padding:8px 0}
.cm+.cm{border-top:1px solid var(--line)}
.mpick{display:grid;gap:10px}
.mp-add{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr) 150px auto;gap:8px}
.mlist{display:grid;gap:6px}
.mrow2{display:grid;grid-template-columns:minmax(0,1fr) 170px auto;gap:10px;align-items:center;padding:6px 10px;border:1px solid var(--line);border-radius:10px}
.mrow2.owner{grid-template-columns:minmax(0,1fr) auto;margin-bottom:10px;background:var(--surface-2)}
@media (max-width:700px){.mp-add{grid-template-columns:minmax(0,1fr)}.mrow2{grid-template-columns:minmax(0,1fr) auto}.mrow2 select{grid-column:1}}
.lvhelp{display:grid;gap:3px;margin-top:8px}
.picklist{display:grid;gap:2px;max-height:340px;overflow:auto;border:1px solid var(--line);border-radius:10px;padding:6px}
.picklist-row{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:8px}
.picklist-row:hover{background:var(--surface-2)}

/* project Gantt */
.pg{min-width:calc(220px + var(--w))}
.pg-row{display:grid;grid-template-columns:220px minmax(0,1fr);align-items:stretch;cursor:pointer}
.pg-row+.pg-row{border-top:1px solid var(--line)}
.pg-row:hover:not(.pg-head){background:color-mix(in srgb,var(--surface-2) 55%,transparent)}
.pg-head{cursor:default;position:sticky;top:0;background:var(--surface);z-index:3}
.pg-label{position:sticky;left:0;z-index:2;background:var(--surface);padding:9px 10px 9px 2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:13px}
.pg-label .dot{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:6px}
.pg-label small{color:var(--ink-3)}
.pg-track{position:relative;min-height:38px}
.pg-track.months{display:flex;min-height:0;align-items:center}
.pg-m{text-align:center;font-size:11.5px;color:var(--ink-2);padding:6px 0;border-left:1px solid var(--line);overflow:hidden;white-space:nowrap}
/* Kang, 2026-10-06: "ไทม์ไลน์ ในโปรเจ็ค ... weekly", then (2nd round) "รายสัปดาห์ ให้แสดงเป็นวันที่เลย" -- สัปดาห์
   mode is one narrow column per day (not per week), each labelled with its own date ("6 ต.ค."), at a smaller
   size than the month header's labels so it still fits a column this narrow on one line. .wk-start gives the
   Monday column a slightly bolder left border so the day-by-day grid still visually breaks into weeks. */
.pg-m.wk{font-size:10px;padding:6px 1px}
.pg-m.wk-start{border-left:2px solid var(--ink-3)}
.pg-bar{position:absolute;top:9px;height:20px;border-radius:6px;background:var(--mute);overflow:hidden;color:#fff;font-size:11px;padding:2px 6px;white-space:nowrap}
.pg-bar i{position:absolute;left:0;top:0;bottom:0;background:rgba(255,255,255,.28)}
.pg-bar span{position:relative}
.pg-bar.doing{background:var(--info)}.pg-bar.blocked{background:var(--bad)}.pg-bar.done{background:var(--good)}
.pg-bar.late{outline:2px solid var(--bad);outline-offset:1px}
.pg-ms{position:absolute;top:8px;width:16px;text-align:center;color:var(--capex);font-size:18px;line-height:22px}
.pg-ms.done{color:var(--good)}.pg-ms.late{color:var(--bad)}
.pg-mlabel{position:absolute;top:10px;font-size:11.5px;color:var(--ink-3);white-space:nowrap}
.pg .tl-today{z-index:1}

.btnrow select.in{width:auto;max-width:100%}
.ptab{grid-template-columns:minmax(0,1fr)}
.ptab>*,.two-col>*{min-width:0}
.tl-scroll{max-width:100%}
@media (max-width:560px){
  .pg-row{grid-template-columns:120px minmax(0,1fr)}
  .pg{min-width:calc(120px + var(--w))}
  .pg-label{font-size:12px}
  .hub-img{aspect-ratio:16/8}
  .hub-hero h2{font-size:19px}
  .hub-hero-img{display:none}
}

/* ---- admin: system and versions ---- */
.sys-now{display:flex;gap:18px;align-items:flex-start;padding:16px 18px;flex-wrap:wrap}
.sys-ver{font-size:30px;font-weight:700;color:var(--brand);line-height:1.1}
.sys-notes{margin:8px 0 0;padding-left:18px;color:var(--ink-2)}
.sys-warn{padding:14px 18px;border-color:var(--warn);background:var(--warn-soft)}
.sys-warn p{margin:6px 0 10px}
.sys-code{margin:0;padding:10px 12px;border-radius:8px;background:var(--surface);border:1px solid var(--line);font-family:var(--mono);font-size:13px;overflow:auto}
.sys-stage{margin-top:12px;padding:14px 18px;display:grid;gap:8px}
.sys-arrow{display:flex;flex-wrap:wrap;gap:8px;align-items:center;font-size:18px}
.sys-counts{display:flex;flex-wrap:wrap;gap:6px}
.sys-files summary{cursor:pointer;color:var(--ink-2)}
.sys-files ul{margin:6px 0 0;padding-left:18px;max-height:180px;overflow:auto;font-size:12px}
.sys-note-warn{padding:8px 10px;border-radius:8px;background:var(--warn-soft);color:var(--warn)}
.sys-list{display:grid}
.sys-danger{border-color:var(--bad)}
.sys-row{display:flex;gap:12px;align-items:center;justify-content:space-between;padding:10px 16px;border-bottom:1px solid var(--line);flex-wrap:wrap}
.sys-row:last-child{border-bottom:0}
.sys-row .help{margin-top:2px}
.sys-wait{position:fixed;inset:0;z-index:1000;background:var(--overlay);display:grid;place-content:center;justify-items:center;gap:10px;text-align:center;padding:24px;color:#fff}
.sys-wait h2,.sys-wait p{margin:0;color:#fff}
.sys-wait .help{color:#dbe6f3}
.sys-spin{width:38px;height:38px;border-radius:50%;border:4px solid rgba(255,255,255,.3);border-top-color:#fff;animation:sysspin 1s linear infinite}
@keyframes sysspin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.sys-spin{animation:none}}

/* theme picker (Admin > Home and settings) */
.theme-opts{display:flex;flex-wrap:wrap;gap:12px;padding:14px 16px}
.theme-opt{display:grid;gap:8px;justify-items:start;padding:10px 12px;border:2px solid var(--line);border-radius:12px;background:var(--surface);min-width:170px;text-align:left}
.theme-opt[aria-checked="true"]{border-color:var(--brand);box-shadow:0 0 0 3px var(--info-soft)}
.theme-opt .sw{display:flex;width:100%;height:34px;border-radius:8px;overflow:hidden;border:1px solid rgba(0,0,0,.08)}
.theme-opt .sw i{flex:1}
.theme-opt .sw.blue i:nth-child(1){background:#12408f}.theme-opt .sw.blue i:nth-child(2){background:#1d5fc0}.theme-opt .sw.blue i:nth-child(3){background:#3d8be8}.theme-opt .sw.blue i:nth-child(4){background:#dbe7fa}
.theme-opt .sw.sky i:nth-child(1){background:#08639f}.theme-opt .sw.sky i:nth-child(2){background:#0b7cc0}.theme-opt .sw.sky i:nth-child(3){background:#38a9e8}.theme-opt .sw.sky i:nth-child(4){background:#d3ebf8}
.theme-opt .sw.green i:nth-child(1){background:#0d5c37}.theme-opt .sw.green i:nth-child(2){background:#127a4a}.theme-opt .sw.green i:nth-child(3){background:#2fa86e}.theme-opt .sw.green i:nth-child(4){background:#d6f0e0}
.theme-opt .sw.orange i:nth-child(1){background:#9a4407}.theme-opt .sw.orange i:nth-child(2){background:#c2620f}.theme-opt .sw.orange i:nth-child(3){background:#e89a3d}.theme-opt .sw.orange i:nth-child(4){background:#fbe4cb}
.theme-opt .sw.yellow i:nth-child(1){background:#7a6008}.theme-opt .sw.yellow i:nth-child(2){background:#b3900d}.theme-opt .sw.yellow i:nth-child(3){background:#dfbb3a}.theme-opt .sw.yellow i:nth-child(4){background:#f6ecc0}
/* Kang, 2026-09-29: "หลายๆ สีผสมกัน" -- these 3 swatches show two distinct hues blending (not 4 shades of one) */
.theme-opt .sw.sunset i:nth-child(1){background:#9a3412}.theme-opt .sw.sunset i:nth-child(2){background:#e0672c}.theme-opt .sw.sunset i:nth-child(3){background:#7c3aed}.theme-opt .sw.sunset i:nth-child(4){background:#e3d4fa}
.theme-opt .sw.ocean i:nth-child(1){background:#0c3a4d}.theme-opt .sw.ocean i:nth-child(2){background:#0f7a6b}.theme-opt .sw.ocean i:nth-child(3){background:#3730a3}.theme-opt .sw.ocean i:nth-child(4){background:#d7d4f5}
.theme-opt .sw.berry i:nth-child(1){background:#701a4d}.theme-opt .sw.berry i:nth-child(2){background:#c2368c}.theme-opt .sw.berry i:nth-child(3){background:#5b21b6}.theme-opt .sw.berry i:nth-child(4){background:#e6d7f7}

/* admin: Excel import */
.imp-panel{padding:14px 18px;display:grid;gap:10px}
.imp-kpis{display:flex;flex-wrap:wrap;gap:12px}
.imp-k{display:grid;gap:2px;min-width:170px;padding:10px 14px;border:1px solid var(--line);border-radius:12px;background:var(--surface-2)}
.imp-k b{font-size:18px}
.imp-chips{display:flex;flex-wrap:wrap;gap:6px}
.imp-table{max-height:420px;overflow:auto;border:1px solid var(--line);border-radius:10px}
.imp-table .tbl th{position:sticky;top:0}

/* printable documents (approval sheet / hotel Capex plan) — browser print only, no PDF library.
   #print-area stays out of the normal page and is shown, alone, only for the print media. */
#print-area{display:none}
.p-head{margin-bottom:14px}
.p-head h1{margin:0 0 2px;font-size:20px}
.p-sub{color:var(--ink-2);font-size:14px}
.p-meta{color:var(--ink-3);font-size:11.5px;margin-top:2px}
.p-kvgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 24px;margin-bottom:16px;padding:12px 14px;border:1px solid var(--line);border-radius:10px}
.p-kv{display:flex;justify-content:space-between;gap:10px;font-size:13px;border-bottom:1px dotted var(--line);padding:3px 0}
.p-k{color:var(--ink-3)}
.p-v{font-weight:600;text-align:right}
/* table-layout stays auto (not fixed) so short columns (a month, a percentage) don't force-widen to match a
   long one -- but a long name/position with no spaces to break on could still push the table wider than the
   printed page, so every cell allows a mid-word break as a last resort rather than spilling off the page edge */
.p-tbl{width:100%;border-collapse:collapse;font-size:12.5px;margin-bottom:16px}
.p-tbl th,.p-tbl td{border:1px solid var(--line);padding:5px 8px;text-align:left;word-break:break-word;overflow-wrap:anywhere}
.p-tbl th{background:var(--surface-2)}
.p-tbl td.num,.p-tbl th.num{text-align:right}
.p-tbl tfoot td{font-weight:700;background:var(--surface-2)}
.p-sigrow{display:flex;flex-wrap:wrap;gap:14px;margin-top:10px}
.p-sig{flex:1 1 200px;min-width:180px;border:1px solid var(--line);border-radius:10px;padding:10px 12px;page-break-inside:avoid}
.p-sig-role{font-size:11.5px;color:var(--ink-3);margin-bottom:6px}
.p-sig-img{height:50px;display:flex;align-items:flex-end;margin-bottom:4px}
.p-sig-img img{max-height:50px;max-width:100%;object-fit:contain}
.p-sig-blank{display:block;width:100%;border-bottom:1px solid var(--ink-3)}
.p-sig-name{font-weight:600;font-size:13px;border-top:1px solid var(--line);padding-top:4px}
.p-sig-date{font-size:11px;color:var(--ink-3)}
.p-sig-note{font-size:11.5px;color:var(--ink-2);margin-top:2px}
/* Performance-evaluation print form (print.js's printEvalResult(), Kang, 2026-10-08, modeled on a real
   "PROBATION APPRAISAL FORM" sample he shared) -- a plain Unicode checkbox glyph (☑/☐) per cell/row, since this
   is a plain browser print page, not an interactive form. */
.p-tbl td.p-chk,.p-tbl th.p-chk{text-align:center;font-size:14px}
.p-tbl .p-idx{width:34px}
.p-tbl td.p-idx{white-space:nowrap;padding-left:4px;padding-right:4px}
/* Combined multi-department roster print (print.js's printRoster(), Kang, 2026-10-15) -- a date-grid table per
   department, same shape as the on-screen "ดูตารางงาน" roster but with every date column kept narrow and
   non-wrapping so a week/month's worth of columns still fits an A4 page (landscape by default). */
.p-tbl.p-roster th,.p-tbl.p-roster td{white-space:nowrap;padding:3px 5px;font-size:11px}
.p-tbl.p-roster td.p-roster-name{white-space:normal;font-size:12.5px}
.p-roster-sect{margin-bottom:14px}
.p-roster-sect h3{margin:0 0 4px;font-size:13px}
.p-tbl td.p-qcat{background:var(--surface-2);font-weight:700}
.p-qtext-en{color:var(--ink-3);font-size:11px;margin-top:2px}
.p-decisionrow{display:flex;flex-wrap:wrap;gap:18px;margin:8px 0 14px;font-size:13px}
.p-ratinggrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:4px 24px;margin-bottom:10px;font-size:12px}
.p-rating-row{display:flex;justify-content:space-between;gap:10px;border-bottom:1px dotted var(--line);padding:3px 0}
.p-rating-row.sel{font-weight:700;color:var(--brand)}
.p-remark{font-size:11.5px;color:var(--ink-2);margin:4px 0 14px}
/* category-template print layout only (print.js's printEvalResult(), Kang, 2026-10-08: "อันนี้ไม่ได้เปลี่ยนฟอร์ม
   เก่านะ แต่ฟอร์มนี้จะใช้กับ แบบฟอร์มที่เปิดใช้หมวดหมู่") -- matches a real "HEAD OF DEPARTMENT APPRAISAL FORM"
   sample's "overall result" grid, which lists the top 5 bands top-to-bottom in a left column and the bottom 5 in
   a right column, NOT row-interleaved like the plain .p-ratinggrid above. grid-auto-flow:column + an explicit
   5-row template fills column-major for exactly 10 bands. */
.p-ratinggrid-2col{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:repeat(5,auto);grid-auto-flow:column;gap:4px 24px;margin-bottom:10px;font-size:12px}
/* a blank hand-written remark box, separate from the Pass/Extend/Not-pass decision checkboxes -- same reference
   form has both */
.p-remarkbox{border:1px solid var(--line);border-radius:10px;padding:8px 12px;margin:0 0 14px;font-size:12px}
.p-remarkbox-label{color:var(--ink-3);margin-bottom:22px}
/* print form designer ("ออกแบบ", Kang 2026-10-08: "ลาก/วางตำแหน่งข้อมูลใหม่ได้อิสระ เหมือน Canva") -- .p-canvas is
   the shared absolutely-positioned container used both for an actual saved-layout print (plain, no outline/
   handles) and as the base of the designer's own live canvas (.p-design-mode adds the dashed outlines/handles/
   label chips below; see print.js's layoutOrFlow()/designEvalPrintLayout()) */
.p-canvas{position:relative;background:#fff}
.p-design-mode{border:1px dashed var(--line)}
.p-design-mode .p-designbox{outline:1px dashed transparent;cursor:move}
.p-design-mode .p-designbox:hover{outline-color:var(--brand)}
.p-design-handle{position:absolute;right:-7px;bottom:-7px;width:14px;height:14px;background:var(--brand);border:2px solid #fff;border-radius:4px;cursor:nwse-resize;z-index:2}
.p-design-label{position:absolute;top:-19px;left:0;font-size:11px;line-height:1.6;background:var(--brand);color:#fff;padding:1px 7px;border-radius:5px 5px 0 0;white-space:nowrap;pointer-events:none}
.p-designwrap{transform-origin:top left;display:inline-block}
.p-designscroll{overflow:auto;max-height:70vh;padding:24px 12px 12px;background:var(--bg)}
/* the training reports' printed dashboard reuses the on-screen .kpi/.bars/.donut/.revchart components as-is
   (see print.js), which were sized for a wide screen panel -- shrunk down here so a 5-card KPI row or the
   side-by-side bar/donut pair doesn't overflow a printed page (Kang, 2026-09-27: "ข้อมูลมันล้นหน้า") */
@media print{
  #app,#layer,#toast,.pwa-install-banner{display:none !important}
  #print-area{display:block !important;padding:0;color:#000;background:#fff}
  .p-sig,.p-tbl tr,.kpi,.bar-row{page-break-inside:avoid}
  .p-tbl{font-size:10.5px}
  .p-tbl th,.p-tbl td{padding:3px 5px}
  #print-area .panel.pad{padding:10px 12px;box-shadow:none;border-radius:8px}
  #print-area .kpis{gap:8px;margin-bottom:12px}
  #print-area .kpi{padding:8px 10px;box-shadow:none}
  #print-area .kpi .v{font-size:16px}
  #print-area .kpi .k,#print-area .kpi .s{font-size:9.5px}
  #print-area .grid2{gap:10px;margin-bottom:12px}
  #print-area .donut{gap:12px}
  #print-area .donut svg{width:110px;height:110px}
  #print-area .dl{font-size:11px}
  #print-area .bar-row{gap:6px}
  #print-area .bar-row .bn{font-size:11.5px}
  #print-area .revchart{max-height:150px}
}
/* the print-area's own paper size/orientation is rewritten per print run by print.js's page-setup modal, in a
   separate <style id="print-page-setup"> tag appended after this stylesheet -- this is just the fallback for
   the (normally unreachable) case that tag hasn't been created yet */
@page{size:A4 portrait;margin:12mm}
/* landscape has real width to spare, so the printed tables can afford to stay closer to their on-screen size
   instead of the cramped default above */
#print-area.p-landscape .p-tbl{font-size:11.5px}
#print-area.p-landscape .p-tbl th,#print-area.p-landscape .p-tbl td{padding:4px 7px}

/* print preview modal (print.js's previewModal) -- a live scaled-down rendering of the actual report inside a
   page-shaped frame, so paper size/orientation/shrink-% and page-break markers can be seen before the real
   print dialog opens (Kang, 2026-09-28: "ปรับขนาด ย้ายตาราง ... ให้อยู่หน้าเดียวกัน") */
.pp-toolbar{display:flex;flex-wrap:wrap;gap:14px;align-items:flex-end;margin-bottom:14px}
.pp-viewport{overflow:auto;max-height:55vh;background:var(--surface-2);border-radius:10px;padding:16px;display:flex;justify-content:center}
.pp-frame{position:relative;background:#fff;box-shadow:0 2px 10px rgba(0,0,0,.18);overflow:visible;flex:none}
.pp-page{position:absolute;top:0;left:0;transform-origin:top left;background:#fff;color:#000}
.pp-pagebreak{position:absolute;left:0;right:0;border-top:2px dashed var(--bad);pointer-events:none}
.pp-pagebreak-label{position:absolute;right:4px;top:2px;font-size:10px;color:var(--bad);background:#fff;padding:0 4px;white-space:nowrap}
.pp-warn{margin-top:10px;font-size:12.5px;color:var(--bad)}

/* ===== PWA install hint (pwa.js) ===== */
.pwa-install-banner{position:fixed;left:0;right:0;top:0;z-index:95;display:flex;align-items:center;gap:10px;
  padding:calc(10px + env(safe-area-inset-top,0px)) 14px 10px;background:var(--surface);border-bottom:1px solid var(--line);
  box-shadow:0 6px 20px rgba(0,0,0,.12)}
.pwa-install-icon{width:30px;height:30px;border-radius:8px;flex:none}
.pwa-install-text{flex:1;font-size:13px;line-height:1.4;color:var(--ink-2)}
.pwa-install-actions{display:flex;align-items:center;gap:6px;flex:none}
.pwa-install-btn{border:none;border-radius:8px;background:var(--brand);color:var(--brand-ink);font-weight:600;
  font-size:13px;padding:7px 14px;cursor:pointer}
.pwa-install-close{border:none;background:none;color:var(--ink-3);font-size:20px;line-height:1;padding:4px 6px;cursor:pointer}
@media (max-width:560px){
  .pwa-install-text{font-size:12.5px}
}

/* ===== mobile: shrink the shell chrome so real content starts sooner =====
   .tabs (the tab strip inside each system, e.g. Capex's own dashboard/register/plan/... tabs) used to wrap
   onto several short lines on a phone -- Admin alone has 9 tabs, 5 lines' worth, and even scrolled sideways
   it's still a row of small tap targets. On a narrow screen it's now replaced outright by .tab-menu, a single
   "≡ current tab" button that opens the same choices as a dropdown list (see the .tab-menu rules further
   below, next to .bottomnav which gets the same "swap the whole control" treatment). min-width:0 keeps things
   from forcing their parent flex/grid row wider than the screen. The system switcher (.spaces) is handled the
   same way, just below. */
@media (max-width:760px){
  .top,.actions{min-width:0}

  /* positioning context for .tab-menu below: it can sit anywhere in the page's markup (Capex's tab bar, Admin's,
     a project's, ...) and still land pinned to this exact top-left corner, the same way .profile-menu is pinned
     to .top's top-right corner -- position:absolute walks up to the nearest *positioned* ancestor regardless of
     how deep the element actually is in the DOM, and .app wraps the whole page (header included). */
  .app{position:relative}

  /* register/project/ticket list filter bars: let each dropdown/segment shrink and share a row instead of one
     full-width control per line (a <select> can size itself to its widest *option*, not just the picked one,
     which is why some of these were rendering almost edge-to-edge on a phone even for a short selected value) */
  .list-tools .left{width:100%}
  .list-tools .left>*{flex:1 1 150px;min-width:0}
  .list-tools .left select.sel{width:100%}
  .search{min-width:0;width:100%}
}

/* ===== mobile: bottom tab bar, in place of the top switcher =====
   .bottomnav is always in the markup (app.js); only the CSS below decides whether the bottom bar or the
   desktop top switcher shows for a given screen width, so app.js never needs to know the viewport size.
   profileMenu() (see the base rules above) is a single widget shown at every width -- only its corner-pinned
   positioning is tweaked here for a phone, right below the .tab-menu rules it mirrors (same size, same corner
   logic, opposite side). */
.bottomnav{display:none}
.tab-menu{display:none}
@media (max-width:760px){
  .spaces{display:none}

  /* .tabwrap (app.js' tabBar()/B.tabBar()) holds both the classic .tabs row and the .tab-menu dropdown; a
     phone shows only the dropdown, tucked away as a small round icon pinned to the header's top-left corner --
     hidden until tapped, opening a floating panel over the content -- mirroring .profile-menu's icon at the
     top-right corner exactly (same size, same corner logic, opposite side). */
  .tabs{display:none}
  .top.has-tabmenu{padding-left:50px}
  .tab-menu{display:block;position:absolute;top:0;left:0}
  .tab-menu-btn{
    width:38px;height:38px;border-radius:50%;background:var(--surface-2);color:var(--ink-2);
    display:flex;align-items:center;justify-content:center;border:1px solid var(--line);cursor:pointer;list-style:none;
  }
  .tab-menu-btn::-webkit-details-marker{display:none}
  .tab-menu[open] .tab-menu-btn{outline:2px solid var(--focus);outline-offset:2px}
  .tm-ico{width:18px;height:18px}
  .tab-menu-panel{
    position:absolute;top:calc(100% + 8px);left:0;z-index:40;min-width:210px;max-width:min(80vw,320px);
    background:var(--surface);border:1px solid var(--line);border-radius:12px;
    box-shadow:var(--shadow);padding:6px;display:grid;gap:2px;
  }
  .tm-item{
    display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:10px 12px;
    border:0;border-radius:8px;background:transparent;color:var(--ink-2);font-weight:500;text-align:left;
  }
  .tm-item.active{color:var(--ink);background:var(--capex-soft);font-weight:600}

  /* pin the avatar to the header's top-right corner regardless of how much the title/description wraps --
     as a normal flex item next to a long page description (e.g. the Capex space) it got pushed onto its own
     line and landed at the left edge instead, which looked fine on Hub's short title but wrong everywhere else.
     Desktop doesn't need this override: .top's row has room to keep .actions (and profileMenu() inside it) at
     the far right in normal flow, so the base rules above are enough there. */
  .top{position:relative;padding-right:50px}
  .profile-menu{position:absolute;top:0;right:0}

  .bottomnav{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:50;justify-content:space-around;
    background:var(--surface);border-top:1px solid var(--line);
    padding:6px 4px calc(6px + env(safe-area-inset-bottom,0px));
  }
  .bn-btn{
    flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:2px;padding:4px 2px;
    border:0;background:transparent;color:var(--ink-3);border-radius:10px;font-size:10.5px;
  }
  .bn-btn[aria-current="page"]{color:var(--brand);background:var(--capex-soft)}
  .nb-ico{width:19px;height:19px}
  .nb-txt{font-size:17px;font-weight:700;line-height:19px}
  .nb-label{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  /* room for the fixed bottom bar (~58px) below the page's own bottom padding/safe-area inset */
  body{padding-block-end:calc(64px + env(safe-area-inset-bottom,0px) + 58px)}
  #toast{bottom:calc(20px + env(safe-area-inset-bottom,0px) + 58px)}
}

/* -------------------------------------------------------------------------------- community (activities/forum) */
.act-card{padding:14px 16px;margin-bottom:12px;display:grid;gap:8px}
.act-card h3{margin:0;font-size:16px}
.act-card p{margin:0;color:var(--ink-2);white-space:pre-line}
.act-photos{display:flex;flex-wrap:wrap;gap:8px}
.act-photos img{width:92px;height:92px;object-fit:cover;border-radius:10px;border:1px solid var(--line);background:var(--surface-2)}
.act-photos .ph-del{position:relative}
.act-photos .ph-del button{position:absolute;top:-6px;right:-6px;width:20px;height:20px;border-radius:50%;border:0;
  background:var(--bad);color:#fff;font-size:11px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
.forum-row{padding:12px 14px;margin-bottom:8px;cursor:pointer}
.forum-row h4{margin:0 0 4px;font-size:15px}
.forum-row .help{margin-top:4px}
.forum-mine-row{padding:10px 14px;margin-bottom:6px;display:flex;flex-wrap:wrap;gap:8px;align-items:baseline;justify-content:space-between}
.reply-row{padding:10px 12px;border-top:1px solid var(--line)}
.reply-row:first-child{border-top:0}

/* -------------------------------------------------------------------------------- public hotel website (logged out) */
.pub{min-height:100dvh;background:var(--bg)}
.pub-top{position:sticky;top:0;z-index:30;display:flex;align-items:center;justify-content:space-between;
  padding:12px 20px;background:var(--surface);border-bottom:1px solid var(--line)}
.pub-brand{font-weight:700;font-size:16px}
.pub-top-actions{display:flex;align-items:center;gap:10px}
.pub-hero{position:relative;aspect-ratio:16/7;overflow:hidden;background:var(--tile-a)}
.pub-hero img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .9s ease}
.pub-hero img.on{opacity:1}
.pub-hero .pub-hero-cap{position:absolute;inset:auto 0 0 0;padding:22px 24px;
  background:linear-gradient(0deg,rgba(0,0,0,.62),transparent);color:#fff}
.pub-hero .pub-hero-cap h1{margin:0 0 4px;font-size:26px}
.pub-hero .pub-hero-cap p{margin:0;opacity:.94;max-width:680px;white-space:pre-line}
.pub-hero-dots{position:absolute;left:0;right:0;bottom:10px;display:flex;justify-content:center;gap:6px}
.pub-hero-dots i{width:7px;height:7px;border-radius:50%;background:rgba(255,255,255,.5)}
.pub-hero-dots i.on{background:#fff}
.pub-body{max-width:980px;margin:0 auto;padding:28px 20px 60px;display:grid;gap:32px}
.pub-sect h2{margin:0 0 12px;font-size:19px}
.pub-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:16px}
.pub-card{overflow:hidden;display:grid;grid-template-rows:auto 1fr}
.pub-card img{width:100%;aspect-ratio:16/10;object-fit:cover;display:block;background:var(--surface-2)}
.pub-card .noimg{aspect-ratio:16/10;display:grid;place-items:center;background:var(--tile-a);color:#fff;font-size:13px}
.pub-card-body{padding:12px 14px;display:grid;gap:4px}
.pub-card-body h3{margin:0;font-size:14.5px}
.pub-card-body p{margin:0;font-size:13px;color:var(--ink-2);white-space:pre-line}
.pub-forum-row{padding:12px 14px;margin-bottom:8px;cursor:pointer}
.pub-empty{color:var(--ink-3);font-size:13.5px}
.pub-login-box{display:grid;gap:12px;width:min(320px,100%)}
/* "featured activities" carousel -- same crossfade mechanics as .pub-hero, plus a per-slide caption (activity
   title/text) that fades with its own photo instead of staying fixed like .pub-hero-cap does */
.pub-feat{position:relative;aspect-ratio:16/8;overflow:hidden;border-radius:14px;background:var(--tile-a)}
.pub-feat img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .9s ease}
.pub-feat img.on{opacity:1}
.pub-feat-cap{position:absolute;inset:auto 0 0 0;padding:20px 22px;opacity:0;transition:opacity .9s ease;
  background:linear-gradient(0deg,rgba(0,0,0,.62),transparent);color:#fff}
.pub-feat-cap.on{opacity:1}
.pub-feat-cap h3{margin:0 0 4px;font-size:18px}
.pub-feat-cap p{margin:0;opacity:.94;max-width:640px;white-space:pre-line;font-size:13.5px}
@media (max-width:760px){.pub-hero .pub-hero-cap h1{font-size:20px}.pub-hero{aspect-ratio:4/5}.pub-feat{aspect-ratio:4/5}}

/* Schedule ("ตารางเวลา", schedule.js) -- the personal month/week calendar block (drawMine) and the team roster
   table (drawTeam, rows=employees x columns=dates, each cell a clickable button that opens the assign-shift
   modal). sch-dot is the small color swatch used next to a shift/leave type's name in the settings tables.
   sch-day is now itself a <button> (2nd round, Kang 2026-10-09: "ขอสลับวันหยุด ได้ด้วย หรือเปลี่ยนกะ") that opens
   the self-service change-request modal -- width/text-align reset so it still lays out exactly like the plain
   div it used to be; sch-cell-ro is the read-only counterpart used by the new "ดูตารางงาน" view (no click handler,
   no hover/cursor). */
.sch-dot{display:inline-block;width:10px;height:10px;border-radius:50%;vertical-align:middle}
.sch-cal{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px}
.sch-cal-head{margin-bottom:-2px}
.sch-wd{text-align:center;font-size:11.5px;color:var(--ink-3);padding:2px 0}
.sch-day{border:1px solid var(--line);border-radius:10px;padding:6px;min-height:64px;background:var(--surface);display:flex;flex-direction:column;gap:3px;width:100%;text-align:left;cursor:pointer}
.sch-day:hover{border-color:var(--brand)}
.sch-day-out{opacity:.4}
.sch-day-today{border-color:var(--brand);box-shadow:0 0 0 1px var(--brand) inset}
.sch-day-num{font-size:12px;color:var(--ink-3);font-weight:600}
.sch-chip{font-size:11px;padding:2px 6px;border-radius:6px;border:1px solid transparent;white-space:normal;line-height:1.3}
.sch-chip-leave{font-style:italic}
.sch-balance{padding:10px 14px;min-width:150px}
.sch-roster th,.sch-roster td{white-space:nowrap}
.sch-roster-sect{margin-bottom:22px}
.sch-roster-sect h3{margin:0 0 6px}
.sch-cell{border:1px solid var(--line);border-radius:7px;background:var(--surface);min-width:46px;height:34px;cursor:pointer;font-size:11px;padding:2px 4px;display:flex;align-items:center;justify-content:center}
.sch-cell:hover{border-color:var(--brand)}
.sch-cell-empty{color:var(--ink-3)}
.sch-cell-ro{cursor:default}
.sch-cell-ro:hover{border-color:var(--line)}
.sch-cell-label{overflow:hidden;text-overflow:ellipsis;max-width:70px}
.sch-cell-plus{opacity:.5}
.sch-today-col{color:var(--brand)!important}
.appr-cell{min-width:180px}
