
  :root{
    --ink:#212A24; --ink2:#5A655D; --paper:#F6F6F2; --surface:#FFFFFF;
    --pine:#1E6B4F; --pine-deep:#15503B; --pine-tint:#EAF3EE;
    --brass:#B08428; --brass-tint:#FBF3E1;
    --line:#E3E6DF; --danger:#B4483C; --danger-tint:#F9ECEA;
    --sky:#3E6E8C; --sky-tint:#E8F0F5;
  }
  *{box-sizing:border-box; margin:0; padding:0;}
  body{
    font-family:"PingFang TC","Noto Sans TC","Microsoft JhengHei",system-ui,sans-serif;
    background:var(--paper); color:var(--ink); font-size:16px; line-height:1.6;
    -webkit-font-smoothing:antialiased;
  }
  .num{font-variant-numeric:tabular-nums;}
  code,.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:.92em;}

  /* ===== App 頂列 ===== */
  .app-head{background:var(--surface); border-bottom:1px solid var(--line);}
  .app-head .row1{
    max-width:1140px; margin:0 auto; padding:14px 24px;
    display:flex; align-items:center; justify-content:space-between; gap:16px;
  }
  .brand{display:flex; align-items:center; gap:10px;}
  .brand .mark{
    width:44px; height:44px; border-radius:50%; object-fit:cover; display:block; flex:none;
    box-shadow:0 0 0 1px rgba(0,0,0,.06);
  }
  .brand .name{font-weight:700; font-size:18px;}
  .brand .tag{font-size:13px; color:var(--ink2); letter-spacing:.14em;}
  .row1-right{display:flex; align-items:center; gap:12px;}
  .userchip{display:flex; align-items:center; gap:10px; font-size:15px; color:var(--ink2);}
  .userchip .avatar{
    width:30px; height:30px; border-radius:99px; background:var(--pine-tint);
    color:var(--pine-deep); font-weight:700; display:flex; align-items:center; justify-content:center; font-size:15px;
  }
  .userchip .out{color:var(--pine); text-decoration:none; font-weight:500;}
  .app-nav{max-width:1140px; margin:0 auto; padding:0 24px; display:flex; gap:2px;}
  .app-nav a{
    padding:10px 16px 12px; font-size:16px; color:var(--ink2); text-decoration:none;
    border-bottom:3px solid transparent; font-weight:500;
  }
  .app-nav a.act{color:var(--pine-deep); border-bottom-color:var(--pine); font-weight:700;}
  .app-nav a:hover{color:var(--ink);}
  /* 手機版導覽:橫向捲動單行,避免文字逐字換行(screenshot 回報過的問題) */
  @media(max-width:640px){
    .app-nav{overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none; flex-wrap:nowrap;}
    .app-nav::-webkit-scrollbar{display:none;}
    .app-nav a{white-space:nowrap; flex:none;}
  }
  /* 群組第二列 subnav(小膠囊 tabs,原 .stats-tabs 樣式沿用泛用化為 .tabs2,只在 active 群組頁數 >1 時渲染) */
  .app-subnav{max-width:1140px; margin:0 auto; padding:0 24px;}
  .tabs2{display:flex; gap:6px; padding:8px 0 10px; overflow-x:auto; scrollbar-width:none;}
  .tabs2::-webkit-scrollbar{display:none;}
  .tabs2 a{padding:5px 12px; border-radius:99px; font-size:14.5px; font-weight:600; text-decoration:none; color:var(--ink2); background:#EFF1EC; white-space:nowrap; flex:none;}
  .tabs2 a.on{background:var(--pine); color:#fff;}

  .wrap{max-width:1140px; margin:0 auto; padding:28px 24px 60px;}
  /* 寬版(PageOpts.wide):欄位多的表用得到整個視窗寬度,頂列與內容一起放寬保持對齊。 */
  body.wide .app-head .row1, body.wide .app-nav, body.wide .app-subnav, body.wide .wrap{max-width:1680px;}

  /* ===== 通用元件 ===== */
  .crumb{font-size:14.5px; color:var(--ink2); margin-bottom:14px;}
  .crumb b{color:var(--ink); font-weight:600;}
  /* 單人頁的「上一位/下一位」導覽(employees/nav.ts):跟麵包屑同一行,右側靠齊。 */
  .crumb-row{display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:14px;}
  .crumb-row .crumb{margin-bottom:0;}
  .recnav{display:flex; align-items:center; gap:8px;}
  .recnav .btn{padding:5px 12px; font-size:14.5px;}
  .recnav .off{color:var(--ink2); border-color:var(--line); opacity:.45; cursor:default;}
  .recnav .pos{font-size:13.5px; color:var(--ink2); white-space:nowrap;}
  .toolbar{display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:16px; flex-wrap:wrap;}
  .toolbar h2{font-size:21px; font-weight:700; letter-spacing:.01em;}
  .toolbar .hint{font-size:14.5px; color:var(--ink2);}
  .actions{display:flex; gap:8px; flex-wrap:wrap;}
  .btn{
    display:inline-flex; align-items:center; gap:6px; border-radius:8px; padding:8px 16px;
    font-size:15.5px; font-weight:600; cursor:pointer; text-decoration:none; border:1px solid transparent;
    font-family:inherit;
  }
  .btn:focus-visible{outline:2px solid var(--brass); outline-offset:2px;}
  .btn-pri{background:var(--pine); color:#fff;}
  .btn-pri:hover{background:var(--pine-deep);}
  .btn-sec{background:var(--surface); color:var(--pine-deep); border-color:var(--line);}
  .btn-sec:hover{border-color:var(--pine); }
  /* ===== 按下就有反應(2026-08-17 老闆:「點擊後畫面常常沒有任何動靜,大家以為沒反應就一直點」)=====
     :active 是純 CSS,手指按下的當下就生效,不等任何網路 —— 這是最快的一層回饋。
     送出中的按鈕由 UX_JS 加上 .is-sending(見下),文字旁出現轉圈,並且擋掉重複送出。 */
  .btn:active{transform:scale(.97);}
  .btn[disabled],.btn.is-sending{opacity:.65; cursor:default; pointer-events:none;}
  .btn.is-sending::after{
    content:""; width:13px; height:13px; border-radius:50%; margin-left:2px;
    border:2px solid currentColor; border-top-color:transparent; animation:spin .6s linear infinite;
  }
  @keyframes spin{to{transform:rotate(360deg);}}
  /* 頂部進度條:一離開/送出就立刻跑起來,讓「系統收到了」這件事在 100ms 內看得見。 */
  #nprog{
    position:fixed; top:0; left:0; height:3px; width:0; z-index:9999;
    background:linear-gradient(90deg,var(--pine),var(--brass)); opacity:0;
    transition:width .2s ease, opacity .2s ease; pointer-events:none;
  }
  #nprog.on{opacity:1;}
  @media (prefers-reduced-motion: reduce){
    .btn:active{transform:none;}
    #nprog{transition:opacity .2s ease;}
    .btn.is-sending::after{animation-duration:2s;}
  }
  /* 小顆按鈕(表格列內用,如打卡單入口):比 .btn 更緊湊 */
  .btn-mini{padding:4px 10px; font-size:14px;}
  /* ===== 期間選擇器 ◀ [ 2026年09月 ⌄ ] ▶(monthPickerHtml/datePickerHtml/yearPickerHtml,見 layout.ts helper 註解)=====
     中間框照抄獎金頁「場次」select:粗外框 + 圓角 + 右側 ⌄,一看就知道能按;字體字重繼承所在標題。
     箭頭緊貼左右,固定字級(不跟大標題一起放大)。 */
  .period-nav{display:inline-flex; align-items:center; gap:6px; vertical-align:middle; white-space:nowrap;}
  .period-arrow{
    display:inline-flex; align-items:center; justify-content:center; width:34px; height:34px; flex:none;
    border:1.5px solid var(--line); border-radius:10px; background:var(--surface); color:var(--pine-deep);
    font-size:13px; font-weight:400; line-height:1; text-decoration:none; letter-spacing:0;
  }
  a.period-arrow:hover{border-color:var(--pine); background:var(--pine-tint);}
  .period-arrow.off{opacity:.35;}
  .period-pick{display:inline-flex; align-items:center; position:relative;}
  .period-pick input,.period-pick select{
    border:2px solid var(--pine-deep); background:var(--surface); width:auto; margin:0; padding:2px 34px 2px 12px;
    font:inherit; font-weight:inherit; color:var(--pine-deep); letter-spacing:inherit; line-height:inherit;
    cursor:pointer; border-radius:10px; -webkit-appearance:none; appearance:none;
  }
  /* iOS WebKit 防塌縮(月選已改 select,這裡管的是日期 input,見 datePickerHtml):
     appearance:none 的 date input 在 iOS 沒有內在寬度,width:auto 會縮成零寬、值看不到;
     給最小寬度 + 值置左(iOS 預設把值置中在塌縮盒內)。 */
  .period-pick input{min-width:7.6em;}
  .period-pick input::-webkit-date-and-time-value{text-align:left; margin:0;}
  /* ⌄:跟左右箭頭同一款圓頭 chevron(SVG mask 上色,不吃字型),固定大小 */
  .period-pick::after{
    content:""; position:absolute; right:11px; top:50%; width:14px; height:14px; margin-top:-7px;
    background:var(--pine-deep); pointer-events:none;
    -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 6 8 10.5 12.5 6' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
    mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 6 8 10.5 12.5 6' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
  }
  .period-pick input:hover,.period-pick select:hover{background:var(--pine-tint);}
  .period-pick input:focus-visible,.period-pick select:focus-visible{outline:2px solid var(--brass); outline-offset:1px;}
  /* Chrome/Edge:把原生日曆小 icon 拉滿整格且透明 —— 點 input 任何位置都直接開 picker */
  .period-pick input::-webkit-calendar-picker-indicator{position:absolute; inset:0; width:auto; height:auto; opacity:0; cursor:pointer;}
  .card{background:var(--surface); border:1px solid var(--line); border-radius:12px; overflow:hidden;}
  .pill{display:inline-block; border-radius:99px; padding:2px 10px; font-size:14px; font-weight:600;}
  .pill-green{background:var(--pine-tint); color:var(--pine-deep);}
  .pill-brass{background:var(--brass-tint); color:#8A6516;}
  .pill-gray{background:#EFF1EC; color:var(--ink2);}
  .pill-red{background:var(--danger-tint); color:var(--danger);}
  /* 異常列反紅(老闆回饋:表中異常的人要反紅才明顯好找)——淡紅底+左緣紅條 */
  tr.anom-row td{background:#FAECE9;}
  tr.anom-row td:first-child{box-shadow:inset 3px 0 0 var(--danger);}

  /* 提早上班的工時認定選單(2026-08-03,punch_page.ts earlyOtCellHtml):
     chip 本身是 summary,點一下浮出選單 —— 純 CSS,不靠 JS;面板 absolute 定位,
     不會把表格列撐高。 */
  details.early-menu{display:inline-block; position:relative;}
  details.early-menu>summary{cursor:pointer; list-style:none;}
  details.early-menu>summary::-webkit-details-marker{display:none;}
  details.early-menu>summary::marker{content:"";}
  details.early-menu[open]>summary{outline:2px solid var(--brass); outline-offset:1px;}
  .early-panel{
    position:absolute; z-index:30; top:100%; right:0; margin-top:5px; min-width:230px;
    background:var(--surface); border:1px solid var(--line); border-radius:10px;
    box-shadow:0 8px 24px rgba(21,80,59,.14); padding:5px; text-align:left;
  }
  /* 最後幾列往上開(2026-08-03 老闆回報:最下面那列的選單掉到卡片外面,點不到)——
     .card 是 overflow:hidden,往下開會被裁掉;往上開時上方有其他列,空間足夠。 */
  tr:nth-last-child(-n+3) .early-panel{top:auto; bottom:100%; margin-top:0; margin-bottom:5px;}
  button.early-opt{
    display:block; width:100%; text-align:left; background:none; border:none; cursor:pointer;
    padding:8px 10px; border-radius:7px; font-family:inherit; font-size:14px; color:var(--ink); line-height:1.45;
  }
  button.early-opt:hover{background:var(--pine-tint);}
  button.early-opt b{display:block; font-weight:700;}
  button.early-opt>span{display:block; font-size:12.5px; color:var(--ink2);}
  button.early-opt[data-cur="1"]{background:var(--pine-tint);}
  .early-cur{
    float:right; font-size:11.5px; font-weight:600; color:var(--pine-deep);
    background:var(--surface); border:1px solid var(--line); border-radius:99px; padding:0 7px;
  }

  table{width:100%; border-collapse:collapse; font-size:15.5px;}
  thead th{
    text-align:left; font-size:14px; color:var(--ink2); font-weight:600; letter-spacing:.06em;
    padding:10px 14px; background:#FBFBF9; border-bottom:1px solid var(--line); white-space:nowrap;
  }
  tbody td{padding:11px 14px; border-bottom:1px solid var(--line); vertical-align:middle;}
  tbody tr:last-child td{border-bottom:none;}
  tbody tr{cursor:pointer;}
  tbody tr:hover{background:#FAFBF8;}
  .t-r{text-align:right;}
  /* 欄位直線分隔(2026-08-13 老闆指示):時數改「N時M分」後每格字串變寬,只靠留白會擠成一團 ——
     需要分欄的表格在該格加 class="sep",左側就畫一條細線。 */
  th.sep, td.sep{border-left:1px solid var(--line);}
  .edit-ic{color:var(--pine); font-size:15px; text-decoration:none; font-weight:600;}

  /* ===== 詳細頁 ===== */
  .detail{display:grid; grid-template-columns:290px 1fr; gap:20px; align-items:start;}
  @media(max-width:820px){ .detail{grid-template-columns:1fr;} }
  .profile{padding:26px 22px; text-align:center;}
  .profile .avatar-lg{
    width:72px; height:72px; border-radius:99px; margin:0 auto 12px; background:var(--pine-tint);
    color:var(--pine-deep); font-size:28px; font-weight:700; display:flex; align-items:center; justify-content:center;
  }
  .profile .empno{font-size:14px; color:var(--ink2); letter-spacing:.12em;}
  .profile .nm{font-size:22px; font-weight:700; margin:2px 0 8px;}
  .profile dl{margin-top:18px; text-align:left; border-top:1px solid var(--line);}
  .profile dl div{display:flex; justify-content:space-between; gap:10px; padding:9px 2px; border-bottom:1px dashed var(--line); font-size:15px;}
  .profile dt{color:var(--ink2);}
  .profile dd{font-weight:600;}

  .tabs{display:flex; gap:2px; border-bottom:1px solid var(--line); background:#FBFBF9; padding:6px 10px 0; border-radius:12px 12px 0 0;}
  .tabs button, .tabs a{
    border:none; background:transparent; padding:9px 16px 11px; font-size:15.5px; font-weight:600;
    color:var(--ink2); cursor:pointer; border-bottom:3px solid transparent; font-family:inherit; text-decoration:none;
  }
  .tabs button.on, .tabs a.on{color:var(--pine-deep); border-bottom-color:var(--pine); background:var(--surface); border-radius:8px 8px 0 0;}
  .tabs button:focus-visible{outline:2px solid var(--brass); outline-offset:-2px;}
  .panel{display:none; padding:22px;}
  .panel.on{display:block;}
  .frows div{display:grid; grid-template-columns:160px 1fr auto; gap:14px; padding:11px 4px; border-bottom:1px dashed var(--line); align-items:center;}
  .frows div:last-child{border-bottom:none;}
  .frows dt{color:var(--ink2); font-size:15px;}
  .frows dd{font-weight:600; font-size:16px;}
  .frows .muted{color:var(--ink2); font-weight:400; font-size:14.5px;}

  .leave-hero{display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:18px;}
  @media(max-width:640px){ .leave-hero{grid-template-columns:1fr;} }
  .stat{border:1px solid var(--line); border-radius:10px; padding:16px; background:#FDFDFC;}
  .stat .lb{font-size:14px; color:var(--ink2); letter-spacing:.08em;}
  .stat .v{font-size:28px; font-weight:700; margin-top:2px;}
  .stat .v small{font-size:15px; font-weight:500; color:var(--ink2);}
  .stat.hero{background:var(--pine-tint); border-color:#CBE2D6;}
  .stat.hero .v{color:var(--pine-deep);}
  .note{background:var(--brass-tint); border:1px solid #EAD9AE; border-radius:10px; padding:12px 14px; font-size:15px; color:#6E5111;}
  .quota{background:var(--brass-tint); border:1px solid #EAD9AE; border-radius:8px; padding:8px 12px; font-size:15px; font-weight:700; color:#8A6516; margin-bottom:10px;}

  /* ===== 我的(員工自助)===== */
  .me-grid{display:grid; grid-template-columns:1fr 1fr; gap:20px;}
  @media(max-width:820px){ .me-grid{grid-template-columns:1fr;} }
  .me-leave{padding:26px;}
  .me-leave .big{font-size:46px; font-weight:800; color:var(--pine-deep); line-height:1.1;}
  .me-leave .big small{font-size:18px; font-weight:600; color:var(--ink2);}
  .bar{height:8px; border-radius:99px; background:#E8ECE6; margin:14px 0 8px; overflow:hidden;}
  .bar i{display:block; height:100%; width:57%; background:var(--pine); border-radius:99px;}
  .me-pay{padding:26px; color:var(--ink2);}
  .me-pay .soon{font-size:15px; background:#EFF1EC; border-radius:8px; padding:10px 12px; margin-top:12px;}

  /* ===== 表單(mockup 未涵蓋,本專案新增) ===== */
  .form-grid{display:grid; grid-template-columns:160px 1fr; gap:12px 16px; align-items:center;}
  .form-grid label{color:var(--ink2); font-size:15px; font-weight:600;}
  /* 標籤對齊內容第一行(2026-08-11 老闆截圖:員工設定頁「固定休」以下整片看起來偏移)。
     預設的 align-items:center 在一格只有一個輸入框時剛好,但「每週班別」那格有七個下拉、
     「固定休」那格有膠囊列+兩個開關+說明 —— 標籤被推到那一格的正中間,視覺上就黏到了上一列的
     內容下方(星期膠囊看起來長在「每週班別」裡)。.top-label 改成靠上對齊,標籤補 9px 讓文字
     與輸入框內的文字同高;純文字的值請一併加 .val-text 補同樣的 9px,兩邊才對得齊。 */
  .form-grid.top-label{align-items:start;}
  .form-grid.top-label > label{padding-top:9px;}
  .form-grid.top-label > .val-text{padding-top:9px;}
  /* 手機改單欄(2026-08-03 老闆回報:加班申請的時/分選單被擠到只剩一個字寬,看不到時間)。
     390px 的螢幕扣掉 160px 標籤欄與內距,右欄只剩 ~180px —— 兩個 select 放不下。
     標籤改放上一行、控制項全寬,所有用 form-grid 的表單在手機上都跟著變好按。 */
  @media(max-width:560px){
    .form-grid{grid-template-columns:1fr; gap:4px 0;}
    .form-grid label{margin-top:10px; font-size:14.5px;}
    .form-grid label:first-child{margin-top:0;}
    /* 單欄堆疊時標籤本來就在內容上一行,不需要那 9px(桌面才有的對齊補正)。 */
    .form-grid.top-label > label, .form-grid.top-label > .val-text{padding-top:0;}
  }
  /* 堆疊式表單欄位(公司設定等):每格自成一塊,標題在上→輸入格在中→說明小灰字緊貼輸入格正下方,
     全寬單欄由上往下排,手機/桌面都對齊。取代舊的 2 欄 form-grid + 黃色 callout 說明亂飄的問題。 */
  .field{display:flex; flex-direction:column; gap:6px; margin-bottom:18px; max-width:100%;}
  .field > label{color:var(--ink); font-size:15.5px; font-weight:600;}
  .field-note{font-size:14px; color:var(--ink2); line-height:1.5;}
  .field-note code{background:#EFF1EC; border-radius:4px; padding:0 4px;}
  .field input, .field select, .field textarea{width:100%;}
  input,select,textarea{
    border:1px solid var(--line); border-radius:8px; padding:8px 10px; font-size:15.5px;
    font-family:inherit; color:var(--ink); background:var(--surface); width:100%;
  }
  /* checkbox/radio 不吃上面的 width:100%(2026-08-10 iPad 回報:裸 checkbox 撐滿整行,
     旁邊的說明文字被擠成一字寬直排、整列被撐到幾千 px 高)。保持原生大小、在 flex 列裡不縮。 */
  input[type="checkbox"],input[type="radio"]{width:auto; flex:none; padding:0;}
  input:focus,select:focus,textarea:focus{
    border-color:var(--pine); outline:2px solid var(--pine-tint); outline-offset:0;
  }
  /* 擋人操作的訊息(2026-07-30 老闆:「員工不知道為什麼被擋住」)。
     不做彈窗(單日申請本身已在 modal 內,再疊一層變雙層遮罩);靠字級、顏色、左緣色條讓它跳出來。
     16.5px 比內文(16px)大,手機再放大到 17px —— 原本 15px 比內文還小,難怪看不到。 */
  .err-note{
    background:var(--danger-tint); color:#8C3229;
    border:1px solid #E8C4BE; border-left:5px solid var(--danger);
    border-radius:10px; padding:16px 18px; font-size:16.5px; line-height:1.55;
    margin-bottom:16px; scroll-margin-top:16px;
  }
  /* 兩層文字:.t 講「為什麼被擋」、.d 講「怎麼辦」。訊息本來就有這兩段,
     只是原本擠成一行 15px 紅字看不出來。 */
  .err-note .t{display:block; font-size:18.5px; font-weight:700; margin-bottom:4px;}
  .err-note .d{display:block; font-size:16px; color:#6E3A33;}
  @media(max-width:640px){
    .err-note{padding:18px 16px; font-size:17px;}
    .err-note .t{font-size:19px;}
    .err-note .d{font-size:16.5px;}
  }
  /* 告知型訊息(2026-08-17):版型同 .err-note,顏色改 brass —— 「你沒排到」不是錯誤、
     但也絕不能是灰字小提示,它是員工這趟操作唯一的結果回報。 */
  .info-note{
    background:var(--brass-tint); color:#8A6516;
    border:1px solid #E4D2A8; border-left:5px solid var(--brass);
    border-radius:10px; padding:16px 18px; font-size:16.5px; line-height:1.55;
    margin-bottom:16px; scroll-margin-top:16px;
  }
  .info-note .t{display:block; font-size:18.5px; font-weight:700; margin-bottom:4px;}
  .info-note .d{display:block; font-size:16px; color:#7A5A14;}
  @media(max-width:640px){
    .info-note{padding:18px 16px; font-size:17px;}
    .info-note .t{font-size:19px;}
    .info-note .d{font-size:16.5px;}
  }
  /* 🔴 .hint 原本只有 ".toolbar .hint" 這個層級選擇器,沒有裸規則 ——
     全站約 100 處 class="hint" 在 .toolbar 之外一律渲染成 16px 預設黑字、零區隔,
     包含預約假的「共 N 天(連休 4 天以上需附副總同意截圖)」。補這一行一次修好。 */
  .hint{font-size:14.5px; color:var(--ink2); line-height:1.5;}

  /* 固定休週選:單行膠囊列(取代舊版逐一垂直 checkbox+label,曾在窄版裂成一長條) */
  .day-pills{display:flex;gap:6px;flex-wrap:wrap}
  .day-pill{border:1.5px solid var(--line);border-radius:99px;padding:5px 12px;font-size:15px;cursor:pointer;user-select:none}
  .day-pill input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
  .day-pill:has(input:checked){background:var(--pine);border-color:var(--pine);color:#fff}

  /* ===== 班表月曆(對齊 docs/design/schedule-mockup-v2.html 畫面1)===== */
  .toolbar .hint a{color:var(--pine-deep); font-weight:600; text-decoration:none;}
  .toolbar .hint a:hover{text-decoration:underline;}
  /* overflow 特意不設 hidden:名額/詳情 popover(.chip-pop)展開時會超出格線範圍,
     若這裡裁切會被截斷/蓋住(owner 回報「詳情浮窗疊字」的一部分成因);四角圓角改由
     border-radius 搭配透明背景撐出即可,不靠 overflow 裁切。 */
  /* 分隔線 1px→2px(2026-07-31 老闆):①手機上容易看錯天;②7 欄寬度除不盡時,
     1px 的 gap 會在某些欄界被 subpixel 捨入吃掉(老闆截圖:週三/週四之間整條消失),2px 不會。 */
  /* minmax(0,1fr)(2026-07-31 老闆:人少的那欄縮成細細的)—— 純 1fr 的最小寬是 auto,
     內容寬的欄會把內容窄的欄擠扁;minmax(0,1fr) 強制七欄永遠等寬。 */
  .cal{display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); gap:2px; background:var(--line); border:1px solid var(--line); border-radius:12px;}
  .cal .h{background:#FBFBF9; padding:8px 10px; text-align:center; font-size:14px; font-weight:700; color:var(--ink2); letter-spacing:.06em;}
  /* 手機版月曆:維持 7 欄,外層橫向捲動撐開最小寬度,格子維持可讀而不是硬擠 */
  @media(max-width:640px){
    .cal-scroll{overflow-x:auto; -webkit-overflow-scrolling:touch; margin:0 -2px; padding:0 2px;}
    /* 2026-07-31 老闆:小字仍被切 → 整體格子加寬(橫向捲動本來就有,寬一點好讀)。 */
    .cal{min-width:940px;}
    .cal .h{font-size:13px; padding:6px 8px;}
  }
  /* padding-bottom 是「一定點得到的空白帶」(2026-08-17 老闆:名字排滿整格時,想再排班進去
     幾乎沒有地方可以點)。整格的連結 .day-link 是 inset:0 鋪滿整個 .day(含 padding),
     名字 chip 疊在上層 —— 所以只要底部保留一條沒有 chip 的空白,那條就是穩定的點擊區。
     這條不放任何文字:老闆要的是留白,不是又多一行說明。 */
  .day{background:var(--surface); min-height:122px; padding:8px 9px 36px; position:relative; scroll-margin-top:76px;}
  .day.empty{background:#FAFAF8;}
  .day.weekend{background:#FBFBF8;}
  .day.today{outline:2px solid var(--pine); outline-offset:-2px;}
  .day.closed{background:#F4F5F1;}
  /* 禁休日(2026-07-30 老闆:「勾這天禁休的話,那一整格反深灰」)。
     整格深灰底 + 反白文字,離很遠也看得出來哪幾天不能排 —— 標記的是**日期格本身**,
     跟事件名稱那顆標籤是兩回事(2026-07-30 老闆補充澄清)。
     .weekend/.today 排在它之前,所以這條會贏過週末的淺底;.today 用 outline 不吃背景,兩者可並存。 */
  .day.restricted{background:#5A605B;}
  .day.restricted .d,
  .day.restricted .cap,
  .day.restricted .empty-hint{color:#EDEFEA;}
  .day.restricted .cap.full{color:#FFC9BE;}
  .day.restricted .chip{border-color:rgba(255,255,255,.28);}
  .day.restricted a.daylink{color:#EDEFEA;}
  /* 詳情浮窗(.chip-pop)展開時,把「這一格」整格拉到所有相鄰格子之上:.day 本身已 position:relative,
     但平常 z-index:auto 不建立新的堆疊環境;相鄰格子內的 .cap-wrap/.chip-wrap 各自帶 z-index:1
     會各自建立堆疊環境,同層比較時只看 DOM 順序,導致展開的浮窗被「後面(下方/右側)那格」的
     名額 pill 等元素蓋過去、看起來變半透明/被切字(owner 回報)。這裡讓「開著詳情的格子」整格
     取得比所有 sibling 格子都高的堆疊層級,格內的 chip-wrap/chip-pop 就整包一起浮到最上層。 */
  .day:has(details[open]){z-index:40; position:relative;}
  /* 日期數字 +3 號(2026-07-31 老闆,15→18;手機 13.5→16.5)。 */
  .day .d{font-size:18px; font-weight:700; display:flex; align-items:center; gap:6px; margin-bottom:6px;}
  .day .cap{margin-left:auto; font-size:12.5px; color:var(--ink2); font-weight:500;}
  .day .cap.full{color:var(--danger); font-weight:700;}
  @media(max-width:640px){
    .day{min-height:96px; padding:6px 7px 34px;}
    .day .d{font-size:16.5px;}
    .day .cap{font-size:11.5px;}
    .evt{font-size:11.5px;}
    .chip{font-size:18px;}
    /* 手機格窄,兩欄擠到假別小字被切(2026-07-31 老闆截圖)→ 單欄。 */
    .chips{grid-template-columns:minmax(0,1fr);}
  }
  /* 月曆即操作介面:整格底層連結(req=/manage=),迷你名額 ±疊在上層維持可點 ===== */
  .day-link{position:absolute; inset:0; z-index:0; cursor:pointer;}
  /* 打工一鍵排休(2026-07-31):整格是一顆 button 而不是 <a>,外觀要一模一樣 ——
     button 預設有邊框/底色/內距,不清掉會在每一格畫出一個灰盒子。 */
  .day-form{position:absolute; inset:0; z-index:0; margin:0;}
  .day-form .day-link{width:100%; height:100%; border:0; background:transparent; padding:0; appearance:none;}
  /* 預約假的 Agoda 式區間選取(2026-07-30):選到的日子整格上色,頭尾再深一階。 */
  /* 選取模式:游標改成十字、蓋掉整格 <a> 的手指游標,讓「現在是在選日期」看得出來。 */
  .cal.rr-picking .day{cursor:crosshair;}
  .cal.rr-picking .day-link{pointer-events:none;}
  .day.rr-sel{background:var(--pine-tint); box-shadow:inset 0 0 0 2px #B7D6C6;}
  .day.rr-edge{background:#D3E8DC; box-shadow:inset 0 0 0 2px var(--pine);}
  .day:hover .day-link{background:rgba(30,107,79,.03);}
  /* ===== 調假模式(2026-08-27,見 schedule/move.ts)=====
     老闆要求:「很清楚地讓使用者知道現在點選日曆就是要調過去的日期」。三個訊號一起下:
     頁頂指示條(.move-banner)、整片月曆換底色+十字游標、原本那天標「原本」並反白。
     可選的日子 hover 會整格亮起來 —— 不能選的日子(過去/今天/原本那天)沒有 .day-link,
     自然就沒有 hover 反應,「按不下去」看得出來而不是沒反應。 */
  .move-banner{border-left:4px solid var(--brass); background:var(--brass-tint);}
  .cal.cal-move{background:#8A6516;}
  .cal.cal-move .day{cursor:crosshair;}
  .cal.cal-move .day:has(.day-link):hover{background:var(--brass-tint); box-shadow:inset 0 0 0 2px var(--brass);}
  .day.day-move-src{background:#F1EFE7; box-shadow:inset 0 0 0 2px var(--brass);}
  .evt-move-src{background:var(--brass); color:#fff;}
  /* 點日期的當下就要有反應(2026-08-17):手指按下 → 整格立刻上色,不等伺服器。
     .day-loading 由 SCHED_JS 在送出請求時加上、面板回來時移除 —— 讓「正在讀這一天」看得見。 */
  .day-link:active{background:rgba(30,107,79,.12);}
  .day.day-loading{background:var(--pine-tint); box-shadow:inset 0 0 0 2px #B7D6C6;}
  /* 當日面板讀取中的骨架:面板框先出現(位置/高度先佔好,不會跳版),內容到了再換掉。 */
  .panel-skel{padding:18px;}
  .panel-skel .sk{height:13px; border-radius:6px; margin-bottom:10px;
    background:linear-gradient(90deg,var(--line) 25%,var(--surface) 37%,var(--line) 63%);
    background-size:400% 100%; animation:skel 1.2s ease infinite;}
  @keyframes skel{0%{background-position:100% 50%;} 100%{background-position:0 50%;}}
  @media (prefers-reduced-motion: reduce){ .panel-skel .sk{animation:none;} }
  /* 名額點擊展開 ±(admin 專用):平常只顯示 pill 文字,點擊後左右滑出 −/＋ 小圓鈕,
     一次只開一個(document click 收合、JS 見 CAP_JS)。 */
  .cap-wrap{margin-left:auto; display:inline-flex; align-items:center; gap:2px; position:relative; z-index:1;}
  .cap-pill{
    background:none; border:1px solid transparent; border-radius:99px; padding:1px 8px;
    font-size:12.5px; color:var(--ink2); font-weight:500; cursor:pointer; font-family:inherit; line-height:1.5;
    transition:background .15s ease, border-color .15s ease;
  }
  .cap-pill.full{color:var(--danger); font-weight:700;}
  .cap-wrap:hover .cap-pill, .cap-wrap.cap-open .cap-pill{border-color:var(--line); background:#F4F6F3;}
  .cap-side{
    display:inline-flex; max-width:0; opacity:0; transform:scale(.4); overflow:hidden; pointer-events:none;
    transition:max-width .15s ease, opacity .15s ease, transform .15s ease;
  }
  .cap-wrap.cap-open .cap-side{max-width:22px; opacity:1; transform:scale(1); pointer-events:auto;}
  .cap-btn{
    background:var(--pine-tint); color:var(--pine-deep); border:none; border-radius:99px; width:18px; height:18px;
    font-size:13px; font-weight:700; cursor:pointer; padding:0; font-family:inherit; line-height:1;
    display:flex; align-items:center; justify-content:center; position:relative; z-index:1;
  }
  .cap-btn:hover{background:var(--pine); color:#fff;}
  @media(prefers-reduced-motion:reduce){
    .cap-pill,.cap-side{transition:none;}
  }
  .chip-wrap{z-index:1;}
  /* 同一格內、DOM 順序在後面的 chip 會蓋住已展開的浮窗(owner 2026-07-28 回報:浮窗不在最上層)——
     每個 .chip-wrap 都是 z-index:1 的堆疊環境,浮窗自己的 z-index:60 只在該環境內有效,
     同層相比只看 DOM 順序。把「展開中的那個 chip」整包抬到同格其他 chip 之上才是根治。 */
  .chip-wrap[open]{z-index:50;}
  .mgmt-section{border-top:1px dashed var(--line); margin-top:12px; padding-top:12px;}
  /* 人工介入打卡標記(補登/訂正,2026-08-01 日檢視也要顯示 → 移到全域;/my-attendance 同款)。 */
  .manual-tag{font-size:11.5px; font-weight:700; color:#8A6516; background:var(--brass-tint); border-radius:4px; padding:1px 5px; margin-left:4px; vertical-align:middle;}
  /* 打卡人工異動標記「修改/補登/已刪除」(2026-08-04,見 attendance/punch_origin.ts)。
     點一下浮出原始打卡時間 —— 標記本身只講種類,細節在面板裡,表格不變寬。
     樣式放全域是因為日檢視/打卡單/我的出勤/單日編輯四個頁面都會用到。 */
  details.po-menu{display:inline-block; position:relative;}
  details.po-menu>summary{cursor:pointer; list-style:none;}
  details.po-menu>summary::-webkit-details-marker{display:none;}
  details.po-menu>summary::marker{content:"";}
  details.po-menu[open]>summary{outline:2px solid var(--brass); outline-offset:1px;}
  .po-tag{display:inline-block; font-size:11.5px; font-weight:700; border-radius:4px; padding:1px 5px; margin-left:4px; vertical-align:middle; white-space:nowrap;}
  .po-edited{color:#8A6516; background:var(--brass-tint);}
  .po-added{color:var(--ink2); background:#EDEFEA;}
  .po-deleted{color:var(--danger); background:#FBEBEA;}
  .po-panel{
    position:absolute; z-index:40; top:100%; right:0; margin-top:5px; min-width:250px;
    background:var(--surface); border:1px solid var(--line); border-radius:10px;
    box-shadow:0 8px 24px rgba(21,80,59,.14); padding:10px 12px; text-align:left; white-space:normal;
  }
  /* 表格最後幾列的面板往上開,免得被切在畫面外(同 .early-panel 的處理)。 */
  tr:nth-last-child(-n+3) .po-panel{top:auto; bottom:100%; margin-top:0; margin-bottom:5px;}
  .po-grid{display:grid; grid-template-columns:auto 1fr; gap:3px 10px; align-items:baseline;}
  .po-k{font-size:12.5px; color:var(--ink2); white-space:nowrap;}
  .po-v{font-size:13.5px; color:var(--ink); font-variant-numeric:tabular-nums;}
  .po-v.po-strong b{font-size:16px; font-weight:700;}
  .po-src{font-size:12px; color:var(--ink2);}
  /* 補卡單的核准前判斷依據(2026-08-04):當天現有什麼卡 + 按下核准的後果。
     有既有卡=更正,平靜的灰底;完全沒卡=純補登、沒有機器紀錄可佐證,紅左邊條讓它有份量。 */
  .punch-ctx{margin-top:6px; padding:7px 10px; border-radius:8px; background:#F4F6F2; border-left:3px solid var(--line); font-size:13.5px; line-height:1.6; font-variant-numeric:tabular-nums;}
  .punch-ctx-bare{background:#FBEBEA; border-left-color:var(--danger);}
  .punch-ctx-eff{color:var(--ink2); margin-top:2px;}
  /* 店內打卡被擋(2026-08-04 改版:最新事件+時間,不統計)。三欄 grid 對齊:時間/人/網段。 */
  .blk-grid{display:grid; grid-template-columns:auto auto 1fr; gap:4px 14px; align-items:baseline; margin:10px 0 4px; font-size:14.5px;}
  .blk-t{font-variant-numeric:tabular-nums; white-space:nowrap; color:var(--ink2);}
  .blk-who{font-weight:700; white-space:nowrap;}
  .blk-net{color:var(--ink2); font-size:13px; overflow-wrap:anywhere;}
  .mgmt-section h4{font-size:14.5px; font-weight:700; color:var(--ink2); margin-bottom:8px;}
  /* 管理面板改摺疊(owner:手機不能整屏肥)——代登記預設展開,當日事件等預設收合,
     一行 summary 顯示目前狀態,點開才看到表單。 */
  .mgmt-section summary{cursor:pointer; font-size:14.5px; font-weight:700; color:var(--ink2); list-style:none; padding:2px 0;}
  .mgmt-section summary::-webkit-details-marker{display:none;}
  .mgmt-section summary::before{content:"▸"; display:inline-block; width:12px; margin-right:2px;}
  .mgmt-section[open] summary::before{content:"▾";}
  .mgmt-section .mgmt-body{margin-top:8px;}
  .evt{display:inline-block; background:#3E4A42; color:#fff; border-radius:5px; padding:0 7px; font-size:12.5px; font-weight:600; margin-bottom:5px;}
  /* 國定假日標籤(tw_holidays,系統產生、非管理面板可編輯):brass 底色與 admin 事件(.evt 深綠底)區隔,兩者可並存 */
  .evt.lian{background:var(--brass);}
  /* 國定連假的補假日(tw_holiday_makeups,2026-09-21):跟國定假日同一族(brass 色系)讓人一眼
     看出是同一件事,但**線框不實心** —— 照本站既有文法「實心=有拘束力、線框=資訊性」。
     這幾天本店照常營業、不加倍發給(見 migrations/0113),畫成實心會被誤讀成放假。 */
  .evt.lian.lian-mk{background:var(--brass-tint); color:var(--brass); border:1px solid var(--brass);}
  /* 「同崗位滿」(2026-08-17):跟禁休(brass 實底)與事件(深綠實底)刻意不同 —— 這天不是
     全店不能休,只是輪不到你,而且照樣點得進去找人調假。用線框弱化,不搶禁休的視覺位置。 */
  .evt.evt-understaff{background:transparent; color:var(--ink2); border:1px solid var(--line); font-weight:700;}
  /* 兩人並排(2026-07-31 老闆:「像以前的 Excel 那樣,兩個兩個並排,格子才不會太長」——
     對照舊排班表照片:一天內人名左右兩欄排,排滿時一眼掃得完)。chip 在欄內拉滿寬度、
     過長裁字(之後名字會改單字簡稱,更放得下);奇數個時最後一顆佔左半欄。 */
  /* minmax(0,1fr)(2026-07-31):chip 名字放大後純 1fr 會被內容撐破格子(名字突出格外)。 */
  .chips{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:3px 4px;}
  .chips .chip{width:100%;}
  /* 右欄 chip 的詳情浮窗改靠右展開,不然 min-width 210px 從右半欄的左緣往右長,會戳出格子外。 */
  .chips .chip-wrap:nth-child(even) .chip-pop{left:auto; right:0;}
  .chip-wrap{position:relative;}
  .chip-wrap summary{list-style:none; cursor:pointer;}
  .chip-wrap summary::-webkit-details-marker{display:none;}
  /* 2026-07-31 老闆:chip 名字調大 5 號(14→19)、假別小字調小 3 號(12→9,見 .chip .st)。 */
  .chip{display:flex; align-items:center; gap:5px; border-radius:6px; padding:2px 7px; font-size:19px; font-weight:600; width:fit-content; max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; border:1px solid transparent; box-sizing:border-box;}
  /* 假別配色(2026-08-01 老闆第三版,取代同日淡色版):**不是自己的一律灰色、不分假別**
     (大家只看自己的班;假別縮寫小字仍在,主管要查照樣看得到),只有自己的班鮮豔 + 帶框。
     自己的配色(老闆指定):一般休=松綠(2026-08-17 由深黑改)、特休=輝煌金、婚假=亮紅、
     病假=草仔色、喪假=卡其色;
     事假維持橘、公假維持 brass。改班藍色 chip 維持原樣(需要被注意)。
     申請視窗(renderTypeOpts)的圓點顏色與這裡同一組,改色兩邊要一起動。 */
  .chip.rest,.chip.annual,.chip.personal,.chip.sick,.chip.out,.chip.marriage,.chip.bereavement{background:#EFF1EC; color:#98A19A;}
  /* 彩色模式(2026-08-01 老闆:最高權限自己不在排班體系,整片灰很難看):admin 個人開關
     (POST /schedule/colormode,app_kv 記住),開啟後所有人的 chip 按假別上色。
     一般休維持淺色(整月大多是休,全黑會滿版黑塊),其餘假別用「自己的」同一組鮮豔色;
     自己的 chip 規則寫在後面、同權重後者勝 → 照樣深黑/帶框,不被這裡蓋掉。 */
  .cal-colored .chip.rest{background:#EFF1EC; color:#4A554C;}
  .cal-colored .chip.annual{background:#F6E084; border-color:#D4AF37; color:#7A5800;}
  .cal-colored .chip.personal{background:#E8862B; color:#FFFFFF;}
  .cal-colored .chip.sick{background:#8FCE3C; color:#26430A;}
  .cal-colored .chip.out{background:#A67F2E; color:#FFFFFF;}
  .cal-colored .chip.marriage{background:#E63C25; color:#FFFFFF;}
  .cal-colored .chip.bereavement{background:#C2B280; color:#463D24;}
  .chip .st{font-size:9px; font-weight:500; opacity:.75;}
  .chip.pending{border-style:dashed; border-color:var(--brass);}
  /* 班別異動 chip(2026-07-31 老闆:改成藍色、名字小/班別字大 —— 一目瞭然誰的班不一樣)。 */
  .chip.shiftchg{background:#E8F1FA; border-color:#3E7CB8; color:#1E5288; cursor:default; font-size:13px;}
  .chip.shiftchg .st{font-size:18px; font-weight:800; opacity:1; color:#1E5288;}
  /* 自己的休假:鮮豔 + 加粗外框(「一眼就能看得出自己的休假在哪裡」)。 */
  .chip.mine{outline:2.5px solid var(--pine); outline-offset:1px; font-weight:700;}
  /* 一般休(自己)2026-08-17 由深黑 #1F1F1F 改成品牌松綠:黑色在整片米白月曆上像個破洞,
     而且它是最常出現的假別,等於整張表最重的視覺量體都給了最普通的東西。松綠與特休的金色
     是這套設計原本的主色配對,且「自己的」外框本來就是松綠 —— 填色一致後,自己的班收斂成
     同一個識別色。外框改用更深一階的松綠,填色與外框才不會糊成一塊。
     ⚠ 這個色值在 calendar_page.ts renderTypeOpts 的圓點也有一份,兩邊要一起改。 */
  .chip.mine.rest{background:var(--pine); color:#FFFFFF; outline-color:var(--pine-deep);}
  .chip.mine.annual{background:#F6E084; border-color:#D4AF37; color:#7A5800;}
  .chip.mine.personal{background:#E8862B; color:#FFFFFF;}
  .chip.mine.sick{background:#8FCE3C; color:#26430A;}
  .chip.mine.out{background:#A67F2E; color:#FFFFFF;}
  .chip.mine.marriage{background:#E63C25; color:#FFFFFF;}
  .chip.mine.bereavement{background:#C2B280; color:#463D24;}
  /* 不透明背景 + 邊框 + 強陰影,z-index:60 高於頁面上其他堆疊層(.modal-backdrop:50、
     .day(開啟時):40)——popover 內容一律要能完整蓋住底下月曆文字,不能穿透。
     max-width 讓窄螢幕(手機)不會被撐出可視範圍。 */
  .chip-pop{position:absolute; z-index:60; top:100%; left:0; margin-top:4px; min-width:210px; max-width:min(230px,80vw); background:var(--surface); border:1px solid var(--line); border-radius:8px; padding:10px 12px; font-size:14.5px; box-shadow:0 8px 28px rgba(30,50,40,.16);}
  /* 往上開的版本(2026-08-17):月曆最後一排的名字,浮窗往下會掉出畫面外 —— 由 CHIP_POP_JS
     的 twPlaceChipPop 在打開當下量測後決定要不要加上這個 class。 */
  .chip-pop.pop-up{top:auto; bottom:100%; margin-top:0; margin-bottom:4px;}
  .chip-pop div{padding:2px 0;}
  .legend{display:flex; gap:12px; flex-wrap:wrap; font-size:14px; color:var(--ink2); margin:12px 2px; align-items:center;}
  .legend .chip{padding:1px 8px; cursor:default;}
  .xmark{position:absolute; right:8px; bottom:6px; font-size:13px; color:#B9BFB6; font-weight:700; letter-spacing:.1em;}
  .empty-hint{background:var(--pine-tint); border:1px solid #CBE2D6; color:var(--pine-deep); border-radius:10px; padding:12px 16px; font-size:15px; margin-bottom:14px;}

  /* ===== 核准工作台側欄 + 調假面板(對齊 mockup .sched-grid/.side/.req/.impact)===== */
  .sched-grid{display:grid; grid-template-columns:1fr 320px; gap:18px; align-items:start;}
  @media(max-width:980px){ .sched-grid{grid-template-columns:1fr;} }
  .side{position:sticky; top:16px;}
  .side .card{padding:16px;}
  .side h3{font-size:15px; font-weight:700; letter-spacing:.06em; color:var(--ink2); margin-bottom:10px;}
  .req{border:1px solid var(--line); border-radius:9px; padding:9px 11px; margin-bottom:8px;}
  .req .who{font-weight:700; font-size:15.5px; display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
  .req .meta, .req .what{font-size:14.5px; color:var(--ink2); margin:2px 0 6px;}
  .req .reason{font-size:14.5px; color:var(--ink2); margin-bottom:8px;}
  .impact{font-size:13.5px; border-radius:6px; padding:4px 8px; margin:3px 0 8px; font-weight:600; display:flex; justify-content:space-between; gap:8px 8px; align-items:center; flex-wrap:wrap;}
  .impact.ok{background:var(--pine-tint); color:var(--pine-deep);}
  .impact.warn{background:var(--brass-tint); color:#8A6516;}
  .impact.full{background:var(--danger-tint); color:var(--danger);}
  /* 「這天另有 N 筆待核准」(2026-08-17):與「核准後 N/M」不同層次的資訊,獨佔一行
     才不會被 space-between 推到旁邊看不見;字級比上一行大一點,因為它是比較容易踩到的那個坑。 */
  .impact-queue{flex-basis:100%; font-size:14.5px; font-weight:600; padding-top:3px; border-top:1px solid rgba(0,0,0,.08);}
  .impact-queue b{font-size:16px;}
  .req .row-actions{display:flex; gap:6px; margin-top:2px; flex-wrap:wrap; align-items:center;}
  .req .row-actions form{display:inline-flex; gap:4px; align-items:center;}
  .req .row-actions input[type=text]{width:104px; padding:5px 8px; font-size:14px;}
  .req .row-actions .btn{padding:5px 10px; font-size:14px;}
  .group-daylist{border-top:1px dashed var(--line); margin-top:8px; padding-top:8px;}
  .group-daylist .dayrow{display:flex; justify-content:space-between; align-items:center; font-size:14px; padding:3px 0;}
  .stat-row{display:flex; justify-content:space-between; align-items:center; font-size:14.5px; padding:3px 0;}
  /* 逐人統計表:名字 / 總天數 / 細項 三欄對齊。用 grid + display:contents,
     數字才會排成一直行 —— 靠 space-between 推到右邊會因細項長短不一而參差。 */
  .leave-stats{display:grid; grid-template-columns:auto max-content 1fr; column-gap:12px; row-gap:5px; align-items:baseline; font-size:14.5px;}
  .leave-stats .ls-row{display:contents;}
  .leave-stats .ls-name{white-space:nowrap;}
  .leave-stats .ls-total{text-align:right; white-space:nowrap; font-weight:700; font-variant-numeric:tabular-nums;}
  .leave-stats .ls-detail{color:var(--ink2); font-variant-numeric:tabular-nums;}
  .empty-side{padding:26px 16px; text-align:center; color:var(--ink2); font-size:15px;}
  .adjust-panel{border:1px solid #EAD9AE; background:var(--brass-tint); border-radius:10px; padding:16px; margin-bottom:16px;}
  .adjust-panel .picks{display:flex; flex-wrap:wrap; gap:8px; margin:10px 0;}
  .adjust-panel .pick{display:flex; align-items:center; gap:6px; background:var(--surface); border:1px solid var(--line); border-radius:8px; padding:6px 10px; font-size:14.5px;}

  /* ===== 申請表單(modal 卡片,對齊 mockup 畫面2)===== */
  .req-forms{display:grid; grid-template-columns:repeat(auto-fit,minmax(320px,1fr)); gap:18px; align-items:start; margin-top:20px;}
  .modal{border:1px solid var(--line); border-radius:14px; background:var(--surface); padding:20px;}
  .modal h3{font-size:17px; font-weight:700; margin-bottom:4px;}
  .modal .sub{font-size:14.5px; color:var(--ink2); margin-bottom:12px;}
  /* 假別選項:2 欄 grid(手機上不能整屏肥,owner 回報);5th(公假,僅 admin)按正常 grid flow
     排在第 3 列第 1 格,不特別跨欄。 */
  .opt-grid{display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-bottom:8px;}
  /* .opt 假別選項:dot+標題同一行、desc 在下方一行,input 視覺隱藏但保留(:has 判斷/表單語意)。 */
  .opt{display:flex; flex-direction:column; justify-content:center; gap:2px; min-height:44px;
    border:1.5px solid var(--line); border-radius:10px; padding:8px 10px; margin-bottom:0; cursor:pointer;}
  .opt:has(input:checked){border-color:var(--pine); background:var(--pine-tint);}
  .opt input[type=radio]{position:absolute; width:1px; height:1px; opacity:0; pointer-events:none;}
  .opt .row1{display:flex; align-items:center; gap:8px;}
  .opt .dot{width:10px; height:10px; border-radius:99px; flex:none;}
  .opt .t{font-weight:700; font-size:15.5px; overflow-wrap:anywhere;}
  .opt .d{font-size:12.5px; color:var(--ink2); overflow-wrap:anywhere; margin-left:18px;}
  .opt .d:empty{display:none;}
  /* 手機:假別選項改單欄直排(2026-07-27 老闆回報:並排太小按不準),字再放大、格子更好按。
     員工幾乎全在手機用,這裡的可點面積直接影響排休體驗。 */
  @media(max-width:640px){
    .opt-grid{grid-template-columns:1fr; gap:10px;}
    .opt{padding:12px 14px; min-height:52px;}
    .opt .t{font-size:17px;}
    .opt .d{font-size:13.5px;}
  }

  /* ===== 面板改真彈窗(POS 確認對話框風格):遮罩置中卡片,手機變底部抽屜 ===== */
  .modal-backdrop{
    position:fixed; inset:0; background:rgba(25,32,28,.45); z-index:50;
    display:flex; align-items:center; justify-content:center; padding:16px;
    animation:mb-fade .18s ease;
  }
  .modal-card{
    background:var(--surface); border-radius:16px; max-width:420px; width:100%;
    max-height:85vh; overflow-y:auto; padding:16px; box-shadow:0 20px 60px rgba(20,30,25,.3);
    animation:mc-in .18s ease;
  }
  .modal-card h3{font-size:17px;}
  @keyframes mb-fade{from{opacity:0}to{opacity:1}}
  @keyframes mc-in{from{opacity:0; transform:translateY(16px)}to{opacity:1; transform:translateY(0)}}
  @media(max-width:640px){
    .modal-backdrop{align-items:flex-end; padding:0;}
    .modal-card{border-radius:16px 16px 0 0; max-width:none; padding-top:10px; max-height:70vh;}
    .modal-card::before{content:""; display:block; width:40px; height:4px; border-radius:99px; background:var(--line); margin:0 auto 14px;}
  }
  @media(prefers-reduced-motion:reduce){
    .modal-backdrop,.modal-card{animation:none;}
  }

  /* ===== 統計(計畫三 Task 6)===== */
  .stat-cards{display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:18px;}
  @media(max-width:820px){ .stat-cards{grid-template-columns:repeat(2,1fr);} }
  .heat-table td.heat{text-align:center; font-weight:700; font-size:14.5px; padding:0;}
  .heat-table td.heat a{color:inherit; text-decoration:none; display:block; padding:11px 6px;}
  .hm0{background:#F4F5F1; color:#B9BFB6;}
  .hm1{background:#EAF3EE; color:var(--pine-deep);}
  .hm2{background:#D8E9DF; color:var(--pine-deep);}
  .hm3{background:#C2DECE; color:var(--pine-deep);}

  /* 上方:置中標題列(黏頂),左側可選 ← 上一頁;不渲染桌面頂列/subnav/齒輪那整塊。 */
  .line-head{
    position:sticky; top:0; z-index:20; background:var(--surface); border-bottom:1px solid var(--line);
    display:flex; align-items:center; justify-content:center; gap:8px; padding:12px 46px; min-height:52px;
  }
  .line-head .line-title{
    font-size:18px; font-weight:700; color:var(--ink); text-align:center;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%;
  }
  .line-head .line-back{
    position:absolute; left:6px; top:50%; transform:translateY(-50%);
    display:flex; align-items:center; justify-content:center; width:38px; height:38px;
    font-size:23px; color:var(--pine-deep); text-decoration:none; border-radius:10px;
  }
  .line-head .line-back:active{background:var(--pine-tint);}
  /* 中間:沿用松綠卡片式 body,只收窄 + 預留底部 tab bar 高度避免被蓋住。 */
  .line-wrap{max-width:560px; padding:18px 16px calc(80px + env(safe-area-inset-bottom));}
  /* 下方:固定底部 5 格 tab bar(松綠),當前頁高亮。 */
  .line-tabbar{
    position:fixed; left:0; right:0; bottom:0; z-index:30; display:flex;
    background:var(--surface); border-top:1px solid var(--line);
    padding-bottom:env(safe-area-inset-bottom); box-shadow:0 -2px 12px rgba(30,50,40,.06);
  }
  .line-tab{
    flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
    padding:8px 2px 9px; min-height:56px; text-decoration:none; color:var(--ink2); font-size:13px; font-weight:600;
  }
  .line-tab .ic{font-size:22px; line-height:1;}
  .line-tab.on{color:var(--pine-deep);}
  .line-tab:active{background:var(--pine-tint);}
  /* 「更多」頁 icon grid(3 欄卡片) */
  .more-sec{margin-bottom:22px;}
  .more-sec h3{font-size:14px; font-weight:700; color:var(--ink2); letter-spacing:.08em; margin:0 2px 10px;}
  .more-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:10px;}
  .more-item{
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px;
    background:var(--surface); border:1px solid var(--line); border-radius:14px; padding:16px 8px;
    text-decoration:none; color:var(--ink); text-align:center;
  }
  .more-item .ic{
    width:44px; height:44px; border-radius:12px; background:var(--pine-tint);
    display:flex; align-items:center; justify-content:center; font-size:24px;
  }
  .more-item .lb{font-size:14.5px; font-weight:600; line-height:1.3;}
  .more-item:active{border-color:var(--pine); background:#FAFBF8;}
  .more-logout{display:block; text-align:center; margin-top:4px; padding:14px; color:var(--danger); font-size:15.5px; font-weight:600; text-decoration:none;}
