/* components.css —— 按鈕、表單、步驟列、日期列、時段表、徽章、資料表、KPI、圖表、雜項
   由 index.html 的 <style> 切出，**嚴格保留原有次序**。
   CSS 係層疊的：同權重的規則後寫的贏，所以四個檔案的載入次序
   必須同原本一致（base → components → receipt → screens），
   唔可以按字母或者其他規律重排。 */
/* ---------- Buttons ---------- */
.btn{background:var(--brand);color:#fff;padding:11px 20px;border-radius:8px;font-weight:600;font-size:16px;
  display:inline-flex;align-items:center;gap:8px;transition:.15s;border:1px solid transparent}
.btn:hover{background:var(--brand-d)}
.btn:disabled{background:#b9c6cd;cursor:not-allowed}
.btn.g{background:var(--ok)} .btn.g:hover{background:#155e37}
.btn.r{background:var(--bad)} .btn.r:hover{background:#8a2020}
.btn.o{background:#fff;color:var(--brand-d);border-color:#d9c396}
.btn.o:hover{background:var(--brand-l)}
.btn.sm{padding:7px 13px;font-size:14px;border-radius:7px}
.btn.big{padding:15px 30px;font-size:19px}
/* 並排的一對按鈕（例如「查詢」／「清除」）：字數唔同都要一樣闊，
   唔會一大一細。 */
.btn.pair{min-width:132px;justify-content:center}
/* 一行入面的輸入框同按鈕統一高度。
   唔靠內距啱啱好——輸入框同按鈕的字級、行高、邊框都唔同，
   靠內距砌出嚟嘅高度改個字級就會唔對齊。直接指定高度最穩陣。 */
.ctlrow{--ctl-h:52px}
.ctlrow input:not([type=checkbox]):not([type=radio]),
.ctlrow select,
.ctlrow .btn{height:var(--ctl-h)}
.ctlrow .btn{padding-top:0;padding-bottom:0}
.btn.ghost{background:transparent;color:var(--ink-2);border-color:var(--line)}
.btn.ghost:hover{background:var(--brand-l);color:var(--brand-d)}
.btn:disabled{background:#cfc3ab}

/* ---------- Forms ---------- */
label.f{display:block;font-size:14px;font-weight:600;color:var(--ink-2);margin-bottom:6px}
/* 所有文字類輸入框一律同一個樣式。用排除法而非逐個列出 type，
   免得日後新增 password / email / tel 等欄位時又漏掉。 */
input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=button]):not([type=submit]):not([type=reset]),
select, textarea{
  width:100%;padding:11px 13px;border:1.5px solid var(--line);border-radius:8px;background:#fff;
  transition:.15s;font-size:inherit;color:inherit}
input[type=search]{-webkit-appearance:none;appearance:none}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(140,106,42,.18)}
input[type=checkbox],input[type=radio]{width:20px;height:20px;accent-color:var(--brand);flex:0 0 auto}
input::placeholder,textarea::placeholder{color:#a8b4bb}
input[type=password]{letter-spacing:.14em}
input[type=password]::placeholder{letter-spacing:normal}
.field{margin-bottom:16px}
.grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:0 16px}
.grid3{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:0 16px}
.mono{font-family:"SF Mono",Menlo,Consolas,monospace;font-variant-numeric:tabular-nums}
.bigid{font-size:26px;font-weight:700;letter-spacing:.16em;text-align:center;
  padding:10px 15px;height:var(--idh)}
/* 「解讀」框：與 .bigid 同高。用 min-height 而非 height，
   令較長的錯誤訊息（例如列出該層有哪幾個室）仍可完整顯示。 */
.parsebox{min-height:var(--idh);padding:10px 16px;background:#fbf7ee;
  border:1.5px solid var(--line);border-radius:8px;font-size:16px;color:var(--ink-3);
  display:flex;align-items:center;line-height:1.45}

/* ---------- Stepper ---------- */
.steps{display:flex;background:#fff;border:1px solid var(--line);border-radius:14px;overflow:hidden;
  margin-bottom:20px;box-shadow:var(--sh)}
.steps .st{flex:1;padding:16px 10px;text-align:center;font-size:16px;font-weight:600;color:var(--ink-3);
  border-right:1px solid var(--line);position:relative;background:#fff}
.steps .st:last-child{border-right:none}
.steps .st .n{display:inline-flex;width:29px;height:29px;border-radius:50%;background:#ece2cd;color:#a3906f;
  align-items:center;justify-content:center;font-size:15px;margin-right:9px;vertical-align:middle;font-weight:700}
.steps .st.on{background:var(--brand-d);color:#fff}
.steps .st.on .n{background:#fff;color:var(--brand-d)}
.steps .st.done{background:var(--brand-l);color:var(--brand-d)}
.steps .st.done .n{background:var(--brand);color:#fff}
@media(max-width:800px){.steps .st{font-size:0;padding:12px 4px}.steps .st .n{margin:0;font-size:14px}}

/* ---------- Date picker strip ---------- */
.dates{display:grid;grid-template-columns:repeat(7,1fr);gap:10px}
@media(max-width:860px){.dates{grid-template-columns:repeat(auto-fit,minmax(110px,1fr))}}
.dbtn{border:2px solid var(--line);border-radius:12px;padding:15px 6px;text-align:center;background:#fff;transition:.15s}
/* 假日／週末／公眾假期：收費唔同，用淺紅底突出，減少揀錯日子。
   紅色標假期同月曆習慣一致，一眼認得。
   ⚠ 必須寫喺 .dbtn:hover 同 .dbtn.on 之前 —— 三者權重一樣（0,2,0），
     同權重時後寫的贏，寫喺後面會蓋住「已選中」嘅啡色。 */
.dbtn.hol{background:var(--bad-l);border-color:#dda79e}
.dbtn.hol .wd,.dbtn.hol .dd,.dbtn.hol .mo{color:var(--bad)}
.dbtn.hol .tag{background:var(--bad);color:#fff}
.dbtn:hover{border-color:var(--brand);background:var(--brand-l)}
.dbtn.on{border-color:var(--brand-d);background:linear-gradient(160deg,var(--brand),var(--brand-d));color:#fff;
  box-shadow:0 4px 12px rgba(140,106,42,.32)}
.dbtn .wd{font-size:14px;font-weight:600;opacity:.85}
.dbtn .dd{font-size:27px;font-weight:700;line-height:1.15;font-variant-numeric:tabular-nums}
.dbtn .mo{font-size:13px;opacity:.75}
.dbtn .tag{display:inline-block;margin-top:4px;font-size:11px;padding:1px 7px;border-radius:20px;
  background:var(--warn-l);color:var(--warn);font-weight:700}
.dbtn.on .tag{background:rgba(255,255,255,.24);color:#fff}
.dbtn .free{font-size:12px;margin-top:5px;color:var(--ok);font-weight:700}
.dbtn.on .free{color:#ffe9a8}

/* ---------- Timetable ---------- */
.tt{border:1px solid var(--line);border-radius:var(--r);background:#fff;
  /* .scrollx 令 overflow-x:auto，CSS 會把 overflow-y 由 visible 強制計為 auto，
     所以 .tt 本身就是捲動容器；表頭的 sticky 必須相對它（top:0），
     用視窗高度的數值會把表頭往下推、壓住第一列。 */
  /* max-height 由 JS 依實際版面量度後覆寫（見 fitTable），
     令表格底部剛好停在「已選時段」列之上；下面只是未有 JS 時的後備值。 */
  overflow:auto;max-height:70vh;min-height:200px;overscroll-behavior:contain}
.tt table{font-size:15px}
/* 即日總覽：表格撐滿容器（見 fitTable 的 fill），行數少過一屏時
   每行自動攤高，唔會落面吉一大截。訂場櫃檯嗰個唔用——嗰度要
   保持固定行高，方便快速掃視同撳中。 */
#v-day .tt table{height:100%}
.tt th{background:#f7fafb;padding:8px;font-size:15px;border-bottom:2px solid var(--line);
  vertical-align:middle;
  border-right:1px solid var(--line);position:sticky;top:0;z-index:5;
  box-shadow:0 2px 0 rgba(16,40,55,.05)}
.tt th small{display:block;font-weight:400;font-size:12px;color:var(--ink-3)}
.tt td{border-bottom:1px solid #e9eff2;border-right:1px solid #e9eff2;padding:3px;text-align:center;vertical-align:middle}
.tt tbody tr:last-child td{border-bottom:none;padding-bottom:9px}
.tt td.hr{background:#f7fafb;font-weight:700;white-space:nowrap;font-size:15px;width:130px;
  font-variant-numeric:tabular-nums;color:var(--ink-2);position:sticky;left:0;z-index:4}
.tt thead th:first-child{left:0;z-index:6}
/* 單行排版：狀態同價錢（或住戶編號）並排，唔再上下兩行。
   兩行嘅時候每格 52px 高，16 個時段要成 1000px，一屏睇唔晒，
   要不停捲先揀到夜晚嗰啲時段。改單行之後高度減一半。 */
.slot{width:100%;border-radius:7px;padding:6px 7px;font-size:15px;font-weight:600;line-height:1.2;
  border:1.5px solid transparent;transition:.12s;min-height:48px;display:flex;flex-direction:row;
  align-items:center;justify-content:center;gap:.45em;white-space:nowrap}
.slot.free{background:var(--ok-l);color:var(--ok);border-color:#b9e0c9}
.slot.free:hover{background:var(--ok);color:#fff;transform:translateY(-1px);box-shadow:0 3px 8px rgba(28,124,74,.28)}
.slot.free small{opacity:.8;font-weight:600;font-size:13px}
.slot.busy{background:var(--bad-l);color:var(--bad);border-color:#eecaca;cursor:default}
.slot.busy .bid{font-family:"SF Mono",Menlo,monospace;font-size:14px;letter-spacing:.04em;font-weight:700}
/* 管理處預留：灰藍色，同住戶「已訂」（紅）分得開。
   櫃檯要一眼睇得出「唔係有人訂咗，係我哋封咗」，先答到住戶。 */
.slot.hold{background:#e7edf2;color:#4a6478;border-color:#b9cbd8;cursor:default}
.slot.hold .rsn{font-size:12.5px;font-weight:700;opacity:.85}
.slot.na{background:#f4f6f7;color:#b0bcc3;cursor:default;font-weight:500}
.slot.past{background:#f4f6f7;color:#b0bcc3;cursor:default;font-weight:500}
.slot.sel{background:var(--brand);color:#fff;border-color:var(--brand-d);
  box-shadow:0 0 0 3px rgba(140,106,42,.26)}
/* 即日全場總覽的「已訂」格有兩截資料：住戶編號，同埋訂場編號 · 付款方式。
   兩截擺埋一行太長會迫爆格仔，所以呢一版維持上下兩行。
   訂場櫃檯嗰邊只有「已訂 + 住戶編號」，一行就夠。 */
#v-day .slot.busy{flex-direction:column;gap:1px;white-space:normal;line-height:1.25}
#v-day .slot.busy small{font-size:11.5px;opacity:.72;font-weight:600}
.legend{display:flex;gap:18px;flex-wrap:wrap;font-size:14px;align-items:center;color:var(--ink-2)}
.legend i{display:inline-block;width:15px;height:15px;border-radius:4px;margin-right:6px;vertical-align:-2px;border:1.5px solid}
.lg-f{background:var(--ok-l);border-color:#b9e0c9}
.lg-b{background:var(--bad-l);border-color:#eecaca}
.lg-n{background:#f4f6f7;border-color:#dde3e6}
.lg-h{background:#e7edf2;border-color:#b9cbd8}
.lg-s{background:var(--brand);border-color:var(--brand-d)}

/* ---------- Badges / alerts ---------- */
.bdg{display:inline-block;padding:3px 11px;border-radius:20px;font-size:13px;font-weight:700;white-space:nowrap}
.bdg.ok{background:var(--ok-l);color:var(--ok)}
.bdg.no{background:var(--bad-l);color:var(--bad)}
.bdg.wa{background:var(--warn-l);color:var(--warn)}
.bdg.nu{background:#eef2f4;color:var(--ink-2)}
.bdg.br{background:var(--brand-l);color:var(--brand)}
/* 步驟二的大字日期。櫃檯同事多為中年，字細加上一連七日的按鈕排喺一齊，
   最易出的錯就是揀錯日子，所以日期比標題本身（18px）更大更重。 */
.ch2 .s2side{flex:1 1 0;min-width:0;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.bigdate{display:inline-block;padding:5px 15px;border-radius:11px;
  background:var(--brand-l);border:2px solid var(--brand);
  color:var(--brand-d);font-size:20px;font-weight:800;letter-spacing:.02em;line-height:1.3}
.alert{padding:14px 17px;border-radius:9px;border-left:5px solid;margin-bottom:16px;font-size:15.5px;display:flex;gap:11px}
.alert .ic{font-size:20px;line-height:1.2}
.alert.ok{background:var(--ok-l);border-color:var(--ok);color:#125733}
.alert.no{background:var(--bad-l);border-color:var(--bad);color:#7d1d1d}
.alert.wa{background:var(--warn-l);border-color:var(--warn);color:#7a5a06}
.alert.in{background:var(--gold-l);border-color:var(--brand);color:#6b5220}

/* ---------- Data tables ---------- */
.dt{width:100%;font-size:15px}
.dt th{background:#f7fafb;text-align:left;padding:11px 13px;border-bottom:2px solid var(--line);
  font-size:14px;color:var(--ink-2);white-space:nowrap}
.dt td{padding:11px 13px;border-bottom:1px solid #eaf0f2;vertical-align:middle}
.dt tbody tr:hover{background:#f9fcfd}
/* 報表「按住戶編號」逐個列出發票號碼：訂得密嘅住戶會有十幾廿個，
   所以整成一粒粒、可以自動斷行，唔會撐闊張表。
   vertical-align 要 top —— 呢格會高過其他格，中間對齊會令成行歪晒。 */
.dt td.inv{vertical-align:top;line-height:1.5}
/* 交易紀錄原文：一定要等寬字型，唔係啲欄就對唔齊，
   而職員喺另一部機補資料嗰陣睇嘅就係呢個樣。 */
.txnraw{margin:0;font-family:"SF Mono",Menlo,Consolas,monospace;font-size:12.5px;
  line-height:1.55;white-space:pre;overflow:auto;max-height:60vh;
  background:#faf7f0;border:1px solid var(--line);border-radius:8px;padding:12px 14px}
.invno{display:inline-block;font-family:"SF Mono",Menlo,Consolas,monospace;font-size:12.5px;
  background:#f4f0e6;border:1px solid #e6ddc6;border-radius:5px;
  padding:1px 6px;margin:0 4px 4px 0;white-space:nowrap}
.dt .num{text-align:right;font-variant-numeric:tabular-nums}
.scrollx{overflow-x:auto}
.empty{text-align:center;padding:46px 20px;color:var(--ink-3)}
.empty .big{font-size:40px;margin-bottom:10px;opacity:.5}

/* ---------- KPI ---------- */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:15px;margin-bottom:20px}
.kpi{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:17px 19px;box-shadow:var(--sh)}
.kpi .lab{font-size:14px;color:var(--ink-2);font-weight:600;margin-bottom:7px}
.kpi .val{font-size:31px;font-weight:700;line-height:1.15;font-variant-numeric:tabular-nums;color:var(--brand-d)}
.kpi .sub{font-size:13px;color:var(--ink-3);margin-top:4px}
.kpi.g .val{color:var(--ok)} .kpi.w .val{color:var(--warn)} .kpi.r .val{color:var(--bad)}
/* 較細字的 KPI：日期範圍之類的長文字，用 31px 會斷幾行，成張卡高過隔籬 */
.kpi.sm .val{font-size:19px;line-height:1.35}
/* 一張卡入面幾個數（訂場／改期／取消）：橫向排，窄螢幕自動摺行 */
.kpi .multi{display:flex;flex-wrap:wrap;gap:6px 20px;margin-top:2px}
.kpi .multi b{display:block;font-size:22px;font-weight:700;line-height:1.2;
  font-variant-numeric:tabular-nums;color:var(--brand-d)}
.kpi .multi span{display:block;font-size:12px;color:var(--ink-3);margin-top:1px}
.kpi .multi .w b{color:var(--warn)} .kpi .multi .r b{color:var(--bad)}

/* ---------- Charts ---------- */
.bars{display:flex;align-items:flex-end;gap:5px;height:200px;padding:10px 0 0;border-bottom:2px solid var(--line)}
.bars .b{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;height:100%;min-width:0}
.bars .b .fill{width:100%;max-width:52px;background:linear-gradient(180deg,#c9a227,var(--brand));border-radius:5px 5px 0 0;
  min-height:3px;transition:.35s;position:relative}
.bars .b .fill:hover{background:var(--brand-d)}
.bars .b .v{font-size:12px;font-weight:700;color:var(--brand-d);margin-bottom:3px;font-variant-numeric:tabular-nums}
.blabels{display:flex;gap:5px;padding-top:7px}
.blabels div{flex:1;text-align:center;font-size:12px;color:var(--ink-2);min-width:0;overflow:hidden}
.hbar{margin-bottom:11px}
.hbar .t{display:flex;justify-content:space-between;font-size:14px;margin-bottom:4px}
.hbar .track{height:13px;background:#eaf0f2;border-radius:7px;overflow:hidden}
.hbar .fill{height:100%;background:linear-gradient(90deg,#d9b845,var(--brand));border-radius:7px;transition:.4s}
.hbar.g .fill{background:linear-gradient(90deg,#6aa85f,var(--ok))}
.hbar.w .fill{background:linear-gradient(90deg,#d9b845,var(--warn))}
.heat{font-size:13px}
.heat th{padding:6px 4px;font-size:12px;color:var(--ink-2);font-weight:600}
.heat td{padding:2px}
.heat .c{border-radius:5px;padding:7px 3px;text-align:center;font-weight:700;font-size:12.5px;
  font-variant-numeric:tabular-nums;min-width:38px}
.heat .rl{font-weight:700;color:var(--ink-2);white-space:nowrap;padding-right:8px;text-align:right;font-size:13px}

/* ---------- Misc ---------- */
.tabs{display:flex;gap:4px;border-bottom:2px solid var(--line);margin-bottom:20px;flex-wrap:wrap}
.tabs button{padding:11px 19px;font-size:16px;font-weight:600;color:var(--ink-2);border-bottom:3px solid transparent;
  margin-bottom:-2px;border-radius:7px 7px 0 0}
.tabs button:hover{background:#eef3f5;color:var(--brand)}
.tabs button.on{color:var(--brand);border-bottom-color:var(--brand);background:var(--brand-l)}
.modal{position:fixed;inset:0;background:rgba(16,35,45,.55);display:none;align-items:center;justify-content:center;
  z-index:900;padding:20px;backdrop-filter:blur(2px)}
.modal.on{display:flex}
.modal .box{background:#fff;border-radius:13px;max-width:620px;width:100%;max-height:90vh;overflow:auto;
  box-shadow:0 20px 60px rgba(0,0,0,.3)}
.modal .box h3{padding:17px 22px;border-bottom:1px solid var(--line);font-size:19px;display:flex;align-items:center}
.modal .box .mb{padding:22px}
.modal .box .mf{padding:15px 22px;border-top:1px solid var(--line);display:flex;gap:10px;justify-content:flex-end;
  background:#fafcfd;border-radius:0 0 13px 13px;flex-wrap:wrap}
.toast{position:fixed;bottom:26px;left:50%;transform:translateX(-50%) translateY(120px);background:var(--ink);
  color:#fff;padding:14px 26px;border-radius:9px;font-weight:600;z-index:1000;transition:.3s;box-shadow:0 8px 26px rgba(0,0,0,.3);
  max-width:90vw;text-align:center}
.toast.on{transform:translateX(-50%) translateY(0)}
.toast.ok{background:var(--ok)} .toast.no{background:var(--bad)}
.kv{display:grid;grid-template-columns:auto 1fr;gap:9px 18px;font-size:16px}
.kv dt{color:var(--ink-2);white-space:nowrap}
.kv dd{font-weight:600;text-align:right}
.hint{font-size:13px;color:var(--ink-3);margin-top:5px}
.sep{height:1px;background:var(--line);margin:18px 0}
.pill-row{display:flex;gap:7px;flex-wrap:wrap}
.pill{padding:8px 15px;border:1.5px solid var(--line);border-radius:20px;font-size:14px;font-weight:600;
  background:#fff;color:var(--ink-2)}
.pill.on{background:var(--brand);border-color:var(--brand);color:#fff}
.pill:hover{border-color:var(--brand)}


/* 由清單載入到編輯區時閃一閃。
   如果本來就顯示緊同一個住戶，重畫出嚟一模一樣，冇呢個提示職員就會
   以為個掣壞咗——「撳完乜都冇發生」係最難查嘅一種「壞」。 */
@keyframes flashbg{from{background:var(--gold-l)}to{background:transparent}}
.flash{animation:flashbg 1.1s ease-out}
