:root{
    --bg:#EEF1F4;
    --surface:#FFFFFF;
    --surface-2:#FAFBFC;
    --border:#DDE1E6;
    --border-strong:#C3C9D1;
    --text:#1B2430;
    --text-secondary:#5B6472;
    --text-muted:#8A93A1;
    --accent:#0F6E56;
    --accent-light:#E1F2ED;
    --accent-dark:#095141;
    --warning:#B5720F;
    --warning-bg:#FBF0DB;
    --success:#1E7A3D;
    --success-bg:#E5F4E9;
    --danger:#B23A34;
    --danger-bg:#FBEAE9;
    --radius:12px;
    --font:ui-rounded,"SF Pro Rounded",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    --shadow:0 1px 2px rgba(27,36,48,.05), 0 1px 6px rgba(27,36,48,.04);
  }
  *{box-sizing:border-box;}
  select, option{
    font-family:var(--font);
    font-size:13px;
  }
  body{
    margin:0;
    font-family:var(--font);
    background:var(--bg);
    color:var(--text);
    font-size:14px;
    line-height:1.5;
  }
  .brand{display:flex;gap:14px;align-items:center;}
  .brand-logo{height:58px;width:auto;flex:0 0 auto;margin:-8px 0;}
  .auth-logo{height:84px;width:auto;max-width:100%;object-fit:contain;display:block;margin:0 auto 10px;}
  .app{width:100%;min-width:0;margin:0 auto;padding:24px 32px 60px;}
  header.top{margin-bottom:14px;}
  header.top h1{font-size:20px;font-weight:600;margin:0 0 2px;}
  header.top p{margin:0;color:var(--text-secondary);font-size:13px;}

  .tabs{display:flex;gap:6px;margin-bottom:18px;border-bottom:1px solid var(--border);overflow-x:auto;scrollbar-width:thin;}
  .tab-btn{
    padding:9px 16px;font-size:13px;font-weight:500;background:none;border:none;cursor:pointer;
    color:var(--text-secondary);border-bottom:2px solid transparent;margin-bottom:-1px;font-family:inherit;
    display:flex;align-items:center;gap:6px;flex:0 0 auto;white-space:nowrap;
  }
  .tab-btn.active{color:var(--accent-dark);border-bottom-color:var(--accent);}
  .tab-count{background:var(--warning-bg);color:var(--warning);font-size:11px;font-weight:600;padding:1px 7px;border-radius:100px;}

  .view{display:none;}
  .view.active{display:block;}

  .cards{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:20px;}
  .card-stat{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:14px 16px;box-shadow:var(--shadow);min-width:0;}
  #posKpis{grid-template-columns:repeat(3,minmax(0,1fr));}
  @media (min-width:1200px){ #posKpis{grid-template-columns:repeat(6,minmax(0,1fr));} }
  .card-stat .label{font-size:12px;color:var(--text-secondary);margin-bottom:4px;}
  .card-stat .value{font-size:20px;font-weight:600;}

  /* ---- Dashboard hero KPI cards (icon + big value + trend badge) ---- */
  /* Plain-language weekly summary card */
  .wk-card{border:1px solid var(--border);border-radius:14px;background:linear-gradient(180deg,#F3FAF7,var(--surface));padding:18px 20px;}
  .wk-title{font-size:13px;font-weight:800;color:var(--accent);letter-spacing:.02em;margin:0 0 12px;display:flex;align-items:center;gap:8px;}
  .wk-lines{display:flex;flex-direction:column;gap:11px;}
  .wk-line{display:flex;align-items:flex-start;gap:11px;font-size:15px;color:var(--text);line-height:1.4;}
  .wk-line .wk-ic{font-size:19px;line-height:1.25;flex:0 0 auto;}
  .wk-line b{font-weight:800;}
  .wk-chip{display:inline-block;font-size:12px;font-weight:800;padding:1px 8px;border-radius:999px;margin-left:4px;}
  .wk-chip.up{color:#0F9D6E;background:#E1F5EE;}
  .wk-chip.down{color:#D64550;background:#FBE9EA;}
  .wk-chip.flat{color:var(--text-muted);background:var(--border);}
  .wk-muted{color:var(--text-muted);}
  /* Fast approval — Tinder-style swipe stack */
  .ap-batchbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:12px 14px;margin:12px 0;background:var(--accent-light);border:1px solid var(--accent);border-radius:12px;}
  .ap-batchbar .ap-batch-txt{font-weight:700;color:var(--accent-dark,#0F6E56);}
  .ap-deck{max-width:440px;margin:14px auto 4px;}
  .ap-progress{text-align:center;font-size:13px;color:var(--text-secondary);margin-bottom:10px;}
  .ap-dots{display:inline-flex;flex-wrap:wrap;justify-content:center;gap:5px;margin-left:10px;max-width:100%;vertical-align:middle;}
  .ap-dot{width:7px;height:7px;border-radius:50%;background:var(--border);flex:none;}
  .ap-dot.done{background:var(--accent);}
  .ap-dot.cur{background:var(--warning);transform:scale(1.25);}
  /* Slim progress bar used instead of dots when the pending queue is large. */
  .ap-bar{display:inline-block;width:140px;max-width:55%;height:6px;border-radius:100px;background:var(--border);margin-left:10px;overflow:hidden;vertical-align:middle;}
  .ap-bar-fill{display:block;height:100%;background:var(--accent);border-radius:100px;transition:width .2s;}
  .ap-stage{position:relative;min-height:60px;}
  .ap-peek{position:absolute;left:0;right:0;top:0;height:100%;border:1px solid var(--border);border-radius:16px;background:var(--surface);}
  .ap-peek-1{transform:scale(.965) translateY(10px);opacity:.7;}
  .ap-peek-2{transform:scale(.93) translateY(20px);opacity:.4;}
  .ap-swipe-card{position:relative;border:1px solid var(--border);border-radius:16px;background:var(--surface);overflow:hidden;box-shadow:0 6px 22px rgba(16,24,40,.12);touch-action:pan-y;cursor:grab;user-select:none;}
  .ap-swipe-card:active{cursor:grabbing;}
  .ap-stamp{position:absolute;top:16px;z-index:5;font-size:22px;font-weight:900;letter-spacing:.06em;padding:5px 12px;border-radius:8px;border:3px solid;opacity:0;transition:opacity .1s;pointer-events:none;}
  .ap-stamp-yes{left:16px;color:#0F9D6E;border-color:#0F9D6E;transform:rotate(-14deg);}
  .ap-stamp-no{right:16px;color:#D64550;border-color:#D64550;transform:rotate(14deg);}
  .ap-swipe-card.swipe-yes .ap-stamp-yes{opacity:1;}
  .ap-swipe-card.swipe-no .ap-stamp-no{opacity:1;}
  .ap-card-photo{height:180px;background:#f1f3f5 center/cover no-repeat;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-muted);font-size:13px;border-bottom:1px solid var(--border);}
  .ap-card-body{padding:14px 16px;display:flex;flex-direction:column;gap:10px;}
  .ap-card-top{display:flex;justify-content:space-between;align-items:flex-start;gap:10px;}
  .ap-card-supp{font-weight:800;font-size:18px;color:var(--text);line-height:1.2;}
  .ap-card-total{font-weight:800;font-size:19px;color:var(--text);white-space:nowrap;}
  .ap-card-meta{font-size:12px;color:var(--text-muted);margin-top:3px;}
  .ap-card-pills{display:flex;gap:6px;flex-wrap:wrap;}
  .ap-items-scroll{max-height:150px;overflow:auto;border:1px solid var(--border);border-radius:10px;}
  table.ap-items{width:100%;border-collapse:collapse;font-size:13px;}
  table.ap-items th{position:sticky;top:0;background:var(--surface);text-align:left;font-size:11px;color:var(--text-muted);padding:7px 10px;border-bottom:1px solid var(--border);}
  table.ap-items td{padding:7px 10px;border-bottom:1px solid var(--border);}
  table.ap-items tr:last-child td{border-bottom:none;}
  .ap-card-amts{display:flex;justify-content:space-between;font-size:12px;color:var(--text-secondary);}
  .ap-card-notes{font-size:12px;color:var(--text-secondary);}
  .ap-card-notes .k{color:var(--text-muted);}
  .ap-swipe-actions{display:flex;align-items:center;justify-content:center;gap:16px;margin-top:14px;}
  .ap-round{width:60px;height:60px;border-radius:50%;border:none;font-size:26px;font-weight:900;cursor:pointer;color:#fff;box-shadow:0 4px 0 rgba(0,0,0,.12);transition:transform .05s;display:inline-flex;align-items:center;justify-content:center;flex:none;line-height:1;padding:0;}
  .ap-round:active{transform:translateY(3px);box-shadow:0 1px 0 rgba(0,0,0,.12);}
  .ap-round.yes{background:#0F9D6E;}
  .ap-round.no{background:#D64550;}
  .ap-skip{background:transparent;color:var(--text-muted);border:1px solid var(--border);}
  .ap-swipe-hint{text-align:center;font-size:11px;color:var(--text-muted);margin-top:8px;}
  .ap-reject{display:none;flex-direction:column;gap:8px;max-width:440px;margin:12px auto 0;}
  .ap-reject.active{display:flex;}
  .ap-reject textarea{width:100%;border:1px solid var(--border);border-radius:8px;padding:8px;font:inherit;resize:vertical;}
  .reason-label{font-size:12px;font-weight:700;color:var(--text-secondary);}
  .reason-chips{display:flex;flex-wrap:wrap;gap:8px;}
  .reason-chip{background:var(--surface);border:1px solid var(--danger,#D64550);color:var(--danger,#D64550);border-radius:999px;padding:7px 13px;font:inherit;font-size:13px;font-weight:600;cursor:pointer;}
  .reason-chip:active{transform:translateY(1px);}
  .reason-chip:hover{background:var(--danger-bg);}
  .ap-done{text-align:center;padding:40px 16px;color:var(--text-secondary);}
  .ap-done-emoji{font-size:44px;}
  .ap-done-title{font-weight:800;font-size:18px;color:var(--text);margin:8px 0 4px;}
  .ap-done-sub{font-size:13px;margin-bottom:14px;}
  /* Live peso echo under amount inputs — helps catch magnitude typos */
  .amount-echo{min-height:20px;margin-top:5px;font-weight:800;font-size:16px;color:var(--accent);font-variant-numeric:tabular-nums;}
  .amount-echo .in-words{display:block;font-weight:500;font-size:11px;color:var(--text-muted);text-transform:capitalize;margin-top:1px;}
  /* Dashboard "needs your attention" nudge cards */
  .nudge-wrap{border:1px solid var(--warning-bg);background:linear-gradient(180deg,#FFFBF2,var(--surface));border-radius:14px;padding:14px 16px;}
  .nudge-title{font-size:13px;font-weight:800;color:var(--warning);letter-spacing:.02em;margin:0 2px 10px;display:flex;align-items:center;gap:7px;}
  .nudge-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px;}
  .nudge{display:flex;align-items:center;gap:13px;text-align:left;background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:13px 15px;cursor:pointer;font:inherit;box-shadow:0 2px 0 var(--border);transition:transform .05s;}
  .nudge:hover{border-color:var(--accent);}
  .nudge:active{transform:translateY(2px);box-shadow:0 0 0 var(--border);}
  .nudge-ic{font-size:24px;line-height:1;flex:0 0 auto;}
  .nudge-txt{flex:1;min-width:0;}
  .nudge-main{display:block;font-weight:700;color:var(--text);font-size:15px;line-height:1.25;}
  .nudge-sub{display:block;font-size:12px;color:var(--text-muted);margin-top:3px;}
  .nudge-go{font-size:18px;color:var(--accent);font-weight:800;flex:0 0 auto;}
  /* Today's close checklist */
  .cl-wrap{border:1px solid var(--border);background:var(--surface);border-radius:14px;padding:14px 16px;}
  .cl-title{font-size:13px;font-weight:800;color:var(--text);letter-spacing:.02em;margin:0 2px 10px;display:flex;align-items:center;gap:7px;}
  .cl-title span{font-weight:500;color:var(--text-muted);}
  .cl-row{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:12px 14px;cursor:pointer;font:inherit;margin-top:8px;transition:transform .05s;}
  .cl-row:hover{border-color:var(--accent);}
  .cl-row:active{transform:translateY(1px);}
  .cl-row.done{background:var(--success-bg,#ecfdf5);cursor:default;}
  .cl-row.done:hover{border-color:var(--border);}
  .cl-check{font-size:20px;line-height:1;flex:0 0 auto;}
  .cl-txt{flex:1;min-width:0;}
  .cl-txt b{display:block;font-weight:700;color:var(--text);font-size:15px;line-height:1.25;}
  .cl-txt small{display:block;font-size:12px;color:var(--text-muted);margin-top:2px;}
  .cl-row.done .cl-txt b{color:var(--success,#059669);}
  .cl-go{font-size:18px;color:var(--accent);font-weight:800;flex:0 0 auto;}
  .cl-alldone{margin-top:10px;text-align:center;font-weight:700;color:var(--success,#059669);font-size:15px;}
  .emp-name-cell{display:inline-flex;align-items:center;gap:9px;}
  .emp-avatar-img{border-radius:50%;object-fit:cover;flex:0 0 auto;background:var(--bg);border:1px solid var(--border);}
  .emp-avatar-fallback{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;flex:0 0 auto;background:var(--accent-soft,#e0f2f1);color:var(--accent,#0d9488);font-weight:800;line-height:1;}
  .kpi-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:16px;margin-bottom:18px;}
  .kpi{
    background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:18px 18px 16px;
    box-shadow:0 1px 2px rgba(16,24,40,.04),0 4px 14px rgba(16,24,40,.05);
    min-width:0;   /* let cards shrink to their grid track so the row never overflows */
  }
  .kpi-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;}
  .kpi-label{font-size:13px;color:var(--text-secondary);font-weight:500;}
  .kpi-ic{width:40px;height:40px;border-radius:11px;display:flex;align-items:center;justify-content:center;flex:0 0 auto;}
  .kpi-ic svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;}
  .kpi-value{font-size:27px;font-weight:700;letter-spacing:-.02em;line-height:1.1;color:var(--text);}
  .kpi-foot{display:flex;align-items:center;gap:8px;margin-top:9px;}
  .kpi-trend{display:inline-flex;align-items:center;gap:3px;font-size:12px;font-weight:700;padding:3px 9px;border-radius:20px;white-space:nowrap;}
  .kpi-trend.up{background:var(--success-bg);color:var(--success);}
  .kpi-trend.down{background:var(--danger-bg);color:var(--danger);}
  .kpi-trend.flat{background:var(--surface-2);color:var(--text-secondary);}
  .kpi-note{font-size:12px;color:var(--text-muted);}
  /* Reusable on/off switch (e.g. Income Statement "Easy mode"). */
  .switch{position:relative;display:inline-flex;align-items:center;gap:9px;cursor:pointer;font-size:13px;font-weight:600;color:var(--text);user-select:none;}
  .switch input{position:absolute;opacity:0;width:0;height:0;}
  .switch .track{width:40px;height:23px;border-radius:20px;background:var(--border-strong,#cbd5e1);transition:background .2s;flex:none;position:relative;}
  .switch .track::after{content:"";position:absolute;top:2px;left:2px;width:19px;height:19px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);transition:transform .2s;}
  .switch input:checked + .track{background:var(--accent,#0d9488);}
  .switch input:checked + .track::after{transform:translateX(17px);}
  /* Sales Trend + Top Categories: let each panel shrink to its grid track so the
     row can't overflow (a wide table then scrolls inside its own panel). */
  #dashSalesRow > .panel{min-width:0;}
  /* Softer, more modern cards just on the dashboard (scoped — app is unchanged). */
  #view-overview .panel{border-radius:18px;box-shadow:0 1px 2px rgba(16,24,40,.04),0 4px 14px rgba(16,24,40,.05);}

  .panel{background:var(--surface);border:1px solid var(--border);border-radius:16px;margin-bottom:16px;box-shadow:var(--shadow);}
  /* Dashboard: Needs Attention + My Tasks + Team Tasks as three aligned boxes.
     auto-fit collapses empty tracks so a Customize-hidden panel doesn't leave a
     gap; tops align via align-items:start. Stacks to one column on phones. */
  .dash-tasks-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:16px;align-items:stretch;margin-bottom:16px;
    /* ONE list height for every card in this row. Declared once because the
       Needs Attention table scrolls itself while the other three scroll via
       .panel-body — two separate mechanisms that must agree, or the cards go
       back to being different heights. */
    --dash-list-h:360px;}
  /* Stretch all three boxes to equal height. Lists start at the top; only the
     empty-state message centers itself in the taller box (margin:auto). */
  .dash-tasks-row > .panel{margin:0;min-width:0;overflow-x:auto;display:flex;flex-direction:column;}
  .dash-tasks-row > .panel > .panel-body{flex:1 1 auto;display:flex;flex-direction:column;justify-content:flex-start;
    max-height:var(--dash-list-h);overflow-y:auto;}
  .dash-tasks-row > .panel > .panel-body > .empty{margin-top:auto;margin-bottom:auto;}
  /* Needs Attention: each alert is a compact card (item title on top, then
     source · priority · action on one line). Applied at ALL widths because the
     box is only ~1/3 the row in the 3-up layout, so the 4-column table would be
     cramped even on a wide screen. The list scrolls inside a capped height so a
     long run of alerts doesn't make the box tower over the tasks beside it. */
  table.records.na-table{min-width:0;display:block;max-height:var(--dash-list-h);overflow-y:auto;}
  .records.na-table thead{display:none;}
  .records.na-table tbody{display:block;}
  .records.na-table tbody tr{
    display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;
    padding:11px 14px;border-bottom:1px solid var(--border);
  }
  .records.na-table tbody tr:last-child{border-bottom:none;}
  .records.na-table tbody td{border:none;padding:0;}
  .records.na-table td[data-label="Item"]{flex:1 0 100%;font-weight:600;font-size:13.5px;color:var(--text);line-height:1.35;}
  .records.na-table td[data-label="Source"]{font-size:12.5px;color:var(--text-secondary);}
  .records.na-table td.na-action{margin-left:auto;white-space:nowrap;}
  .records.na-table td.na-action .link-btn{font-size:13px;font-weight:600;}
  .panel-header{padding:12px 16px;border-bottom:1px solid var(--border);font-weight:600;font-size:14px;display:flex;justify-content:space-between;align-items:center;}
  .panel-body{padding:16px;}
  .panel-title{display:inline-flex;align-items:center;gap:8px;cursor:pointer;user-select:none;}
  .panel-title .caret{font-size:10px;color:var(--text-secondary);transition:transform .15s;display:inline-block;line-height:1;}
  .panel.collapsed .panel-title .caret{transform:rotate(-90deg);}
  .panel.collapsed > *:not(.panel-header){display:none !important;}
  .panel.collapsed .panel-header{border-bottom:none;}
  /* Costing: collapsible ingredient category group headers */
  tr.cost-cat-row td{background:var(--surface-alt,#f3f4f6);font-weight:600;font-size:12.5px;cursor:pointer;user-select:none;padding:8px 12px;color:var(--text-secondary);}
  tr.cost-cat-row:hover td{background:var(--border,#e5e7eb);}
  tr.cost-cat-row .caret{display:inline-block;width:12px;font-size:10px;color:var(--text-muted);}
  /* Ron Assist chat */
  .ron-msgs{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:14px;}
  .ron-msg{max-width:82%;padding:10px 14px;border-radius:14px;font-size:14px;line-height:1.55;white-space:normal;word-wrap:break-word;}
  .ron-msg.user{align-self:flex-end;background:var(--brand,#16603a);color:#fff;border-bottom-right-radius:4px;}
  .ron-msg.bot{align-self:flex-start;background:var(--surface-alt,#f3f4f6);color:var(--text-primary,#111);border-bottom-left-radius:4px;}
  .ron-msg.bot p{margin:6px 0;} .ron-msg.bot ul{margin:6px 0;padding-left:20px;} .ron-msg.bot li{margin:3px 0;}
  .ron-msg.bot h4{margin:10px 0 4px;font-size:14px;} .ron-msg.bot strong{font-weight:700;}
  .ron-msg.typing{color:var(--text-secondary);font-style:italic;}
  .ron-empty{margin:auto;text-align:center;color:var(--text-secondary);max-width:520px;}
  .ron-chip{display:inline-block;margin:5px;padding:8px 12px;border:1px solid var(--border-strong);border-radius:20px;font-size:13px;cursor:pointer;background:var(--surface);}
  .ron-chip:hover{background:var(--surface-alt,#f3f4f6);}
  .ron-inputbar{display:flex;gap:8px;padding:12px 16px;border-top:1px solid var(--border);align-items:flex-end;}
  .ron-inputbar textarea{flex:1;resize:none;max-height:140px;padding:10px 12px;border:1px solid var(--border-strong);border-radius:10px;font-family:inherit;font-size:14px;line-height:1.4;}
  .ron-disclaimer{padding:0 16px 10px;font-size:11px;color:var(--text-muted);text-align:center;}

  .grid-fields{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;}
  .field label{display:block;font-size:12px;color:var(--text-secondary);margin-bottom:4px;font-weight:500;}
  /* Checkbox/radio must be excluded — otherwise a checkbox inside a .field
     (e.g. the AI-draft document-context checklist) gets stretched to a
     full-width bordered box, shoving its label off to the side. */
  .field input:not([type="checkbox"]):not([type="radio"]), .field select, .field textarea{
    width:100%;padding:8px 10px;border:1px solid var(--border-strong);border-radius:var(--radius);
    font-size:13px;font-family:inherit;background:var(--surface);color:var(--text);
  }
  .field input:not([type="checkbox"]):not([type="radio"]):focus, .field select:focus, .field textarea:focus{
    outline:none;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-light);
  }
  /* Public customer reservation form: force every control to fit narrow phones.
     iOS date/time inputs have an intrinsic min-width that ignores width:100% and
     overflows — appearance:none + min-width:0 fixes it. */
  #publicResvView input, #publicResvView select, #publicResvView textarea{
    width:100%;max-width:100%;min-width:0;box-sizing:border-box;
  }
  #publicResvView input[type="date"], #publicResvView input[type="time"]{
    -webkit-appearance:none;appearance:none;min-height:48px;
  }
  .cf-wallet-row{display:grid;grid-template-columns:1fr 140px 140px;gap:12px;align-items:center;padding:6px 0;border-bottom:1px solid var(--border);}
  .cf-wallet-row:last-child{border-bottom:none;}
  .cf-wallet-row > span:first-child{font-size:13px;color:var(--text);}
  .cf-wallet-row input{padding:7px 9px;border:1px solid var(--border-strong);border-radius:var(--radius);font-size:13px;font-family:inherit;background:var(--surface);color:var(--text);}
  .cf-wallet-row input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-light);}
  .cf-wallet-head span{font-size:11px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-secondary);font-weight:600;}
  .cf-wallet-head span:not(:first-child){text-align:left;padding-left:2px;}
  .att-cell{
    width:32px;height:28px;padding:0;border:1px solid var(--border);border-radius:6px;
    background:var(--surface);cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;
    color:var(--text-muted);text-align:center;line-height:1;
  }
  .att-cell:hover{border-color:var(--accent);}
  .att-cell.P{background:var(--success-bg);color:var(--success);border-color:transparent;}
  .att-cell.H{background:var(--warning-bg);color:var(--warning);border-color:transparent;}
  .att-cell.A{background:var(--danger-bg);color:var(--danger);border-color:transparent;}
  .att-cell.L{background:var(--accent-light);color:var(--accent-dark);border-color:transparent;}
  .att-cell.R{background:var(--surface-2);color:var(--text-muted);border-color:transparent;}
  /* Read off the Schedule rather than marked by anyone: a rostered rest day,
     and a rostered work day still waiting for its mark. Dashed = an
     expectation, so it never reads as a real mark or earns a day credit. */
  .att-cell.derived{background:var(--surface-2);color:var(--text-muted);border:1px dashed var(--border-strong);}
  .att-cell.rostered{border:1px dashed var(--accent);color:var(--accent);opacity:.65;}
  #attTable td{padding:4px 3px;}
  #attTable th{white-space:nowrap;}

  .encode-scroll{max-height:430px;overflow-y:auto;}
  /* Fixed layout + percentage column widths (set on the thead) so the text
     dropdowns (Category, Department, Type) get room to show their full value
     instead of being squeezed to a fixed px width that truncated them.
     Overridden to a stacked card layout on phones (see the mobile block). */
  table.encode{width:100%;border-collapse:collapse;font-size:13px;table-layout:fixed;}
  table.encode select{text-overflow:ellipsis;}
  table.encode th{
    text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.03em;
    color:var(--text-secondary);font-weight:600;padding:8px 8px;
    background:var(--surface-2);
    position:sticky;top:0;z-index:2;box-shadow:0 1px 0 var(--border);
  }
  table.encode td{padding:4px 6px;border-bottom:1px solid var(--border);vertical-align:middle;}
  table.encode input, table.encode select{
    width:100%;border:1px solid transparent;background-color:transparent;padding:6px 4px;font-size:13px;
    border-radius:4px;font-family:inherit;color:var(--text);
  }
  /* Compact custom dropdown chevron: the native select arrow reserves ~35px,
     which truncated even short values (OPEX, kg) in the packed item table.
     Replacing it reclaims that width so column values fit. */
  table.encode select{
    -webkit-appearance:none;appearance:none;padding-right:16px;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%2390969E' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
    background-repeat:no-repeat;background-position:right 4px center;background-size:9px;
  }
  table.encode input:hover, table.encode select:hover{border-color:var(--border-strong);background-color:var(--surface);}
  table.encode input:focus, table.encode select:focus{outline:none;border-color:var(--accent);background-color:var(--surface);box-shadow:0 0 0 2px var(--accent-light);}
  table.encode input.qty, table.encode input.price, table.encode input.total{text-align:right;}
  table.encode input.total{font-weight:600;}
  table.encode td.num{width:90px;}
  table.encode td.uom{width:80px;}
  td.rowdel{width:34px;text-align:center;}
  .cellfill{display:flex;align-items:center;gap:2px;}
  .cellfill > select, .cellfill > input{flex:1 1 auto;min-width:0;}
  .fill-btn{
    flex:0 0 auto;border:1px solid transparent;background:transparent;color:var(--text-muted);
    cursor:pointer;font-size:12px;line-height:1;padding:5px 5px;border-radius:4px;
  }
  .fill-btn:hover{background:var(--accent-light);color:var(--accent-dark);}

  /* Photo-scan "confirm or change" affordance on encode rows. Category, type
     and department filled from the receipt photo get an amber cue so the
     encoder reviews rather than trusts blindly. The field stays fully editable;
     touching it clears the cue (updateRow drops the scanned flag + re-renders). */
  .cellfill.scanned{
    background:var(--warning-bg);border-radius:4px;
    box-shadow:inset 2px 0 0 var(--warning);padding-left:2px;
  }
  .cellfill.scanned > select{background-color:transparent;}
  /* Item-List locked classification: calm green, clearly "settled". */
  .cellfill.fromlist{
    background:var(--success-bg);border-radius:4px;
    box-shadow:inset 2px 0 0 var(--success);padding-left:2px;
  }
  .cellfill.fromlist > select{background-color:transparent;}
  .scan-hint.lock{color:var(--success);border-color:var(--success);}
  .scan-hint.req{color:var(--warning);border-color:var(--warning);}
  .scan-hint{
    flex:0 0 auto;font-size:10px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;
    color:var(--warning);background:var(--surface);border:1px solid var(--warning);
    border-radius:3px;padding:1px 4px;line-height:1.3;cursor:default;user-select:none;
  }
  .req-item{width:100%;}
  .req-note{font-size:11px;color:var(--text-muted);margin-top:3px;line-height:1.35;}
  .req-note a{color:var(--accent);text-decoration:underline;cursor:pointer;}

  .icon-btn{
    width:26px;height:26px;border-radius:4px;border:1px solid transparent;background:transparent;
    color:var(--text-muted);cursor:pointer;font-size:15px;line-height:1;display:inline-flex;align-items:center;justify-content:center;
  }
  .icon-btn:hover{background:var(--danger-bg);color:var(--danger);border-color:var(--danger-bg);}

  .row-actions{display:flex;gap:8px;padding:10px 16px;border-top:1px solid var(--border);background:var(--surface-2);}

  /* Chunky "press" buttons: a solid bottom edge that depresses on tap —
     friendly and obviously tappable, sized to still fit dense tables. */
  .btn{
    padding:9px 16px;border-radius:12px;border:1.5px solid var(--border-strong);background:var(--surface);
    color:var(--text);font-size:13.5px;font-weight:700;cursor:pointer;font-family:inherit;
    box-shadow:0 3px 0 var(--border-strong);transition:transform .05s ease,box-shadow .05s ease,filter .1s ease;
    /* Kill mobile double-tap-to-zoom and the ~300ms tap delay on buttons
       (matters most for fast taps on the kiosk PIN pad). */
    touch-action:manipulation;-webkit-tap-highlight-color:transparent;user-select:none;
  }
  .btn:hover{background:var(--surface-2);}
  .btn:active{transform:translateY(3px);box-shadow:0 0 0 var(--border-strong);}
  .btn-primary{background:var(--accent);border-color:var(--accent-dark);color:#fff;box-shadow:0 3px 0 var(--accent-dark);}
  .btn-primary:hover{background:var(--accent);filter:brightness(1.04);}
  .btn-primary:active{transform:translateY(3px);box-shadow:0 0 0 var(--accent-dark);}
  .btn-danger{background:var(--danger);border-color:#8f2e29;color:#fff;box-shadow:0 3px 0 #8f2e29;}
  .btn-danger:hover{filter:brightness(1.04);}
  .btn-danger:active{transform:translateY(3px);box-shadow:0 0 0 #8f2e29;}
  .btn-sm{padding:6px 11px;font-size:12px;box-shadow:0 2.5px 0 var(--border-strong);}
  .btn-sm.btn-primary{box-shadow:0 2.5px 0 var(--accent-dark);}
  .btn-sm:active{transform:translateY(2.5px);}
  /* Guided "record money" wizard — themed by direction: green in, amber out */
  #quickModal{--qk-accent:var(--accent)}
  #quickModal.qk-out{--qk-accent:var(--warning)}
  #quickModal.qk-out .btn-primary{background:var(--warning);border-color:#8a5a0c;color:#fff}
  .qk-amount{font-size:40px;font-weight:800;text-align:center;color:var(--qk-accent);padding:6px 0;font-variant-numeric:tabular-nums}
  .qk-pad{display:grid;grid-template-columns:repeat(3,1fr);gap:9px;margin:8px 0 14px}
  .qk-key{height:54px;border-radius:14px;border:1.5px solid var(--border-strong);background:var(--surface);color:var(--text);
          font-family:inherit;font-size:21px;font-weight:800;cursor:pointer;box-shadow:0 3px 0 var(--border-strong);
          touch-action:manipulation;-webkit-tap-highlight-color:transparent}
  .qk-key:active{transform:translateY(3px);box-shadow:0 0 0 var(--border-strong)}
  .qk-opt{display:flex;align-items:center;gap:12px;width:100%;text-align:left;padding:14px;border-radius:14px;border:2px solid var(--border);
          background:var(--surface);cursor:pointer;font-family:inherit;box-shadow:0 3px 0 var(--border);margin-bottom:9px;
          touch-action:manipulation;-webkit-tap-highlight-color:transparent}
  .qk-opt:active{transform:translateY(3px);box-shadow:0 0 0 var(--border)}
  .qk-opt.sel{border-color:var(--qk-accent);background:var(--accent-light)}
  #quickModal.qk-out .qk-opt.sel{background:var(--warning-bg,#fdf3e2)}
  .qk-opt .qk-ic{font-size:22px;flex:none}
  .qk-opt .qk-t{font-weight:800;font-size:15px}
  .qk-opt .qk-s{font-size:12.5px;color:var(--text-secondary)}
  .qk-dot{height:7px;flex:1;border-radius:5px;background:var(--border)}
  .qk-dot.on{background:var(--qk-accent)}

  .totals-bar{display:flex;justify-content:flex-end;gap:24px;padding:12px 16px;border-top:1px solid var(--border);background:var(--surface-2);}
  .totals-bar .item{text-align:right;}
  .totals-bar .item .label{font-size:11px;color:var(--text-secondary);}
  .totals-bar .item .value{font-size:16px;font-weight:600;}

  .notes-row{padding:0 16px 16px;}
  .save-bar{display:flex;justify-content:flex-end;gap:10px;padding:14px 16px;}

  table.records{width:100%;border-collapse:collapse;font-size:13px;}
  table.records th{
    text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-secondary);
    font-weight:600;padding:10px 12px;border-bottom:1px solid var(--border);background:var(--surface-2);
  }
  table.records td{padding:10px 12px;border-bottom:1px solid var(--border);vertical-align:top;}
  table.records tr:last-child td{border-bottom:none;}
  table.records.compact{font-size:12px;}
  table.records.compact td{padding:5px 10px;}
  table.records.compact th{padding:6px 10px;position:sticky;top:0;}
  table.records.compact .badge{padding:2px 8px;font-size:10px;}
  /* Cash entries: scrollable list with a sticky header row. */
  .cf-scroll{max-height:58vh;overflow:auto;}
  #cfEntriesTable thead th{position:sticky;top:0;background:var(--surface-2);z-index:1;}
  .badge{display:inline-block;padding:3px 9px;border-radius:100px;font-size:11px;font-weight:600;white-space:nowrap;}
  .badge.pending{background:var(--warning-bg);color:var(--warning);}
  .badge.approved{background:var(--success-bg);color:var(--success);}
  .badge.rejected{background:var(--danger-bg);color:var(--danger);}
  .badge.info{background:var(--accent-light);color:var(--accent-dark);}
  /* Daily wallets calendar */
  .cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;}
  .cal-dow{text-align:center;font-size:11px;font-weight:600;color:var(--text-muted);padding:4px 0;}
  .cal-day{text-align:center;padding:9px 0;border-radius:var(--radius);font-size:13px;cursor:pointer;border:1px solid transparent;color:var(--text-secondary);}
  .cal-day:hover{border-color:var(--border-strong);}
  .cal-day.moved{background:var(--success-bg);color:var(--success);font-weight:600;}
  .cal-day.neg{background:var(--danger-bg);color:var(--danger);font-weight:600;}
  .cal-day.sel{outline:2px solid var(--accent);outline-offset:-1px;}
  .cal-blank{visibility:hidden;}
  .empty{padding:30px;text-align:center;color:var(--text-muted);font-size:13px;}
  .link-btn{background:none;border:none;color:var(--accent);cursor:pointer;font-size:12px;padding:0;font-family:inherit;font-weight:500;}
  td.acts .link-btn + .link-btn{margin-left:16px;}
  .supplier-link{color:var(--accent);cursor:pointer;font-weight:500;}
  .supplier-link:hover{text-decoration:underline;}
  .link-btn.danger{color:var(--danger);}
  .note-banner{background:var(--warning-bg);color:var(--warning);border-radius:var(--radius);padding:10px 14px;font-size:12px;margin-bottom:16px;}

  .filter-bar{display:flex;gap:6px;padding:12px 16px;border-bottom:1px solid var(--border);align-items:center;flex-wrap:wrap;}
  .filter-btn{padding:5px 12px;border-radius:100px;border:1px solid var(--border-strong);background:var(--surface);font-size:12px;cursor:pointer;color:var(--text-secondary);font-family:inherit;}
  .filter-btn.active{background:var(--accent);border-color:var(--accent);color:#fff;}
  .filter-spacer{flex:1;}
  .approver-field{display:flex;align-items:center;gap:8px;}
  .approver-field label{font-size:12px;color:var(--text-secondary);font-weight:500;}
  .approver-field input{padding:6px 10px;border:1px solid var(--border-strong);border-radius:var(--radius);font-size:12px;font-family:inherit;width:160px;}
  /* Approval detail filters: a tidy responsive grid tucked behind a toggle. */
  .ap-filters{display:grid;grid-template-columns:repeat(auto-fill,minmax(165px,1fr));gap:12px 16px;padding:14px 16px;border-bottom:1px solid var(--border);background:var(--surface-2,transparent);}
  .ap-filters .approver-field{flex-direction:column;align-items:stretch;gap:4px;}
  .ap-filters .approver-field input,.ap-filters .approver-field select{width:100%;box-sizing:border-box;}
  .ap-filters .approver-field.ap-filter-actions{justify-content:flex-end;}
  .ap-summary{display:flex;align-items:flex-start;gap:12px 24px;flex-wrap:wrap;padding:12px 16px;border-bottom:1px solid var(--border);background:var(--surface-2,transparent);}
  /* One band per group (status / by payment / by type). The band is the wrap
     UNIT: it wraps inside itself and the row breaks BETWEEN bands, so a figure
     can never land beside the next band's label and be read as belonging to it.
     Flat siblings in a single wrapping row did exactly that. */
  .ap-summary-section{display:flex;align-items:flex-start;gap:12px 24px;}
  /* The figures wrap; the label does not. min-width:0 lets this shrink inside
     the flex row instead of forcing the strip wider than its panel. */
  .ap-summary-figures{display:flex;align-items:flex-start;gap:12px 24px;flex-wrap:wrap;flex:1 1 auto;min-width:0;}
  .ap-summary-group{display:flex;flex-direction:column;gap:2px;min-width:112px;}
  .ap-summary-label{font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--text-muted);}
  .ap-summary-value{font-size:14px;font-weight:600;color:var(--text-secondary);white-space:nowrap;}
  .ap-summary-headline{min-width:180px;}
  .ap-summary-headline .ap-summary-label{font-size:11px;font-weight:700;color:var(--text-secondary);}
  .ap-summary-headline .ap-summary-value{font-size:18px;font-weight:700;color:var(--text);}
  .ap-summary-marker{font-size:10px;font-weight:400;color:var(--text-muted);}
  .ap-summary-divider{display:flex;align-items:center;align-self:stretch;border-left:1px solid var(--border-strong);padding-left:16px;color:var(--text-muted);font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;}
  .ap-summary-note{flex:1 0 100%;padding:9px 11px;border-radius:var(--radius);background:var(--warning-bg);color:var(--warning);font-size:12px;}
  .filter-count{background:var(--accent);color:#fff;border-radius:100px;padding:1px 7px;font-size:11px;}
  /* Bounded, vertically-scrollable table area with a sticky header. */
  .table-scroll{max-height:65vh;overflow-y:auto;}
  .table-scroll thead th{position:sticky;top:0;background:var(--surface);z-index:2;}

  .detail-row td{background:var(--surface-2);padding:14px 16px;}
  /* Focus the item being reviewed: tint its header row, frame the detail, mute the rest */
  table.records tr.rv-open td{background:var(--accent-light);border-top:2px solid var(--accent);}
  .detail-row.rv-detail > td{
    background:var(--surface);
    border-left:4px solid var(--accent);
    border-bottom:2px solid var(--accent);
    box-shadow:0 8px 22px rgba(20,24,30,0.12);
    padding:18px 20px;
  }
  #approvalBody.rv-focus tr:not(.rv-open):not(.rv-detail){opacity:0.4;transition:opacity .12s;}
  #approvalBody.rv-focus tr:not(.rv-open):not(.rv-detail):hover{opacity:0.8;}
  .detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px;font-size:12px;}
  .detail-grid div span.k{color:var(--text-secondary);display:block;margin-bottom:2px;}
  .detail-items{width:100%;border-collapse:collapse;font-size:12px;margin-bottom:12px;}
  .detail-items th{text-align:left;color:var(--text-secondary);font-weight:600;padding:5px 8px;border-bottom:1px solid var(--border);}
  .detail-items td{padding:5px 8px;border-bottom:1px solid var(--border);}
  .reject-box{display:none;margin-top:10px;}
  .reject-box.active{display:block;}
  .reject-box textarea{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius);padding:8px;font-family:inherit;font-size:12px;margin-bottom:8px;}
  .decision-note{font-size:12px;color:var(--text-secondary);margin-top:8px;}
  .decision-note.rejected{color:var(--danger);}
  .decision-note.approved{color:var(--success);}

  /* Redesigned review detail */
  .rv{font-size:13px;color:var(--text);}
  .rv-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;}
  .rv-supplier{font-size:16px;font-weight:600;}
  .rv-sub{font-size:12px;color:var(--text-secondary);margin-top:3px;}
  .rv-total{font-size:20px;font-weight:600;}
  .rv-head .badge{margin-top:5px;}
  .rv-meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:12px 20px;margin:14px 0;padding:12px 0;border-top:1px solid var(--border);border-bottom:1px solid var(--border);}
  .rv-meta .k,.rv-amt-group .k{display:block;color:var(--text-muted);font-size:11px;margin-bottom:2px;}
  .rv-amounts{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:10px 14px;margin-bottom:14px;}
  .rv-amt-group{display:flex;gap:26px;flex-wrap:wrap;align-items:center;}
  .rv-pill{font-size:11px;padding:3px 10px;border-radius:100px;white-space:nowrap;}
  .rv-pill.ok{background:var(--success-bg);color:var(--success);}
  .rv-pill.warn{background:var(--warning-bg);color:var(--warning);}
  .rv-pill.bad{background:var(--danger-bg);color:var(--danger);}
  .rv-pill.pay{background:var(--accent-light);color:var(--accent-dark,#0F6E56);font-weight:700;}
  .rv-pill.type{background:#EEF2F7;color:#3B4757;font-weight:800;letter-spacing:.02em;}
  /* Commissary production. Classes rather than inline style="" so the value
     interpolated at the sink is only ever escaped text, never a style string —
     see the XSS-sink notes in CLAUDE.md. */
  .prod-qty{white-space:nowrap;font-weight:600;}
  .prod-short{white-space:nowrap;font-weight:600;color:var(--danger);}
  .prod-var-flat{text-align:right;font-weight:700;color:var(--text-muted);}
  .prod-var-down{text-align:right;font-weight:700;color:var(--danger);}
  .prod-var-up{text-align:right;font-weight:700;color:var(--warning);}
  .rv-pill.type.cogs{background:#E1F5EE;color:#0F7A5C;}
  .rv-pill.type.salary{background:#F3E8FB;color:#7A3FB0;}
  .rv-pill.type.asset{background:#FBF0DD;color:#9A6A12;}
  .rv-photo-wrap{display:flex;align-items:center;gap:8px;}
  .rv-photo-wrap img{width:46px;height:46px;object-fit:cover;border-radius:6px;border:1px solid var(--border);cursor:pointer;}
  .rv-photo-link{font-size:12px;color:var(--accent);cursor:pointer;}
  .rv-items tfoot td{border-top:1px solid var(--border-strong);border-bottom:none;padding-top:8px;font-weight:600;}

  .photo-row{padding:16px;border-top:1px solid var(--border);}
  .photo-row > label{display:block;font-size:12px;color:var(--text-secondary);margin-bottom:8px;font-weight:500;}
  .photo-upload{display:flex;align-items:center;gap:14px;}
  .photo-drop{
    border:1px dashed var(--border-strong);border-radius:var(--radius);padding:10px 16px;
    font-size:12px;color:var(--text-secondary);cursor:pointer;background:var(--surface-2);
  }
  .photo-drop:hover{border-color:var(--accent);color:var(--accent-dark);}
  .photo-drop input{display:none;}
  .photo-preview{display:flex;align-items:center;gap:10px;}
  .photo-thumb{
    width:52px;height:52px;object-fit:cover;border-radius:4px;border:1px solid var(--border);cursor:pointer;
  }
  .photo-preview .name{font-size:12px;color:var(--text-secondary);max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .photo-remove{background:none;border:none;color:var(--danger);font-size:12px;cursor:pointer;font-family:inherit;padding:0;}
  .photo-hint{font-size:11px;color:var(--text-muted);margin-top:6px;}
  /* ⚙ Work hours & punch photos — five labelled sections sharing ONE Save at the
     bottom (the button used to sit at the top beside Start/End, so a change made
     further down looked as though it had nowhere to be saved). The separator is
     the same 1px rule the sections were already drawn with inline; it is a
     sibling selector so the first section has no stray line above it. */
  .sch-sec + .sch-sec{border-top:1px solid var(--border);margin-top:14px;padding-top:12px;}
  .sch-sec-title{margin:0 0 4px;font-size:13px;font-weight:700;color:var(--text);}
  /* The long explanations kept their words but stopped sitting between a label
     and its input. <details> needs no JS, so nothing here touches CSP. */
  .sch-more{margin-top:6px;}
  .sch-more > summary{cursor:pointer;font-size:11px;color:var(--text-secondary);list-style:none;display:inline-flex;align-items:center;gap:5px;}
  .sch-more > summary::-webkit-details-marker{display:none;}
  .sch-more > summary::before{content:"▸";font-size:9px;}
  .sch-more[open] > summary::before{content:"▾";}
  .sch-more > summary:hover{color:var(--accent-dark);}
  .sch-save{display:flex;gap:12px;flex-wrap:wrap;align-items:center;border-top:1px solid var(--border);margin-top:16px;padding-top:14px;}
  /* "That Rate looks like a monthly salary" on the pay-item form. It is a grid
     item of .grid-fields sitting straight after the Rate field, and spans every
     column so the sentence reads as a sentence instead of wrapping to eight
     lines inside a third-width column. It carries display:none inline and is
     only ever shown by renderPayRateWarning, so a form with nothing suspect is
     laid out exactly as before. (The mobile block collapses .grid-fields to one
     column, where 1/-1 is simply the whole width.) */
  .pr-rate-warn{
    grid-column:1/-1;background:var(--warning-bg);color:var(--warning);
    border-radius:var(--radius);padding:10px 12px;font-size:12px;line-height:1.5;
  }
  /* The same suspicion on a saved register row. Emitted only when it trips. */
  .pr-rate-flag{color:var(--warning);font-weight:700;cursor:help;}
  .scan-invite{display:flex;align-items:center;gap:14px;padding:14px 18px;margin-bottom:16px;flex-wrap:wrap;
    border:1px solid var(--accent);border-radius:var(--radius);background:var(--accent-light);}
  .scan-invite:hover{border-color:var(--accent-dark);}
  .scan-invite-icon{font-size:26px;line-height:1;}
  /* flex-basis 240px: when the row gets tight, the BUTTONS wrap to their own
     line instead of the text being crushed to one word per line. */
  .scan-invite-text{display:flex;flex-direction:column;gap:2px;flex:1 1 240px;min-width:0;}
  .scan-invite-text strong{font-size:14px;color:var(--accent-dark);}
  .scan-invite-text span{font-size:12px;color:var(--text-secondary);}

  .lightbox{
    display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(20,24,30,0.82);
    align-items:center;justify-content:center;z-index:50;cursor:zoom-out;
  }
  .lightbox.active{display:flex;}
  .lightbox img{max-width:85%;max-height:85%;border-radius:6px;}

  .modal{
    display:none;position:fixed;inset:0;background:rgba(20,24,30,0.55);z-index:46;
    justify-content:center;align-items:flex-start;overflow-y:auto;padding:36px 16px;
  }
  .modal.active{display:flex;}
  .modal-card{
    background:var(--surface);border:1px solid var(--border);border-radius:12px;
    width:100%;max-width:900px;min-width:0;padding:22px 24px;position:relative;
    box-shadow:0 20px 60px rgba(20,24,30,0.35);
  }
  /* Wide detail tables scroll horizontally inside the card instead of forcing
     the whole modal past the viewport edge (which cut off the title on phones). */
  .tbl-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin-bottom:12px;}
  .tbl-scroll > table{margin-bottom:0;}
  .modal-close{
    position:absolute;top:12px;right:12px;width:30px;height:30px;border:none;background:none;
    color:var(--text-muted);font-size:17px;cursor:pointer;border-radius:6px;line-height:1;
  }
  .modal-close:hover{background:var(--surface-2);color:var(--text);}
  .rv-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px;padding-top:14px;border-top:1px solid var(--border);}
  .ob-compare-grid{
    display:grid;grid-template-columns:minmax(105px,1.2fr) repeat(2,minmax(0,1fr));
    border:1px solid var(--border);border-radius:8px;overflow:hidden;font-size:12.5px;
  }
  .ob-compare-grid > div{min-width:0;padding:7px 9px;border-bottom:1px solid var(--border);word-break:break-word;}
  .ob-compare-grid > div:nth-child(3n+2),.ob-compare-grid > div:nth-child(3n+3){text-align:right;}
  .ob-compare-grid > div:nth-last-child(-n+3){border-bottom:none;}
  .ob-compare-head{background:var(--surface-2);font-weight:700;color:var(--text-secondary);}

  /* Business-owner document template editor. Template syntax is represented
     as protected chips/regions; Advanced HTML remains available separately. */
  .tpl-mode-row{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin:6px 0 10px;}
  .tpl-mode-switch{display:inline-flex;border:1px solid var(--border-strong);border-radius:8px;padding:2px;background:var(--surface-2);}
  .tpl-mode-switch button{border:0;background:transparent;color:var(--text-secondary);font:inherit;font-size:12px;font-weight:600;padding:6px 11px;border-radius:6px;cursor:pointer;}
  .tpl-mode-switch button.active{background:var(--surface);color:var(--accent-dark);box-shadow:0 1px 3px rgba(20,24,30,.12);}
  .tpl-toolbar{display:flex;align-items:center;gap:5px;flex-wrap:wrap;padding:7px;border:1px solid var(--border-strong);border-bottom:0;border-radius:8px 8px 0 0;background:var(--surface-2);}
  .tpl-toolbar button,.tpl-toolbar select{min-height:32px;border:1px solid var(--border);border-radius:6px;background:var(--surface);color:var(--text);font:inherit;font-size:12px;padding:5px 9px;cursor:pointer;}
  .tpl-toolbar button{min-width:34px;font-weight:700;}
  .tpl-align-icon{display:inline-flex;width:14px;flex-direction:column;gap:2px;vertical-align:middle;}
  .tpl-align-icon i{display:block;width:14px;height:2px;border-radius:2px;background:currentColor;}
  .tpl-align-icon i:nth-child(even){width:9px;}
  .tpl-align-icon.center i:nth-child(even){align-self:center;}
  .tpl-align-icon.right i:nth-child(even){align-self:flex-end;}
  .tpl-visual{min-height:310px;max-height:48vh;overflow:auto;padding:18px;border:1px solid var(--border-strong);border-radius:0 0 8px 8px;background:#fff;color:#1f2933;font-family:Arial,sans-serif;font-size:14px;line-height:1.55;outline:none;}
  .tpl-visual:focus{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent);}
  .tpl-ph{display:inline-block;max-width:100%;margin:0 2px;padding:1px 7px;border:1px solid #81aee3;border-radius:999px;background:#eaf4ff;color:#174b7a;font-size:12px;font-weight:700;line-height:1.65;vertical-align:baseline;white-space:nowrap;user-select:all;}
  .tpl-ph-raw{border-color:#b89bd9;background:#f4edff;color:#60418a;}
  .tpl-cond{display:block;margin:9px 0;padding:28px 10px 8px;border:1px dashed #d49a34;border-radius:8px;background:#fffaf0;position:relative;}
  .tpl-cond-inline{display:inline;padding:18px 4px 2px;margin:0 2px;box-decoration-break:clone;-webkit-box-decoration-break:clone;}
  .tpl-cond-label{position:absolute;top:4px;left:8px;color:#8a5a0c;font-size:10px;font-weight:700;line-height:1.2;text-transform:uppercase;letter-spacing:.03em;user-select:none;}
  .tpl-cond-inline > .tpl-cond-label{top:2px;left:4px;}
  .tpl-cond-body{display:contents;}
  .tpl-cond:not(.tpl-cond-inline) > .tpl-cond-body{display:block;}
  .tpl-insert-list{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin:8px 0 10px;}
  .tpl-insert-list .tpl-insert-label{font-size:11px;color:var(--text-muted);margin-right:2px;}
  .tpl-insert-list button{border:1px solid #81aee3;border-radius:999px;background:#f5faff;color:#174b7a;font:inherit;font-size:11px;font-weight:600;padding:4px 8px;cursor:pointer;}
  .tpl-insert-list button.raw{border-color:#b89bd9;background:#faf7ff;color:#60418a;}
  .tpl-fallback{display:none;margin:8px 0;padding:9px 11px;border:1px solid #e2b35c;border-radius:8px;background:#fff8e8;color:#73500c;font-size:12px;line-height:1.45;}
  .tpl-preview{display:none;margin-top:12px;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:var(--surface-2);}
  .tpl-preview-head{display:flex;justify-content:space-between;align-items:center;padding:7px 10px;border-bottom:1px solid var(--border);font-size:12px;font-weight:700;}
  .tpl-preview iframe{display:block;width:100%;height:330px;border:0;background:#fff;}

  /* Toast notifications (replaces browser alert() for saves/errors) */
  #toastWrap{position:fixed;top:16px;right:16px;z-index:120;display:flex;flex-direction:column;gap:8px;max-width:360px;}
  .toast{
    padding:11px 14px;border-radius:10px;font-size:13px;line-height:1.45;white-space:pre-line;
    box-shadow:0 8px 24px rgba(20,24,30,0.18);border:1px solid var(--border);
    background:var(--surface);color:var(--text);animation:toastIn .18s ease-out;word-wrap:break-word;
  }
  .toast.success{border-left:4px solid var(--success);}
  .toast.error{border-left:4px solid var(--danger);}
  .toast.warn{border-left:4px solid #d97706;}
  .toast.hide{opacity:0;transform:translateX(12px);transition:opacity .25s,transform .25s;}
  .toast.has-action{display:flex;align-items:center;gap:12px;}
  .toast .toast-action{flex:0 0 auto;font-weight:800;color:var(--accent);background:var(--accent-light);border:none;border-radius:8px;padding:6px 12px;cursor:pointer;font-size:13px;}
  .toast .toast-action:active{transform:translateY(1px);}
  @keyframes toastIn{from{opacity:0;transform:translateX(12px);}to{opacity:1;transform:none;}}

  /* Thin top progress bar while any api() call is in flight */
  #apiProgress{position:fixed;top:0;left:0;height:2px;background:var(--accent);width:0;opacity:0;z-index:130;transition:width .4s ease,opacity .3s;}

  .detail-photo{margin-bottom:12px;}
  .detail-photo img{width:64px;height:64px;object-fit:cover;border-radius:4px;border:1px solid var(--border);cursor:pointer;}
  .detail-photo .no-photo{font-size:12px;color:var(--text-muted);}

  /* Modern minimalist auth: an airy white card on a soft near-white backdrop
     with a whisper of brand tint. Generous spacing, quiet borders. */
  .auth-screen{
    display:none;min-height:100vh;align-items:center;justify-content:center;padding:24px;
    background:#f5f8f7;
    background-image:radial-gradient(62% 45% at 50% -6%, rgba(15,110,86,.10) 0, transparent 72%);
  }
  .auth-screen.active{display:flex;}
  .auth-card{
    background:#fff;border:1px solid #edf1ef;border-radius:20px;
    padding:44px 40px;width:100%;max-width:404px;
    box-shadow:0 1px 3px rgba(16,40,32,.05),0 24px 60px rgba(16,40,32,.09);
  }
  .auth-card .auth-logo{height:46px;margin:0 auto 10px;}
  .auth-card label{color:#2a3a33;font-weight:600;font-size:13px;}
  .auth-card .field input{border-radius:10px;padding:12px 14px;border:1px solid #e3e9e6;background:#fff;}
  .auth-card .field input:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(15,110,86,.14);}
  .auth-card h1{font-size:22px;font-weight:800;letter-spacing:-.01em;margin:0 0 4px;text-align:center;}
  .auth-card p.sub{text-align:center;}
  .auth-card p.sub{margin:0 0 26px;color:var(--text-secondary);font-size:14px;}
  .auth-card .field{margin-bottom:16px;}
  .auth-card .btn{width:100%;padding:13px;border-radius:10px;font-weight:600;margin-top:4px;}
  .auth-alt{text-align:center;margin:14px 0 0;font-size:13px;color:var(--text-secondary);}
  .auth-alt a{color:var(--accent);font-weight:600;text-decoration:none;}
  .auth-alt a:hover{text-decoration:underline;}
  .auth-error{
    display:none;background:var(--danger-bg);color:var(--danger);border-radius:var(--radius);
    padding:9px 12px;font-size:12px;margin-bottom:12px;
  }
  .auth-error.active{display:block;}

  .user-bar{display:flex;align-items:center;gap:10px;}
  .user-chip{font-size:12px;color:var(--text-secondary);text-align:right;}
  .user-chip .name{font-weight:600;color:var(--text);display:block;font-size:13px;}
  header.top{display:flex;justify-content:space-between;align-items:flex-start;}

  .role-badge{display:inline-block;padding:2px 8px;border-radius:100px;font-size:11px;font-weight:600;}
  .role-badge.admin{background:var(--accent-light);color:var(--accent-dark);}
  .role-badge.approver{background:var(--warning-bg);color:var(--warning);}
  .role-badge.encoder{background:var(--surface-2);color:var(--text-secondary);border:1px solid var(--border);}

  .match-status{font-size:12px;padding:8px 16px;}
  .match-status.ok{color:var(--success);background:var(--success-bg);}
  .match-status.bad{color:var(--danger);background:var(--danger-bg);}
  .override-box{display:none;padding:0 16px 14px;}
  .override-box.active{display:block;}
  .override-box label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text);margin-bottom:8px;cursor:pointer;}
  .override-box textarea{width:100%;border:1px solid var(--border-strong);border-radius:var(--radius);padding:8px;font-family:inherit;font-size:12px;}

  /* ---------- Sidebar ---------- */
  .shell{display:flex;min-height:100vh;align-items:stretch;}
  .sidebar{
    width:200px;flex:0 0 200px;background:var(--surface);border-right:1px solid var(--border);
    padding:16px 10px;display:flex;flex-direction:column;gap:4px;
    position:sticky;top:0;height:100vh;overflow-y:auto;
  }
  .side-logo{height:44px;width:auto;align-self:flex-start;margin:2px 6px 16px;}
  .side-btn{
    display:flex;align-items:center;gap:10px;padding:10px 12px;border:none;background:none;
    border-radius:8px;font-family:inherit;font-size:13.5px;font-weight:500;color:var(--text-secondary);
    cursor:pointer;text-align:left;width:100%;line-height:normal;text-decoration:none;
  }
  .side-btn:hover{background:var(--surface-2);}
  .side-btn.active{background:var(--accent-light);color:var(--accent-dark);font-weight:600;}
  /* A module the tenant's PLAN doesn't include: still listed (it's a sale, not a
     permission), muted, with a padlock. The click opens the upgrade panel. */
  .side-btn.side-locked{opacity:.55;}
  .side-btn.side-locked:hover{background:var(--surface-2);opacity:.75;}
  .side-lock{margin-left:auto;font-size:12px;flex:0 0 auto;}
  /* padding-right keeps the heading clear of the ✕ close button */
  .upgrade-title{font-weight:800;font-size:18px;margin-bottom:4px;padding-right:28px;line-height:1.3;}
  .upgrade-sub{color:var(--text-secondary);font-size:13.5px;line-height:1.5;margin-bottom:6px;}
  .upgrade-offer{border:1px solid var(--border);border-radius:10px;padding:12px 14px;margin:12px 0;}
  .upgrade-plan{font-weight:700;font-size:16px;margin-bottom:4px;}
  .side-btn .ic{width:22px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;}
  .side-btn .ic svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round;}
  .side-sep{height:1px;background:var(--border);margin:10px 6px;}
  .header-meta{text-align:right;flex:0 0 auto;}
  .header-company{font-weight:600;font-size:14px;color:var(--text);}
  .header-date{font-size:12.5px;color:var(--text-secondary);margin-top:2px;}

  /* Notifications: bell in the header + dropdown panel. */
  .notif-wrap{position:relative;margin-left:auto;margin-right:16px;flex:0 0 auto;}
  .notif-bell{
    position:relative;display:inline-flex;align-items:center;justify-content:center;
    width:38px;height:38px;border:1px solid var(--border);border-radius:9px;
    background:var(--surface);color:var(--text-secondary);cursor:pointer;
  }
  .notif-bell:hover{background:var(--surface-2);color:var(--text);}
  .notif-badge{
    position:absolute;top:-5px;right:-5px;min-width:18px;height:18px;padding:0 4px;
    background:var(--danger,#c0392b);color:#fff;border-radius:9px;font-size:11px;font-weight:700;
    display:flex;align-items:center;justify-content:center;border:2px solid var(--surface);
  }
  .notif-panel{
    display:none;position:absolute;top:46px;right:0;width:340px;max-width:92vw;
    background:var(--surface);border:1px solid var(--border);border-radius:12px;
    box-shadow:0 20px 60px rgba(20,24,30,.28);z-index:120;overflow:hidden;
  }
  .notif-panel.active{display:block;}
  .notif-panel-head{
    display:flex;justify-content:space-between;align-items:center;padding:12px 14px;
    border-bottom:1px solid var(--border);font-weight:600;font-size:14px;
  }
  .notif-list{max-height:min(64vh,440px);overflow-y:auto;}
  .notif-item{display:flex;gap:10px;padding:11px 14px;border-bottom:1px solid var(--border);cursor:pointer;}
  .notif-item:hover{background:var(--surface-2);}
  .notif-item.unread{background:var(--accent-light);}
  .notif-item.unread:hover{background:var(--accent-light);}
  .notif-dot{flex:0 0 auto;width:8px;height:8px;border-radius:50%;background:var(--accent);margin-top:6px;}
  .notif-item.read .notif-dot{background:transparent;}
  .notif-body{min-width:0;flex:1 1 auto;}
  .notif-title{font-size:13px;font-weight:600;color:var(--text);}
  .notif-text{font-size:12.5px;color:var(--text-secondary);margin-top:1px;word-break:break-word;}
  .notif-time{font-size:11px;color:var(--text-muted);margin-top:3px;}
  .notif-empty{padding:26px 14px;text-align:center;color:var(--text-secondary);font-size:13px;}
  .notif-panel-foot{padding:10px 14px;border-top:1px solid var(--border);}
  .notif-panel-foot .btn{width:100%;justify-content:center;}
  .side-user{margin-top:auto;padding-top:12px;border-top:1px solid var(--border);display:flex;flex-direction:column;gap:1px;}
  .side-user-name{font-weight:600;font-size:13px;color:var(--text);padding:0 6px;}
  .side-user-role{font-size:11.5px;color:var(--text-secondary);padding:0 6px 10px;line-height:1.35;}
  .side-user-actions{display:flex;flex-direction:column;gap:6px;}
  .side-user-actions .btn{width:100%;justify-content:center;}

  /* Mobile nav drawer controls — hidden on desktop, shown in the phone media query. */
  .nav-toggle{
    display:none;align-items:center;justify-content:center;flex:0 0 auto;
    width:40px;height:40px;margin:-2px 2px -2px -6px;padding:0;
    border:1px solid var(--border);border-radius:9px;background:var(--surface);
    color:var(--text);cursor:pointer;
  }
  .nav-toggle:hover{background:var(--surface-2);}
  .nav-backdrop{display:none;}

  /* Reservations calendar: comfortable 7-col grid on desktop; the mobile block
     below shrinks the columns so the whole month fits the screen (no h-scroll). */
  .resv-cal-wrap{overflow-x:auto;}
  .resv-cal-grid{display:grid;grid-template-columns:repeat(7,minmax(74px,1fr));gap:4px;min-width:540px;}
  .resv-cal-cell{min-height:72px;min-width:0;overflow:hidden;border:1px solid var(--border);border-radius:6px;padding:3px;cursor:pointer;}

  /* ---------- Role permissions matrix ----------
     Areas are ROWS and roles are COLUMNS. With 17 areas the old orientation was
     ~19 columns wide, so it always scrolled sideways and the role name scrolled
     out of view — you couldn't tell which role a checkbox belonged to. Here the
     roles sit in a sticky header and the permission name in a sticky first
     column, so both stay on screen no matter how far you scroll. */
  .perm-wrap{overflow:auto;max-height:min(72vh,720px);border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);}
  .perm-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;}
  .perm-table th,.perm-table td{padding:9px 12px;border-bottom:1px solid var(--border);}
  .perm-table thead th{position:sticky;top:0;z-index:3;background:var(--surface-2);text-align:center;white-space:nowrap;font-size:12px;border-bottom:1px solid var(--border-strong);}
  /* Selector must out-specify `.perm-table thead th` above (0,1,2) or the z-index
     loses and the role headers paint over this cell when scrolled sideways. */
  .perm-table thead th.perm-h-area{position:sticky;left:0;z-index:5;text-align:left;min-width:250px;}
  .perm-h-role{min-width:94px;}
  .perm-h-role span{display:block;font-weight:400;font-size:11px;color:var(--text-muted);margin-top:2px;}
  .perm-h-admin{color:var(--text-muted);}
  .perm-h-dirty{box-shadow:inset 0 -3px 0 var(--accent);}
  .perm-h-dirty span{color:var(--accent);font-weight:600;}
  .perm-table tbody td:first-child{position:sticky;left:0;z-index:1;background:var(--surface);}
  .perm-area-name{display:block;font-weight:600;}
  .perm-hint{display:block;font-size:11.5px;color:var(--text-muted);margin-top:1px;max-width:330px;white-space:normal;}
  .perm-cell{text-align:center;}
  .perm-cell input[type=checkbox]{width:18px;height:18px;cursor:pointer;accent-color:var(--accent);}
  .perm-admin{color:var(--success);font-weight:700;}
  .perm-group td{background:var(--bg);font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-secondary);padding:7px 12px;}
  /* The group cell spans every column, so when scrolled sideways its text ran
     off to the left and the section read as a blank stripe. Stick the label. */
  .perm-group td span{position:sticky;left:12px;display:inline-block;}
  .perm-table tbody tr:not(.perm-group):hover td,
  .perm-table tbody tr:not(.perm-group):hover td:first-child{background:var(--surface-2);}
  .perm-actions{display:flex;justify-content:flex-end;align-items:center;gap:12px;margin-top:12px;flex-wrap:wrap;}
  .perm-note{font-size:12.5px;color:var(--text-muted);}

  /* ---------- Mobile ---------- */
  @media (max-width: 720px){
    /* Phones stack these cards, so a capped scroll box per card would nest four
       scrollers inside the page scroll — the cramped-box-inside-a-box problem the
       .hr-table-scroll rule below exists to avoid. Let them grow instead; the page
       is the only vertical scroller. */
    .dash-tasks-row{--dash-list-h:none;}
    .dash-tasks-row > .panel > .panel-body{max-height:none;overflow-y:visible;}
    table.records.na-table{max-height:none;overflow-y:visible;}

    .shell{flex-direction:column;}
    /* Reservations calendar fits all 7 days on-screen instead of scrolling. */
    .resv-cal-grid{grid-template-columns:repeat(7,minmax(0,1fr));min-width:0;gap:3px;}
    .resv-cal-cell{min-height:62px;padding:2px;}
    .resv-cal-cell > div:first-child{font-size:10px;}
    /* Sidebar becomes an off-canvas drawer: the same vertical nav slides in
       from the left over a backdrop, toggled by the header hamburger. The
       cramped horizontal-scroll strip (where most sections sat off-screen)
       is gone. Desktop is untouched — these rules only apply ≤720px. */
    .sidebar{
      position:fixed;top:0;left:0;z-index:200;
      width:min(84vw,300px);height:100vh;height:100dvh;
      flex-direction:column;align-items:stretch;gap:4px;
      padding:16px 12px;border-right:1px solid var(--border);border-bottom:none;
      overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;
      transform:translateX(-100%);transition:transform .25s ease;
      box-shadow:0 12px 40px rgba(15,20,25,.28);
    }
    body.nav-open .sidebar{transform:translateX(0);}
    .nav-backdrop{
      display:block;position:fixed;inset:0;z-index:190;
      background:rgba(15,20,25,.45);opacity:0;visibility:hidden;
      transition:opacity .25s ease;
    }
    body.nav-open .nav-backdrop{opacity:1;visibility:visible;}
    body.nav-open{overflow:hidden;}
    .nav-toggle{display:inline-flex;}
    .side-logo{height:34px;margin:2px 6px 12px;align-self:flex-start;}
    .side-btn{width:100%;flex:0 0 auto;padding:12px 12px;white-space:normal;font-size:14.5px;}
    .side-sep{width:auto;height:1px;margin:10px 6px;flex:0 0 auto;}
    .app{padding:14px 10px 40px;}
    /* Hamburger + greeting on line 1 (greeting truncates); company/date wrap
       to their own full-width line 2 so they never collide with the title.
       The inner min-width:0 lets the nested h1 actually ellipsis. */
    header.top{flex-direction:row;flex-wrap:wrap;align-items:center;gap:4px 10px;}
    header.top .brand{min-width:0;flex:1 1 auto;}
    header.top .brand > div{min-width:0;}
    header.top h1{font-size:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
    .notif-wrap{margin-right:0;}
    .header-meta{flex:1 0 100%;order:3;text-align:left;margin-left:0;}
    .header-company{font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .header-date{font-size:11.5px;}
    .side-user{margin-top:auto;border-top:1px solid var(--border);padding-top:12px;flex-direction:column;align-items:stretch;gap:1px;margin-left:0;}
    .side-user-name{display:block;}
    .side-user-role{display:block;}
    .side-user-actions{flex-direction:column;}
    .side-user-actions .btn{width:100%;}
    .tabs{overflow-x:auto;flex-wrap:nowrap;-webkit-overflow-scrolling:touch;scrollbar-width:none;}
    .tabs::-webkit-scrollbar{display:none;}
    .tab-btn{flex:0 0 auto;padding:11px 14px;white-space:nowrap;}
    .cards{grid-template-columns:repeat(2,1fr) !important;}
    .grid-fields{grid-template-columns:1fr !important;}
    /* 16px inputs stop iOS Safari from zooming in on focus */
    .field input,.field select,.field textarea,
    table.encode input,table.encode select,
    .approver-field input,.auth-card input{font-size:16px;}
    .btn{padding:11px 16px;}
    .btn-sm{padding:9px 12px;}
    .icon-btn{width:36px;height:36px;font-size:17px;}
    .filter-btn{padding:9px 14px;}
    .panel{overflow-x:auto;}
    /* Keep the page as the only vertical scroller on phones; bounded desktop
       HR tables otherwise become cramped scroll boxes inside the page. */
    .hr-table-scroll{max-height:none !important;overflow-y:visible;}
    table.records{min-width:640px;}
    table.records.narrow, table.records.compact{min-width:0;}
    /* Records tables → stacked cards on phones (no sideways scroll). Each <tr>
       becomes a bordered card; each <td> a "Label: value" line from its
       data-label. Only tables tagged .records-cards convert; others still
       h-scroll. Cards are full-width so the .panel never needs to scroll. */
    table.records-cards{min-width:0 !important;width:100%;display:block;}
    table.records-cards thead{display:none;}
    table.records-cards tbody{display:block;}
    table.records-cards tr{
      display:block;border:1px solid var(--border);border-radius:12px;
      background:var(--surface);padding:6px 12px 10px;margin-bottom:12px;
      box-shadow:0 1px 0 var(--border);
    }
    table.records-cards td{
      display:flex;align-items:center;justify-content:space-between;gap:10px;
      width:auto !important;padding:7px 0;border-bottom:1px solid var(--border);
      text-align:right;white-space:normal;
    }
    table.records-cards td::before{
      content:attr(data-label);flex:0 0 auto;text-align:left;
      font-size:11px;text-transform:uppercase;letter-spacing:.03em;
      color:var(--text-secondary);font-weight:700;
    }
    table.records-cards td.acts{
      flex-wrap:wrap;justify-content:flex-start;gap:6px 14px;border-bottom:none;padding-top:10px;
    }
    table.records-cards td.acts::before{content:"";display:none;}
    table.records-cards td.acts .link-btn{font-size:14px;padding:2px 0;}
    /* Empty spacer cells (e.g. the payroll TOTAL row) collapse in card mode. */
    table.records-cards td.pr-blank{display:none;}
    /* A cell whose own text already names what it is. In card mode every cell
       prints its data-label beside its value, so these read the word twice —
       "SUBTOTAL  SUBTOTAL — Kitchen". Desktop needs the word IN the cell (there
       is no label column there), so the label is dropped here rather than the
       text being shortened. */
    table.records-cards td.card-selflabel::before{content:none;}
    /* POS Receivables "Assign to" cell: label on top, controls full-width below */
    table.records-cards td.posar-cell{flex-direction:column;align-items:stretch;text-align:left;gap:8px;}
    table.records-cards td.posar-cell::before{text-align:left;}
    table.records-cards td.posar-cell > div{max-width:none !important;}
    .encode-scroll{overflow-x:visible;-webkit-overflow-scrolling:touch;}
    /* Encode item table → stacked card per item (no 1260px h-scroll on phones).
       Each <tr> becomes a bordered card; each <td> is a "Label: control" line.
       Labels come from the fixed column order via :nth-child ::before — the
       markup/order in renderRows is unchanged, no data-label needed. Every
       field stays visible + editable; nothing is hidden. Desktop is untouched
       (all rules live inside this @media block). */
    table.encode{min-width:0;width:100%;display:block;}
    table.encode thead{display:none;}
    table.encode tbody{display:block;}
    table.encode tr{
      display:block;border:1px solid var(--border);border-radius:8px;
      background:var(--surface);padding:6px 10px 10px;margin-bottom:12px;
    }
    table.encode td{
      display:flex;align-items:center;gap:8px;width:auto !important;
      padding:5px 0;border-bottom:1px solid var(--border);
    }
    table.encode tr td:last-child{border-bottom:none;}
    table.encode td::before{
      flex:0 0 40%;max-width:40%;
      font-size:11px;text-transform:uppercase;letter-spacing:.03em;
      color:var(--text-secondary);font-weight:600;
    }
    /* Column-order labels (renderRows td order is fixed). */
    table.encode td:nth-child(1)::before{content:"#";}
    table.encode td:nth-child(2)::before{content:"Item";}
    table.encode td:nth-child(3)::before{content:"Category";}
    table.encode td:nth-child(4)::before{content:"Subcategory";}
    table.encode td:nth-child(5)::before{content:"Department";}
    table.encode td:nth-child(6)::before{content:"Type";}
    table.encode td:nth-child(7)::before{content:"Qty";}
    table.encode td:nth-child(8)::before{content:"Unit";}
    table.encode td:nth-child(9)::before{content:"Unit price";}
    table.encode td:nth-child(10)::before{content:"Total";}
    table.encode td.rowdel::before{display:none;}
    /* Row number: small muted line, not a full-height cell. */
    table.encode td:nth-child(1){
      justify-content:flex-start;color:var(--text-muted);font-size:12px;
      padding-top:2px;padding-bottom:2px;border-bottom:none;
    }
    table.encode td:nth-child(1)::before{color:var(--text-secondary);}
    /* The field control fills the remaining width of each line. */
    table.encode td > input,
    table.encode td > select,
    table.encode td > .cellfill{flex:1 1 auto;min-width:0;}
    table.encode input,table.encode select{
      border:1px solid var(--border);background:var(--surface);
    }
    /* Remove (✕) control: right-aligned, no label. */
    table.encode td.rowdel{justify-content:flex-end;}
    /* 2B scan cue stays intact inside the stacked line — amber bar + PHOTO chip. */
    table.encode td .cellfill.scanned{padding:2px 4px;}

    /* Snap-invite on phones: hide the camera glyph, let the text use the full
       width, and stretch the two buttons edge-to-edge on their own line. */
    .scan-invite{gap:10px;}
    .scan-invite-icon{display:none;}
    .scan-invite > span:last-of-type{width:100%;}
    .scan-invite .btn{flex:1;min-width:0;}
    .detail-grid{grid-template-columns:1fr;}
    .totals-bar{gap:16px;}
    .filter-bar{padding:10px 12px;}
    /* The 2-up card grid moves onto the BAND, not the strip: the strip stacks
       its bands, each band lays its own figures out two across. Left on the
       strip, the grid items would be the bands rather than the figures and the
       whole phone layout would collapse into three tall single columns. */
    .ap-summary{display:flex;flex-direction:column;gap:12px;}
    .ap-summary-section{display:flex;flex-direction:column;gap:8px;}
    .ap-summary-figures{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 16px;}
    .ap-summary-headline,.ap-summary-note{grid-column:1/-1;}
    .ap-summary-divider{grid-column:1/-1;align-self:auto;border-left:0;border-top:1px solid var(--border);padding:10px 0 0;}
    .ap-summary-group{min-width:0;}
    .ap-summary-value{white-space:normal;}
    .ap-summary-marker{display:block;}
    .save-bar{flex-wrap:wrap;}
    .save-bar .btn{flex:1;min-width:140px;}
    .lightbox img{max-width:95%;max-height:90%;}

    /* Panel headers now carry controls (search, selects, buttons) — let them wrap. */
    .panel-header{flex-wrap:wrap;gap:8px;row-gap:8px;}
    .panel-header > span{flex-wrap:wrap;max-width:100%;}
    .panel-header input[type="search"]{width:100% !important;min-width:0;}
    .panel-header select{max-width:46vw;}

    /* Stat cards: 2-up needs smaller values so peso amounts fit. */
    .card-stat .value{font-size:17px;word-break:break-word;}

    /* Dashboard: Sales Trend + Top Categories stack instead of squeezing 2-up. */
    #dashSalesRow{grid-template-columns:1fr !important;}
    /* Costing: recipe list + detail stack on phones. */
    #costRecipeRow{grid-template-columns:1fr !important;}

    /* Toasts span the phone width instead of hugging a 360px column. */
    #toastWrap{left:12px;right:12px;max-width:none;}

    /* Modals: tighter padding, near-full width. */
    .modal{padding:14px 8px;}
    .modal-card{padding:18px 14px;}
    .modal-close{top:8px;right:8px;}
    .ob-compare-grid{grid-template-columns:minmax(86px,1.1fr) repeat(2,minmax(0,1fr));font-size:11.5px;}
    .ob-compare-grid > div{padding:6px 5px;}
    #tplModal .modal-card{padding:16px 10px;}
    .tpl-mode-row{align-items:stretch;}
    .tpl-mode-switch{width:100%;}
    .tpl-mode-switch button{flex:1;}
    .tpl-toolbar{gap:4px;overflow-x:auto;flex-wrap:nowrap;-webkit-overflow-scrolling:touch;}
    .tpl-toolbar button,.tpl-toolbar select{flex:0 0 auto;min-height:40px;}
    .tpl-visual{min-height:280px;max-height:44vh;padding:13px 10px;font-size:15px;}
    .tpl-insert-list{max-height:112px;overflow-y:auto;align-content:flex-start;}
    .tpl-preview iframe{height:300px;}
    /* Receipt & POS line items: stack each item as labeled rows instead of a
       wide table that scrolls off-screen. Labels come from each td's
       data-label, so tables with different column orders all read correctly.
       No horizontal scroll, nothing clipped. */
    .rv-items{display:block;min-width:0;}
    .rv-items thead{display:none;}
    .rv-items tbody{display:block;}
    .rv-items tbody tr{
      display:block;border:1px solid var(--border);border-radius:8px;
      background:var(--surface-2);padding:2px 10px;margin-bottom:10px;
    }
    .rv-items tbody td{
      display:flex;align-items:baseline;justify-content:space-between;gap:14px;
      padding:7px 0;border-bottom:1px solid var(--border);
      text-align:right;white-space:normal;
    }
    .rv-items tbody tr td:last-child{border-bottom:none;}
    .rv-items tbody td::before{
      content:attr(data-label);flex:0 0 auto;text-align:left;
      font-size:11px;text-transform:uppercase;letter-spacing:.03em;
      color:var(--text-secondary);font-weight:600;
    }
    .rv-items tfoot{display:block;}
    .rv-items tfoot tr{display:flex;justify-content:flex-end;gap:12px;padding:8px 2px 0;font-weight:700;}
    .rv-items tfoot td{padding:0;border:none;}


    /* Ron Assist: size the chat to the small viewport (dvh tracks the URL bar). */
    #view-ronassist > .panel{height:calc(100vh - 190px) !important;height:calc(100dvh - 190px) !important;min-height:400px;}
    .ron-msg{max-width:92%;}

    /* Time clock name grid: 2-up tap targets. */
    #tcGrid{grid-template-columns:repeat(2,1fr) !important;}

    /* Day close (per-wallet): each wallet stacks into a full-width block —
       counted box, reason and Close button each on their own line, tappable. */
    #cfDayClosePanel .dc-row{flex-direction:column;align-items:stretch;gap:8px;}
    /* flex-basis is a HEIGHT once the row turns into a column, so the wallet
       name block's `flex:1 1 150px` reserved 150px for ~40px of text — about
       110px of dead white space per wallet, four times over, on the phone
       where the day actually gets closed. */
    #cfDayClosePanel .dc-row > div{width:100%;flex:0 0 auto !important;}
    #cfDayClosePanel .dc-count{justify-content:space-between;}
    #cfDayClosePanel .dc-row input{width:100% !important;box-sizing:border-box;flex:1 1 auto;}
    #cfDayClosePanel .dc-row .btn{width:100%;}
    #cfDayClosePanel .dc-row span[id^="dc-var-"]{text-align:left !important;min-width:0;}

    /* No modal ever wider than the screen (inline max-widths are overridden). */
    .modal-card{max-width:100% !important;}

    /* Purchasing item-row editors (request + PO modals): the fixed Qty/Unit/₱
       columns squeezed the Item input to ~1 character on phones. Stack each
       line — Item full-width on top, qty/unit/price + ✕ underneath. */
    .item-rows-table{display:block;}
    .item-rows-table thead{display:none;}
    .item-rows-table tbody{display:block;}
    .item-rows-table tr{display:grid;grid-template-columns:1fr 1fr 1.3fr auto;gap:8px;align-items:center;padding:10px 0;border-bottom:1px solid var(--border);}
    .item-rows-table td{display:block;width:auto !important;padding:0;border:none;}
    .item-rows-table td:first-child{grid-column:1/-1;}
    .item-rows-table input{width:100% !important;box-sizing:border-box;}

    /* Permissions matrix on a phone: the sticky permission name is what makes
       sideways scrolling survivable, so keep it — just narrow it and drop the
       hint text (the label carries the meaning). */
    /* Must match the desktop rule's specificity (`.perm-table thead th.perm-h-area`)
       or the 250px min-width wins and eats two thirds of a phone screen. */
    .perm-table thead th.perm-h-area{min-width:148px;}
    .perm-table tbody td:first-child{min-width:148px;}
    .perm-hint{display:none;}
    .perm-h-role{min-width:72px;}
    .perm-table th,.perm-table td{padding:8px 7px;}
    .perm-actions{justify-content:stretch;}
    .perm-actions .btn{flex:1;}
  }

  /* Routine checklist: the grid is wider than a phone, so the chore's NAME stays
     put while the dates scroll under it — the same reason the permissions matrix
     pins its first column. Without it you scroll right and lose which row you are
     reading, which is the only thing that makes the ticks mean anything. */
  .routine-table th:first-child, .routine-table td:first-child{
    position:sticky;left:0;z-index:1;background:var(--surface);
    /* box-shadow, not border-right: a border on a sticky cell scrolls with the
       table's own border-collapse and leaves a gap. */
    box-shadow:1px 0 0 var(--border);
  }
  .routine-table thead th:first-child{background:var(--surface-2,var(--surface));}

  /* ---- Kiosk PIN pad: must fit ANY screen, punch buttons always reachable ----
     These rules are keyed on HEIGHT, not width, and therefore deliberately live
     outside the max-width:720px block above. The devices that break here are
     phones in LANDSCAPE — 844px wide but only 390px tall — which no width query
     would ever match. The kiosk is wall-mounted or handheld, so landscape is the
     normal orientation, not an edge case. */
  .kiosk-pad-card{
    background:var(--surface);border-radius:16px;width:min(330px,92vw);text-align:center;
    box-shadow:0 12px 40px rgba(0,0,0,.3);
    display:flex;flex-direction:column;
    /* dvh tracks the collapsing browser chrome on mobile; vh is the fallback for
       engines without it, and is merely conservative rather than wrong. */
    max-height:calc(100vh - 20px);
    max-height:calc(100dvh - 20px);
    margin:auto;   /* centres while still allowing the overlay to scroll — with
                      align-items:center alone an overflowing card is clipped at
                      the TOP and that part becomes unreachable. */
  }
  /* min-height:0 is what actually lets this shrink; a flex item defaults to
     min-height:auto and would refuse to become shorter than its content, pushing
     the footer off-screen exactly as before. */
  .kiosk-pad-scroll{overflow-y:auto;min-height:0;flex:1 1 auto;padding:26px 26px 0;}
  .kiosk-pad-foot{flex:0 0 auto;padding:10px 26px 18px;}
  .kiosk-keys{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:14px 0;}
  #kioskCam{width:180px;height:135px;}

  /* Short screens: shrink so the keypad stays comfortably tappable instead of
     being scrolled. The footer is pinned regardless, so this is about keeping
     the pad usable, not about reaching the buttons. */
  @media (max-height: 700px){
    .kiosk-pad-scroll{padding:16px 18px 0;}
    .kiosk-pad-foot{padding:8px 18px 12px;}
    .kiosk-keys{gap:7px;margin:9px 0;}
    .kiosk-keys .btn{padding:9px 10px;}
    #kioskCam{width:132px;height:99px;}
    #kioskPadName{font-size:18px;}
    #kioskPadDots{font-size:24px;height:28px;}
  }
  @media (max-height: 520px){
    /* Landscape phones. Put the camera preview and the keypad side by side so
       the pad uses the width it has plenty of instead of the height it has none
       of, and drop the ornamental bits. */
    .kiosk-pad-card{width:min(560px,96vw);}
    .kiosk-pad-scroll{display:flex;align-items:center;gap:14px;text-align:left;padding:12px 14px 0;}
    .kiosk-pad-scroll > .kiosk-keys{flex:1 1 auto;margin:0;}
    .kiosk-pad-side{flex:0 0 auto;max-width:44%;}
    .kiosk-pad-foot{padding:8px 14px 10px;}
    .kiosk-keys{gap:6px;}
    .kiosk-keys .btn{padding:7px 10px;font-size:15px;}
    #kioskCam{width:104px;height:78px;margin:0 0 4px;}
    #kioskCamNote{display:none !important;}   /* the preview itself says it */
    #kioskPadName{font-size:15px;}
    #kioskPadSub{font-size:12px;margin-bottom:6px;}
    #kioskPadDots{font-size:20px;height:22px;letter-spacing:7px;}
    #kioskPadMsg{margin-top:6px;min-height:0;font-size:13px;}
  }
  /* Ordinary modals already scroll (.modal is align-items:flex-start with
     overflow-y:auto), so nothing in them is unreachable — but 36px of padding
     top and bottom is 72px of a 390px-tall landscape phone spent on nothing.
     Give it back; the in-app time-clock PIN modal then fits without scrolling. */
  @media (max-height: 560px){
    .modal{padding:10px 12px;}
    .modal-card{padding:16px 16px;}
  }
