.user-duplicate-notice { margin:12px; padding:12px; border:1px solid var(--border-strong); border-radius:8px; overflow-wrap:anywhere; }
.user-duplicate-notice p { margin:0 0 10px; }
.user-duplicate-notice button { max-width:100%; white-space:normal; }
: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;
    /* ⚠ DEFINED, NOT RENAMED AWAY. public/app.js used var(--font-mono) on a
       self-signup URL with word-break:break-all — deliberately monospace — and
       the token did not exist, so the declaration was dropped and the link
       inherited --font. Mapping the use site to --font instead would have been
       a SILENT NO-OP: measured in a browser, that element already computes to
       the --font stack today, so the "fix" would have changed nothing on screen
       while closing the bug. This is the only one of the eleven undefined
       tokens that restores an appearance rather than a colour. */
    --font-mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
    --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;}

  /* ⚠ A CUSTOMER'S OWN WORDS MUST NEVER PUSH THE PAGE SIDEWAYS — the sibling of the
     rule above, and the same failure in a different costume. That one is a flex item
     that WOULD not shrink (min-width:auto); this is one that CANNOT, because its
     longest word has nowhere to break.

     Workplace → Routines renders names and "when" hints the customer typed into
     plain divs. A long unbroken token means the flex item holding it can never be
     narrower than that word: the row grows, the tab grows with it, and EVERY panel
     on the tab is clipped at the viewport edge with its right border off-screen.
     Reported as exactly that — subtitles cut mid-phrase, Run and Edit gone, the
     history row running past the edge. Measured at 820px: 12 elements wider than
     their parent and the document 90px past the window; with this rule, zero, and
     it fits. Removing it restores the defect.

     ⚠ overflow-wrap, NOT overflow-x:auto on the section. Wide content scrolls inside
     its OWN container in this app and the body never scrolls sideways; a scroller
     here would hide the symptom and break that convention in the same stroke.

     Inherited, so one rule reaches the name, the hint and the history rows without
     touching any generated markup. Hyphens are already break opportunities, so only
     a genuinely unbroken token ever gets this far. */
  #tasksTab-routines{overflow-wrap:anywhere;}
  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) ---- */
  .dash-money{margin:0 0 18px;min-width:0;}
  .dash-money-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin:0 0 10px;}
  .dash-money-head h2{font-size:16px;margin:0;font-weight:650;}
  .dash-money-period{display:flex;gap:6px;flex-wrap:wrap;}
  .dash-money-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;min-width:0;}
  .dash-money-block{min-width:0;overflow:hidden;}
  .dash-money-answer{padding:8px 16px 4px;min-width:0;}
  .dash-money-label{font-size:11px;color:var(--text-muted);margin-bottom:3px;}
  .dash-money-big{font-size:30px;line-height:1.15;font-weight:750;font-variant-numeric:tabular-nums;white-space:nowrap;}
  .dash-money-big.positive{color:var(--success,#0F6E56);}
  .dash-money-big.negative{color:var(--danger);}
  .dash-money-lines{display:flex;flex-direction:column;gap:5px;margin-top:8px;font-size:12px;color:var(--text-secondary);min-width:0;}
  .dash-money-line{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;min-width:0;}
  .dash-money-line-label{min-width:0;overflow-wrap:anywhere;}
  .dash-money-line-amount{white-space:nowrap;font-variant-numeric:tabular-nums;color:var(--text);text-align:right;}
  .dash-money-line-amount.positive{color:var(--success,#0F6E56);}
  .dash-money-line-amount.negative{color:var(--danger);}
  .dash-money-depreciation-note{font-size:12px;color:var(--text-muted);padding-left:12px;margin-top:-3px;}
  .dash-money-nonexpense-line{border-top:1px solid var(--border);padding-top:6px;margin-top:3px;color:var(--text-muted);}
  .dash-money-nonexpense-line .dash-money-line-amount{color:var(--text-muted);}
  .dash-money-sharebar{height:6px;display:flex;overflow:hidden;border-radius:4px;background:var(--border);margin:2px 0 3px;}
  .dash-money-sharebar span{height:100%;flex:0 0 auto;}
  .dash-money-legend{display:flex;flex-direction:column;gap:4px;font-size:11px;color:var(--text-secondary);}
  .dash-money-legend-row{display:flex;align-items:flex-start;gap:5px;min-width:0;}
  .dash-money-legend-dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto;margin-top:4px;}
  .dash-money-legend-name{min-width:0;overflow-wrap:anywhere;flex:1;}
  .dash-money-legend-amount{white-space:nowrap;font-variant-numeric:tabular-nums;color:var(--text);}
  .dash-money-note{padding:0 16px 8px;font-size:11px;color:var(--text-muted);}
  .dash-money-link{margin:0 16px 12px;}
  .dash-money-error{font-size:13px;color:var(--danger);}
  /* 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;}
  .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);}
  /* Category rows open the shared receipt popup. */
  tr.rep-cat-row{cursor:pointer;}
  tr.rep-cat-row:hover td{background:var(--accent-light);}
  tr.rep-cat-row:focus-visible{outline:3px solid var(--accent);outline-offset:-3px;}
  /* 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. */
  /* ⚠ #onboardScreen IS LISTED HERE RATHER THAN GIVEN ITS OWN RULE, and it is the
     setup wizard's inputs that need it. Several of them are bare <input>s, not
     wrapped in .field — and every rule that would otherwise style an .auth-card
     input lives inside the @media (max-width:720px) block, so on a LAPTOP they
     matched nothing but `*` and rendered as raw browser defaults (2px inset
     border, 13.3px font) while the company-name field beside them looked normal.
     With no width they also kept their intrinsic ~154px, which is what pushed a
     .grid-fields track past the 404px card and clipped the password box by 130px.
     Sharing this rule rather than copying it is deliberate: a second block of the
     same declarations is how the wizard's inputs come to look subtly unlike every
     other input in the product.
     ⚠ file is excluded as well as checkbox/radio: #onboardLogoFile sits in a flex
     row beside its preview image, and width:100% there would stretch it across a
     layout that is already correct. */
  .field input:not([type="checkbox"]):not([type="radio"]),
  #onboardScreen input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
  .field select, .field textarea, #onboardScreen select, #onboardScreen 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,
  #onboardScreen input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):focus,
  .field select:focus, .field textarea:focus, #onboardScreen select:focus, #onboardScreen textarea:focus{
    outline:none;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-light);
  }
  #holidaysWrap[hidden],#holidayAdminControls[hidden],#holidayForm[hidden],#holidaysEmpty[hidden]{display:none;}
  .holiday-intro{margin-bottom:12px;}
  .holiday-toolbar{display:flex;align-items:flex-end;gap:10px;flex-wrap:wrap;margin-bottom:12px;}
  .holiday-year-field{width:120px;margin:0;}
  .holiday-actions{display:flex;gap:8px;flex-wrap:wrap;}
  .holiday-form{display:grid;grid-template-columns:160px minmax(220px,1fr) 170px auto;gap:10px;align-items:end;padding:12px;margin-bottom:14px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);}
  .holiday-form .field{margin:0;}
  .holiday-form-actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap;}
  .holiday-table-wrap{overflow-x:auto;}
  .holiday-table{min-width:0;}
  /* 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-prov{grid-column:1 / -1;font-size:12px;color:var(--text-secondary);margin-top:-2px;}
  .cf-proposal{border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin-bottom:10px;font-size:13px;}
  .cf-proposal[data-status="pending"]{border-color:var(--warning, #d97706);}
  .cf-proposal-head{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:6px;}
  .cf-proposal-status{font-weight:700;font-size:11px;letter-spacing:.03em;}
  .cf-proposal-wallets{margin:4px 0 6px 18px;padding:0;}
  .cf-proposal-reason,.cf-proposal-outcome{margin:4px 0;color:var(--text-secondary);}
  .cf-proposal-escape{margin:6px 0;padding:6px 8px;border-radius:8px;background:rgba(217,119,6,.12);font-weight:600;}
  .cf-proposal-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:6px;}
  .cf-proposal-hint{font-size:12px;color:var(--text-secondary);}
  .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);}

  /* ⚠ A BUTTON THAT REFUSES MUST NOT LOOK LIVE. There was no :disabled rule at
     all, so a disabled button rendered at full contrast with the pointer
     cursor: pressing it did nothing and said nothing. Reduced contrast plus
     not-allowed, and the hover states are neutralised so a dead button does
     not light up under the mouse. Nothing that is meant to look active is
     touched — the selectors reach disabled elements only. */
  .btn:disabled, .btn[disabled], button:disabled, button[disabled]{
    opacity:.5;cursor:not-allowed;filter:grayscale(.35);
  }
  .btn:disabled:hover, .btn[disabled]:hover, button:disabled:hover, button[disabled]:hover{
    background:var(--surface);filter:grayscale(.35);
  }
  .btn-primary:disabled:hover, .btn-primary[disabled]:hover{background:var(--accent);}
  .btn:disabled:active, .btn[disabled]:active{transform:none;}
  .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;}
  .payment-sites-summary{display:flex;align-items:center;flex-wrap:wrap;gap:4px;min-width:0;}
  .payment-sites-summary > .link-btn{flex-shrink:0;}
  .payment-site-chip{background:var(--bg);border:1px solid var(--border);border-radius:10px;padding:2px 6px;font-size:11px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .payment-sites-every{color:var(--text-muted);white-space:nowrap;font-size:12px;}
  .payment-sites-picker{width:360px;padding:8px;border:1px solid var(--border);border-radius:var(--radius);text-align:left;}
  #paymentSettingsTable td.acts > .link-btn{white-space:nowrap;}
  .payment-type-popover{position:fixed;z-index:60;box-sizing:border-box;max-width:calc(100vw - 16px);overflow:auto;background:var(--surface);color:var(--text);box-shadow:0 8px 24px rgba(20,24,30,.2);}
  .payment-type-menu{width:220px;padding:4px;border:1px solid var(--border);border-radius:var(--radius);}
  .payment-type-menu .link-btn{display:block;width:100%;text-align:left;padding:9px 10px;overflow-wrap:anywhere;}
  .payment-type-menu .link-btn:is(:hover,:focus-visible){background:var(--bg);}
  .payment-type-menu .danger{border-top:1px solid var(--border);margin-top:4px;}
  .payment-sites-picker label{display:flex;align-items:center;gap:6px;font-weight:normal;overflow-wrap:anywhere;}
  .payment-sites-picker input{flex-shrink:0;width:auto;}
  .payment-sites-actions{display:flex;gap:8px;margin-top:4px;grid-column:1 / -1;}
  .payment-sites-warning{grid-column:1 / -1;font-size:12px;color:var(--text-secondary);}
  .payment-sites-unavailable{font-size:11px;color:var(--text-muted);flex-basis:100%;}
  .payment-sites-every:is(button){cursor:pointer;background:none;border:0;padding:0;font-family:inherit;font-weight:normal;}
  .payment-sites-header-hint{display:block;text-transform:none;font-size:11px;font-weight:normal;color:var(--text-muted);}
  .payment-sites-hint{grid-column:1 / -1;display:none;color:var(--text-muted);font-size:12px;margin-bottom:6px;}
  @media (min-width:721px){
    #paymentSettingsTable td[data-payment-sites]{min-width:280px;}
    .payment-sites-two-columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:4px 8px;}
    #paymentSettingsBody td[data-label="Wallet"] select{min-width:150px;}
  }
  .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;}

  /* Inventory toolbar (BRIEF-CODEX-linked-dishes-section-layout-2026-09-29,
     Part A): the ⋯ overflow menu behind Export / Import / Import from POS /
     Clear movements, and the below-zero banner + POS auto-deduct status line
     that replaced text squeezed beside "Stock on hand". */
  .inv-more-wrap{position:relative;}
  /* position/top/left are set in JS (toggleInvMoreMenu) and clamped to the
     viewport — the fallback top:36px;right:0 below only matters before JS has
     ever opened it once, and is harmless since the menu starts display:none. */
  .inv-more-menu{
    display:none;position:absolute;top:36px;right:0;min-width:210px;
    background:var(--surface);border:1px solid var(--border);border-radius:10px;
    box-shadow:0 14px 40px rgba(20,24,30,.22);z-index:60;padding:6px;
  }
  .inv-more-menu.active{display:block;}
  .inv-more-item{
    display:block;width:100%;text-align:left;background:none;border:none;
    padding:8px 10px;font-size:13px;font-family:inherit;color:var(--text);
    border-radius:6px;cursor:pointer;box-sizing:border-box;
  }
  .inv-more-item:hover{background:var(--surface-2);}
  .inv-more-divider{height:1px;background:var(--border);margin:6px 2px;}
  .inv-more-danger{color:var(--danger);}
  .inv-alert-banner{
    display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;
    padding:10px 16px;background:var(--danger-bg);border-bottom:1px solid var(--border);
    color:var(--danger);font-weight:600;font-size:13.5px;
  }
  .inv-status-line{display:flex;align-items:center;gap:10px;padding:10px 16px 0;font-size:13px;color:var(--text-secondary);}
  /* Part B: row actions fade in on hover, so the eye lands on figures rather
     than buttons — scoped to the Inventory stock/held tables ONLY (by id, not
     the shared .acts class other tables also use, e.g. moves/links/production). */
  #invItemsBody tr .acts, #invHeldBody tr .acts{opacity:0;transition:opacity .12s;}
  #invItemsBody tr:hover .acts, #invHeldBody tr:hover .acts,
  #invItemsBody tr .acts:focus-within, #invHeldBody tr .acts:focus-within{opacity:1;}

  .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;
  }
  /* Pay-item money is grouped in the order HR reasons about it: identify the
     person, compose earnings, compose deductions, then confirm take-home. */
  .pr-form-section + .pr-form-section{border-top:1px solid var(--border);margin-top:18px;padding-top:16px;}
  .pr-form-section-title{margin:0 0 11px;font-size:13px;font-weight:700;color:var(--text);}
  /* A payslip figure a payroll step produced (lockedFields from the server):
     read-only, and visibly so - a dashed, dimmed box and a "locked" tag - with
     #prLockNotes saying which step to go to instead. */
  /* ⚠ As specific as the base .field input rule plus a class, or it loses to it
     (QA: the box rendered exactly like an editable one). */
  .field.pr-locked input:not([type="checkbox"]):not([type="radio"]){background:var(--surface-2);color:var(--text-secondary);border-style:dashed;cursor:not-allowed;}
  .pr-lock-tag{display:flex;align-items:center;gap:5px;margin-top:5px;font-size:11px;color:var(--text-secondary);}
  .pr-lock-tag svg{width:14px;height:14px;flex:none;}
  .pr-lock-notes{margin:0 0 14px;padding:10px 12px;border-radius:var(--radius);background:var(--surface-2);border:1px solid var(--border);font-size:12px;line-height:1.5;color:var(--text-secondary);}
  .pr-lock-notes p{margin:0 0 6px;} .pr-lock-notes p:last-child{margin:0;}
  .pr-total-strip{
    display:grid;grid-template-columns:minmax(140px,1fr) minmax(180px,1fr);align-items:center;gap:14px;
    margin-top:12px;padding:11px 14px;border:1px solid var(--border);border-radius:var(--radius);
    background:var(--surface-2);
  }
  .pr-total-strip label{margin:0;font-size:13px;color:var(--text);}
  .pr-net-total{margin-top:18px;border-color:var(--accent);background:var(--accent-light);}
  /* 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;}
  .rep-statement-panels{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);gap:14px;margin-bottom:8px;min-width:0;}
  .rep-statement-panel{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:16px;min-width:0;box-shadow:var(--shadow);}
  .rep-statement-panel.is-full{grid-column:1/-1;}
  .rep-statement-muted{background:var(--surface-2,var(--bg));border-style:dashed;box-shadow:none;}
  .rep-statement-muted[hidden]{display:none;}
  .rep-statement-title{font-size:12px;color:var(--text-secondary);margin-bottom:12px;}
  .rep-share-bar{height:6px;display:flex;overflow:hidden;border-radius:4px;background:var(--border);margin-bottom:8px;}
  .rep-share-segment{height:100%;flex:0 0 auto;}
  .rep-statement-lines{min-width:0;}
  .rep-statement-line{display:flex;align-items:center;gap:9px;width:100%;min-width:0;padding:10px 0;border:0;border-bottom:1px solid var(--border);background:transparent;color:var(--text);font:inherit;text-align:left;cursor:pointer;}
  .rep-statement-static{cursor:default;}
  .rep-statement-line:hover .rep-group-cue{color:var(--accent-dark);}
  .rep-statement-line:focus-visible{outline:3px solid var(--accent);outline-offset:2px;border-radius:5px;}
  .rep-line-dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;}
  .rep-line-name{min-width:0;flex:1;overflow-wrap:anywhere;text-transform:uppercase;font-size:12px;}
  .rep-line-share{font-size:11px;color:var(--text-muted);white-space:nowrap;}
  .rep-line-amount{white-space:nowrap;font-variant-numeric:tabular-nums;text-align:right;font-size:12px;}
  .rep-group-cue{font-size:11px;color:var(--accent);white-space:nowrap;margin-left:2px;}
  .rep-statement-total{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;border-top:1px solid var(--border);padding-top:12px;margin-top:10px;font-size:13px;}
  .rep-statement-total-strong{font-weight:700;color:var(--text);border-top:2px solid var(--text);}
  .rep-statement-total-strong > span:first-child{overflow-wrap:anywhere;}
  .rep-statement-total-quiet{font-weight:400;color:var(--text-secondary);border-top-color:var(--border);}
  .rep-approved-line{font-size:11px;color:var(--text-muted);margin-bottom:18px;}
  #reportGroupTitle{padding-right:30px;overflow-wrap:anywhere;}
  #reportGroupDayHeader:not([hidden]){display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px;}
  #reportGroupDayLabel{margin:0;}
  #reportGroupDayNav:not([hidden]){display:flex;justify-content:space-between;gap:8px;margin-bottom:12px;}
  #reportGroupTotal{font-size:26px;font-weight:700;}
  #reportGroupModal td{overflow-wrap:anywhere;}
  #reportGroupModal th,#reportGroupModal td{padding:10px;text-align:left;}
  #reportGroupModal .tbl-scroll{max-width:100%;}
  /* One row per receipt. Each row is a real button over a grid so it is reachable by
     Tab and activates on Enter/Space. The supplier column is the one that gives way:
     min-width:0 + ellipsis means a long name with no spaces can never push Amount
     off-screen. */
  .rep-receipts{margin-bottom:12px;}
  .rep-receipt-grid{display:grid;grid-template-columns:minmax(0,1fr) 3.5em 9em;gap:10px;align-items:center;
    box-sizing:border-box;width:100%;min-width:0;max-width:100%;padding:10px;text-align:left;font:inherit;color:var(--text);}
  .rep-receipt-grid.has-sites,#reportGroupReceipts.has-sites .rep-receipt-grid{grid-template-columns:minmax(0,1fr) 3.5em 9em minmax(0,7em);}
  .rep-receipt-head{font-size:12px;font-weight:600;color:var(--text-secondary);border-bottom:1px solid var(--border);}
  .rep-receipt-head[hidden]{display:none;}
  .rep-receipt-head > span:nth-child(2),.rep-receipt-items{text-align:right;}
  .rep-receipt-head > span:nth-child(3),.rep-receipt-amount{text-align:right;}
  .rep-receipt-row{background:none;border:none;border-bottom:1px solid var(--border);cursor:pointer;border-radius:0;}
  .rep-receipt-row:hover{background:var(--bg);}
  .rep-receipt-row:focus-visible{outline:3px solid var(--accent);outline-offset:-3px;}
  .rep-receipt-supplier,.rep-receipt-site{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .rep-receipt-amount{white-space:nowrap;font-variant-numeric:tabular-nums;font-weight:600;}
  #reportReceiptModal .modal-card{max-width:560px;}
  #reportReceiptTitle{padding-right:30px;overflow-wrap:anywhere;}
  #reportReceiptMeta{margin:0 0 12px;color:var(--text-secondary);font-size:13px;}
  #reportReceiptModal td{overflow-wrap:anywhere;text-align:left;padding:10px;}
  #reportReceiptModal th{text-align:left;padding:10px;}
  #reportReceiptTotalRow{display:flex;justify-content:space-between;gap:12px;font-size:17px;margin-bottom:12px;}
  .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);}
  /* pre-wrap so a multi-paragraph announcement keeps its paragraphs in the bell
     (the email already did — two documents from one send); clamped to 4 lines to
     keep the list compact. The notification detail view shows the full text. */
  .notif-text{font-size:12.5px;color:var(--text-secondary);margin-top:1px;word-break:break-word;white-space:pre-wrap;
    display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden;}
  .notif-item.expanded .notif-text{display:block;-webkit-line-clamp:unset;overflow:visible;}
  .notif-item.has-more .notif-body::after{content:"Show more";display:block;font-size:11.5px;color:var(--accent);margin-top:3px;}
  .notif-item.has-more.expanded .notif-body::after{content:"Show less";}
  .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);}

  /* The owner's own typed pre-order items. Capped so the Add row above and the
     Save button below stay reachable with a 44-item menu instead of being pushed
     off the fold. Lifted on phones below — the same cap-plus-lift pairing
     .hr-table-scroll uses, and for the same reason. */
  #resvManualList{max-height:34vh;overflow-y:auto;}

  #slpFilters{min-width:0;max-width:100%;}
  #slpFilters label{display:flex;align-items:center;gap:6px;font-size:13px;}
  #slpFilters input{width:145px;min-width:0;padding:6px 8px;font-family:inherit;font-size:13px;}

  /* Request detail: where each line ended up. Desktop shows the "Ordered?" column;
     the copy under the item name is hidden. On a phone the table is wider than the
     screen and that column is entirely off-screen, so it swaps (rules in the
     mobile block below). */
  .prq-where-m{display:none;}

  /* ---------- Mobile ---------- */
  #reviewOpenBtn{white-space:nowrap}
  .review-card{max-width:620px;max-height:min(90vh,850px);overflow:auto}
  .review-card h3{margin:18px 0 8px}
  .review-card label{display:block;margin:8px 0;font-size:13px}
  .review-card input{display:block;width:100%;margin-top:4px;box-sizing:border-box}
  .review-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
  .review-head h2{margin:0}
  .review-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
  .review-grid .btn{white-space:normal}
  .review-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}
  .review-branches{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 12px}
  .review-kiosk-card{width:min(100%,380px);height:min(90vh,760px);display:flex;flex-direction:column}
  #reviewKioskFrame{border:1px solid var(--border);border-radius:16px;flex:1;width:100%;background:white}
  @media print{#reviewOpenBtn,#reviewPanel,#reviewKiosk{display:none!important}}
  .pr-sheet-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:0 16px 10px}
  .pr-sheet-toolbar #prSheetOnly{display:inline-flex;gap:6px;flex-wrap:wrap}
  .pr-sheet-toolbar #prSheetOnly[hidden]{display:none}
  .pr-sheet-switch{display:inline-flex;gap:3px}
  .pr-sheet-switch [aria-pressed="true"]{background:var(--accent);color:white}
  .pr-sheet-export-note{font-size:11px;line-height:1.3;color:var(--text-secondary);max-width:185px}
  .pr-sheet-look{font-size:12px;display:inline-flex;align-items:center;gap:4px;white-space:nowrap}
  .pr-sheet-panel{max-width:100%;min-width:0;background:var(--surface);--pr-row-width:36px;--pr-name-width:190px}
  .pr-sheet-panel[hidden]{display:none}
  .pr-sheet-formula{display:flex;gap:10px;align-items:center;min-height:42px;padding:6px 12px;border-top:1px solid var(--border);border-bottom:1px solid var(--border);font-size:12px}
  #prSheetRef{font-weight:700;min-width:42px;border-right:1px solid var(--border)}
  #prSheetFormula{flex:1;min-width:0;overflow-wrap:anywhere}
  .pr-sheet-exit{display:none}
  .pr-sheet-panel.pr-sheet-full .pr-sheet-exit{display:inline-block}
  .pr-sheet-scroll{width:100%;max-height:min(63vh,680px);overflow:auto;overscroll-behavior:contain}
  #prSheetTable{border-collapse:separate;border-spacing:0;min-width:max-content;font-size:12px}
  #prSheetTable th,#prSheetTable td{padding:7px 9px;border-right:1px solid var(--border);border-bottom:1px solid var(--border);background:var(--surface);white-space:nowrap;min-width:105px}
  #prSheetTable .pr-rownum{position:sticky;left:0;z-index:3;min-width:var(--pr-row-width);width:var(--pr-row-width);text-align:center;background:var(--surface-2)}
  #prSheetTable .pr-name{position:sticky;left:var(--pr-row-width);z-index:2;min-width:var(--pr-name-width);max-width:var(--pr-name-width);overflow:hidden;text-overflow:ellipsis;background:var(--surface)}
  #prSheetTable thead th{position:sticky;z-index:4;background:var(--surface-2)}
  #prSheetTable thead .pr-rownum{z-index:6}
  #prSheetTable thead .pr-name{z-index:5;background:var(--surface-2)}
  #prSheetTable .pr-sheet-groups th{top:0;height:30px;background:var(--surface-2);font-weight:700;color:var(--text-secondary)}
  #prSheetTable .pr-sheet-letters th{top:30px;height:26px;background:var(--surface-2);font-weight:500;color:var(--text-secondary)}
  #prSheetTable .pr-sheet-titles th{top:56px;height:36px;background:var(--surface-2)}
  #prSheetTable .pr-sheet-titles button{border:0;background:none;color:inherit;font:inherit;font-weight:700;cursor:pointer;padding:0;text-align:left}
  #prSheetTable .pr-num{text-align:right;font-variant-numeric:tabular-nums}
  #prSheetTable .pr-sheet-actions{min-width:175px}
  #prSheetTable .pr-sheet-actions button{margin-right:5px}
  #prSheetTable tbody td[data-row]{cursor:cell}
  #prSheetTable tbody td.pr-name span{cursor:pointer;text-decoration:underline}
  #prSheetTable .pr-selected{outline:2px solid var(--accent);outline-offset:-2px;background:var(--surface-2)}
  #prSheetTable tfoot td,#prSheetTable tfoot .pr-name{position:sticky;bottom:0;background:var(--surface-2);font-weight:700;z-index:3}
  #prSheetTable tfoot tr:first-child:not(:last-child) td{bottom:32px}
  #prSheetTable tfoot .pr-name{z-index:5}
  .pr-net-tag{display:inline-block;margin-left:5px;padding:2px 4px;border-radius:4px;background:#fff1d6;color:#704900;font-size:10px}
  .pr-sheet-panel.pr-sheet-full{position:fixed;inset:0;z-index:10000;display:flex;flex-direction:column;background:var(--surface)}
  .pr-sheet-panel.pr-sheet-full .pr-sheet-scroll{max-height:none;flex:1}
  .wallet-view-switch,.wallet-new-controls,.wallet-filters{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:12px}
  .wallet-view-switch .active{background:var(--accent);color:#fff}
  .wallet-summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:12px}
  .wallet-summary>div{padding:10px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}
  .wallet-summary-calendar{grid-template-columns:repeat(2,minmax(0,1fr))}
  .wallet-summary small{display:block;color:var(--text-secondary)}
  .wallet-grid-scroll{max-width:100%;max-height:65vh;overflow:auto;border:1px solid var(--border);border-radius:var(--radius)}
  .wallet-grid{border-collapse:separate;border-spacing:0;min-width:max-content;width:100%;font-size:13px}
  .wallet-grid th,.wallet-grid td{padding:7px 10px;border-right:1px solid var(--border);border-bottom:1px solid var(--border);background:var(--surface);white-space:nowrap;text-align:right}
  .wallet-grid thead th{position:sticky;top:0;z-index:3;background:var(--surface)}
  .wallet-grid thead tr:first-child th{top:0}
  .wallet-grid thead tr:nth-child(2) th{top:31px}
  .wallet-grid th:first-child,.wallet-grid td:first-child{position:sticky;left:0;z-index:2;text-align:left;background:var(--surface)}
  .wallet-grid thead th:first-child{z-index:4}
  .wallet-grid .wallet-moved{background:var(--success-bg)}
  .wallet-grid .wallet-negative{background:var(--danger-bg);color:var(--danger)}
  .wallet-grid .wallet-today td{box-shadow:inset 0 0 0 1px var(--accent)}
  .wallet-grid .wallet-footer td{position:sticky;bottom:0;z-index:2;font-weight:700;background:var(--surface)}
  .wallet-grid .wallet-footer-before td{bottom:34px}
  .wallet-grid .wallet-footer td:first-child{z-index:3}
  .wallet-grid small{display:block;font-size:10px;color:var(--text-secondary)}
  .wallet-grid button.wallet-cell{border:0;background:none;color:inherit;font:inherit;cursor:pointer;text-align:right}
  .wallet-filters label{display:flex;gap:5px;align-items:center;font-size:12px}
  .wallet-filter-wallet{position:relative;display:flex;gap:5px;align-items:center;font-size:12px}
  .wallet-filter-menu{position:absolute;top:calc(100% + 4px);left:0;z-index:8;min-width:190px;max-width:min(300px,calc(100vw - 32px));max-height: min(55vh,320px);overflow:auto;padding:6px;border:1px solid var(--border-strong);border-radius:var(--radius);background:var(--surface);box-shadow:0 8px 24px #0002}
  .wallet-filter-menu[hidden]{display:none}
  .wallet-filter-menu button,.wallet-filter-menu label{display:flex;align-items:center;gap:8px;width:100%;box-sizing:border-box;padding:7px 8px;border:0;border-radius:6px;background:transparent;color:var(--text);text-align:left;font:inherit;cursor:pointer}
  .wallet-filter-menu button:hover,.wallet-filter-menu label:hover{background:var(--surface-2)}
  .wallet-filter-menu .wallet-filter-all{font-weight:700;border-bottom:1px solid var(--border);border-radius:0}
  .wallet-filter-menu input{margin:0}
  .wallet-cashbook-text{text-align:left!important}
  .wallet-cashbook-number{text-align:right!important}
  .wallet-footnote{font-size:11px;color:var(--text-secondary)}
  #walletCellModal{background:transparent;padding:0}
  #walletCellModal .wallet-cell-card{position:fixed;width:min(430px,calc(100vw - 24px));max-width:none;max-height:calc(100dvh - 24px);overflow-y:auto;padding:18px}
  #cfDailyPanel.wallet-full{position:fixed;inset:0;z-index:40;margin:0;overflow:auto;border-radius:0;background:var(--surface)}
  #cfDailyPanel.wallet-full .wallet-grid-scroll{max-height:calc(100dvh - 230px)}
  @media (max-width: 720px){
    #payDecisionPerson .pay-decision-day{grid-template-columns:1fr;}
    #payDecisionPerson .pay-decision-day.pay-decision-tickable{grid-template-columns:44px minmax(0,1fr);}
    #payDecisionPerson .pay-decision-tickable .pay-decision-actions{grid-column:2;}
    #prSheetPanel{max-width:100%;width:100%;overflow:hidden}
    #prSheetPanel .pr-sheet-scroll{max-width:100%;overflow-x:auto}
    #prSheetPanel{--pr-name-width:145px;--pr-row-width:30px}
    #prSheetTable th,#prSheetTable td{padding:6px;min-width:90px}
    .pr-sheet-export-note{max-width:155px}
    #cfDailyPanel,#cfDailyContent,#walletSheetView,#walletCashbookView{min-width:0;max-width:100%;box-sizing:border-box}
    .wallet-summary{grid-template-columns:repeat(2,minmax(0,1fr))}
    .wallet-grid-scroll{width:100%;max-width:100%;overflow-x:auto}
    .wallet-filters{align-items:flex-start}
    .wallet-filter-wallet{max-width:100%}
    .wallet-filter-menu{position:fixed;left:12px;top:auto;right:12px;bottom:12px;max-width:none;max-height:55dvh}
    .review-card{width:100%;max-width:100%;max-height:100dvh;border-radius:0}
    .review-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
    .review-branches{grid-template-columns:1fr}
    #reviewOpenBtn{padding:7px 9px;font-size:12px}
    .prq-where-col{display:none;}
    .prq-where-m{display:block;margin-top:4px;font-size:12px;line-height:1.35;}
    #reportGroupModal .modal-card{padding:16px;min-width:0;}
    #reportGroupDayHeader:not([hidden]){align-items:flex-start;flex-direction:column;}
    #reportGroupDayNav button{padding:8px 10px;}
    #reportGroupExport{max-width:100%;white-space:normal;}
    #reportGroupModal table{min-width:480px;}
    /* Phone: supplier + amount on the first line, items + site underneath, so a
       narrow screen never has to squeeze four columns. */
    .rep-receipt-head{display:none;}
    .rep-receipt-grid,.rep-receipt-grid.has-sites,#reportGroupReceipts.has-sites .rep-receipt-grid{grid-template-columns:minmax(0,1fr) auto;row-gap:2px;}
    .rep-receipt-items{grid-row:2;grid-column:1;text-align:left;font-size:12px;color:var(--text-secondary);}
    .rep-receipt-items::before{content:"Items: ";}
    .rep-receipt-amount{grid-row:1;grid-column:2;}
    .rep-receipt-site{grid-row:2;grid-column:2;text-align:right;font-size:12px;color:var(--text-secondary);max-width:40vw;}
    #reportGroupModal .tbl-scroll{overflow-x:auto;}

    #slpFilters{width:100%;}
    #slpFilters label{flex:1 1 100%;}
    #slpFilters input{flex:1;max-width:100%;font-size:16px;}
    #slpFilters select{min-width:0;max-width:100%;font-size:16px !important;}
    /* Payroll "Run this period" steps: on a phone the description takes the
       full width and the buttons wrap onto their own line beneath it. With two
       buttons in the row ("Keep figures as entered" beside the step's own) the
       description was squeezed to a sliver and the first button overlapped it. */
    .pr-run-step{flex-wrap:wrap}
    .pr-run-step > div{flex:1 1 calc(100% - 38px) !important}
    .pr-run-step > .btn{margin-left:38px}
    /* 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;}
    .holiday-toolbar{align-items:stretch;}
    .holiday-year-field{width:100%;}
    .holiday-actions{width:100%;}
    .holiday-actions .btn{flex:1 1 180px;}
    .holiday-form{grid-template-columns:1fr;}
    .holiday-form-actions .btn{flex:1 1 120px;}
    .pr-total-strip{grid-template-columns:1fr;gap:6px;}
    /* 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;}
    .payment-settings-scroll{max-width:100%;overflow-x:auto;}
    /* Same rule for the pre-order menu modal's two lists. #resvCurateList carries
       its cap inline, hence !important. Without these a phone gets the page
       scroller plus two nested boxes inside one modal. */
    #resvManualList{max-height:none;overflow-y:visible;}
    #resvCurateList{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;}
    /* ⚠ tfoot needs this as much as tbody does. Without it the footer stays a
       table-footer-group inside a display:block table, so it renders as an
       anonymous box sized to its content — a totals card visibly narrower than
       the rows above it. Only ONE .records-cards table has a tfoot today (the
       branch scoreboard), which is why this went unnoticed; any future one gets
       it for free. */
    table.records-cards tfoot{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[data-payment-sites]{flex-wrap:wrap;min-width:0;}
    table.records-cards td[data-payment-sites] .payment-sites-summary{flex:1;justify-content:flex-end;}
    .payment-sites-two-columns{display:block;}
    .payment-sites-hint{display:block;}
    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;}
    .dash-money-grid{grid-template-columns:minmax(0,1fr);}
    .dash-money-period{width:100%;}
    .dash-money-period .filter-btn{flex:1 1 auto;padding:7px 8px;}
    /* 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;}

    /* Keep the typed Clear confirmation readable without iOS input zoom. */
    #invClearName{font-size:16px;}

    /* 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;}

    /* Inventory: :hover doesn't fire reliably on a touch screen, so the
       fade-on-hover row actions (desktop, above) stay always-on on a phone —
       a tap must not need a hover it can't produce. */
    #invItemsBody tr .acts, #invHeldBody tr .acts{opacity:1;}
    .inv-more-menu{max-width:calc(100vw - 16px);}
    #payHelpDrawer{width:100%;}
    #payHelpDrawer .payhelp-fields{grid-template-columns:repeat(2,minmax(0,1fr));}
  }
  @media (max-width:480px){
    .rep-statement-panels{grid-template-columns:minmax(0,1fr);}
    .rep-group-cue{font-size:0;width:16px;flex:0 0 16px;text-align:center;}
    .rep-group-cue::after{content:"›";font-size:19px;}
  }
  @media (max-width:400px){
    .dash-money-grid{grid-template-columns:minmax(0,1fr) !important;}
    .dash-money-block .cards{grid-template-columns:minmax(0,1fr) !important;}
    .dash-money-block .dash-money-big{white-space:nowrap;}
    .rep-statement-panel{padding:14px;}
    .rep-statement-line{gap:6px;}
    .rep-line-name{font-size:11px;}
    .rep-line-share{font-size:10px;}
    .rep-line-amount{font-size:11px;}
  }

  /* 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;}
  }

/* Public schedule link (#schedView). Two renderings of the same data; only one
   shows. Below 900px the day-grouped list (the phone layout chosen deliberately
   in #314) is exactly what shipped; at 900px and up the container widens and a
   Monday-first fortnight grid takes its place. Decided by width, never by user
   agent, and with no state. */
/* The public schedule container: 560px for the phone-first day list; the
   >=900px rule below widens it for seven columns. The width lives HERE and
   not on the element's inline style, because an inline max-width beats any
   class rule and silently pins the grid at 560px (seen in a real browser). */
.sched-wrap{max-width:560px;}
.sched-grid{display:none;}
@media (min-width:900px){
  #schedView .sched-wrap{max-width:1180px;}
  .sched-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:8px;}
  .sched-list{display:none;}
}
.sched-cell{border:1px solid var(--border);border-radius:10px;background:var(--surface);padding:8px 9px;min-height:118px;min-width:0;}
.sched-cell.today{border-color:var(--accent);border-width:2px;}
.sched-cell.past{opacity:.62;}
.sched-cell-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px;}
.sched-cell-wd{font-weight:700;font-size:12.5px;}
.sched-cell-dt{font-size:11px;color:var(--text-secondary);}
.sched-cell-today{font-size:10px;font-weight:700;color:var(--accent);}
.sched-row{padding:4px 0;border-top:1px solid var(--border-light,rgba(0,0,0,.05));min-width:0;}
.sched-row-name{font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.sched-row-when{font-size:11.5px;color:var(--text-secondary);font-variant-numeric:tabular-nums;line-height:1.3;white-space:normal;}
.sched-row-when.rest{color:var(--text-muted);}
.sched-row-dep{font-size:10.5px;color:var(--text-muted);white-space:normal;overflow-wrap:anywhere;}
.sched-cell-empty{font-size:11.5px;color:var(--text-muted);padding-top:4px;}

/* Payroll review: people, their days, then the existing day editor. */
.pay-decision-done { background: var(--success-bg); }
/* The people list fills its card: Employee takes the slack, the figures sit right-aligned
   in tabular numerals so ₱0.96 and ₱600.00 line up. No min-width, so it fits at 375px. */
.pay-decision-people { width:100%; border-collapse:collapse; }
.pay-decision-people th { text-align:left; }
.pay-decision-people th, .pay-decision-people td { padding:10px; }
.pay-decision-people th:first-child { width:100%; }
.pay-decision-people th.r, .pay-decision-people td.r { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
.pay-decision-people td:last-child, .pay-decision-people th:last-child { white-space:nowrap; }
.pay-decision-name { color:var(--accent); text-decoration:underline; background:none; border:0; text-align:left; }
/* The name is a link, as in the mockup, not a raised pill: drop the .btn shadow and padding. */
.btn.pay-decision-name { box-shadow:none; padding:2px 0; min-height:0; border-radius:0; transform:none; }
.attendance-time-edit { font-size:12.5px; color:var(--warning); background:var(--warning-bg); border-radius:6px; padding:6px 9px; margin-top:5px; width:fit-content; overflow-wrap:anywhere; max-width:100%; }
#attTimeEdits:not(:empty) { margin-bottom:14px; }
.pay-decision-day { display:grid; grid-template-columns:1fr auto; gap:10px 14px; padding:14px 10px; border-bottom:1px solid var(--border); }
.pay-decision-day.pay-decision-tickable { grid-template-columns:44px minmax(0,1fr) auto; }
.pay-decision-tick-hit { min-width:44px; min-height:44px; display:flex; align-items:flex-start; justify-content:center; box-sizing:border-box; cursor:pointer; }
.pay-decision-tick { width:18px; height:18px; margin:2px 0 0; }
.pay-decision-tick-all { display:flex; align-items:center; gap:8px; padding:8px 10px; }
.pay-decision-tick-all input { width:18px; height:18px; margin:0; }
.pay-decision-tick-all[hidden], #payDecisionPersonDeclineSelected[hidden] { display:none; }
.pay-decision-time { font-size:13px; font-variant-numeric:tabular-nums; color:var(--text-secondary); }
.pay-decision-note, .pay-decision-reason { font-size:12px; margin-top:4px; color:var(--text-secondary); overflow-wrap:anywhere; }
.pay-decision-actions, .pay-decision-footer { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
.pay-decision-footer { padding-top:16px; }
.pay-decision-footer span { flex:1; font-size:12px; color:var(--text-secondary); }
.pay-decision-day > [id^="payDecisionReasonBox"] { grid-column:1/-1; background:var(--surface-2); }
.pay-decision-verdict { padding:12px; margin-top:10px; background:var(--surface-2); border-radius:6px; font-size:13px; }
@media(max-width:600px){ .pay-decision-people th, .pay-decision-people td { padding:8px 5px; } }

.pr-post-review{width:min(680px, calc(100vw - 24px));max-width:100%;box-sizing:border-box;}
.pr-post-table{width:100%;border-collapse:collapse;}
.pr-post-table th,.pr-post-table td{padding:8px 4px;white-space:normal;overflow-wrap:anywhere;}
.pr-post-table th:first-child,.pr-post-table td:first-child{width:31%;min-width:84px;text-align:left;}
.pr-post-table th:not(:first-child),.pr-post-table td:not(:first-child){text-align:right;font-variant-numeric:tabular-nums;}
/* A peso figure never breaks mid-number ("₱23,000.0" / "0" on a 375px phone,
   QA on #533). Auto layout lets each figure column take its figure's width;
   when the figures outgrow the card, the table scrolls inside its own
   .table-scroll box, never the page. Headers still wrap, but only between words. */
.pr-post-table tbody th:not(:first-child),.pr-post-table tbody td:not(:first-child){white-space:nowrap;overflow-wrap:normal;}
.pr-post-table thead th:not(:first-child){overflow-wrap:normal;}
.pr-post-table .pr-post-shortfall{font-size:12px;color:var(--text-secondary);}
@media(max-width:480px){.pr-post-review{padding:14px;}.pr-post-table{font-size:11px;}}

/* Board 10: the read-only detail behind one Planned figure, stacked above
   .pr-post-review (see the modal's own comment in index.html for why). */
.pr-post-detail{width:min(560px, calc(100vw - 24px));max-width:100%;box-sizing:border-box;}
.pr-post-detail-sub{color:var(--text-secondary);font-size:13px;margin:2px 0 12px;}
.pr-post-detail-table{width:100%;border-collapse:collapse;margin-bottom:14px;}
.pr-post-detail-table th,.pr-post-detail-table td{padding:7px 6px;text-align:left;white-space:normal;overflow-wrap:anywhere;}
.pr-post-detail-table th:last-child,.pr-post-detail-table td:last-child{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;}
.pr-post-detail-table .pr-post-detail-empty{color:var(--text-secondary);text-align:center;}
.pr-post-detail-figures{display:grid;grid-template-columns:1fr auto;gap:5px 12px;margin:0 0 10px;}
.pr-post-detail-figures dt{color:var(--text-secondary);}
.pr-post-detail-figures dd{margin:0;text-align:right;font-variant-numeric:tabular-nums;}
.pr-post-detail-warn{color:var(--warning);font-weight:700;}
.pr-post-detail-note{font-size:12px;color:var(--text-secondary);}
@media(max-width:480px){.pr-post-detail{padding:14px;}.pr-post-detail-table{font-size:11px;}}

/* Payroll explanation drawer */
.payhelp-how{font-size:12px;color:var(--accent);cursor:pointer;font-weight:600;margin-left:6px;white-space:nowrap;}
.payhelp-open{margin-left:auto;}
.payhelp-scrim{position:fixed;inset:0;background:rgba(15,20,26,.4);z-index:150;}
.payhelp-drawer{position:fixed;top:0;right:0;bottom:0;width:min(560px,100%);background:var(--surface);z-index:151;box-shadow:0 12px 32px rgba(0,0,0,.25);display:flex;flex-direction:column;padding-top:env(safe-area-inset-top,0px);}
.payhelp-head{display:flex;align-items:center;gap:10px;padding:16px 18px;border-bottom:1px solid var(--border);}
.payhelp-head h3{font-size:17px;margin:0;flex:1;}
.payhelp-head button{border:0;background:none;font-size:24px;cursor:pointer;color:var(--text-secondary);}
.payhelp-settings{padding:10px 18px;background:var(--surface-2);border-bottom:1px solid var(--border);font-size:12px;color:var(--text-secondary);}
#payHelpChips{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px;}
.payhelp-chip{background:var(--surface);border:1px solid var(--border);border-radius:999px;padding:3px 9px;color:var(--text);font-weight:600;}
.payhelp-tabs{display:flex;flex-wrap:wrap;gap:4px;padding:8px 12px;border-bottom:1px solid var(--border);}
.payhelp-tabs button{border:0;background:none;padding:7px 10px;border-radius:8px;font-weight:600;font-size:13px;color:var(--text-secondary);white-space:nowrap;cursor:pointer;}
.payhelp-tabs button[aria-selected="true"]{background:var(--accent-light);color:var(--accent);}
#payHelpBody,.payhelp-body{grid-auto-rows:max-content;}
.payhelp-body{flex:1;overflow:auto;padding:16px 18px calc(24px + env(safe-area-inset-bottom,0px));display:grid;gap:14px;align-content:start;line-height:1.5;}
.payhelp-body h4,.payhelp-body p{margin:0;}
.payhelp-body h4{font-size:15px;}
.payhelp-rule{display:grid;gap:4px;border-left:3px solid var(--accent);padding:2px 0 2px 12px;}
.payhelp-rule p{color:var(--text-secondary);}
.payhelp-calc{border:1px solid var(--border);border-radius:12px;padding:12px 14px;display:grid;gap:10px;background:var(--surface-2);}
.payhelp-fields{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;}
.payhelp-fields label{display:grid;gap:3px;font-size:12px;color:var(--text-secondary);}
.payhelp-fields input{min-width:0;width:100%;border:1px solid var(--border);border-radius:8px;padding:6px 8px;background:var(--surface);}
#payHelpResult{font-weight:700;}
.payhelp-table{overflow-x:auto;overflow-y:visible;}
.payhelp-table table{width:100%;border-collapse:collapse;}
.payhelp-table th,.payhelp-table td{padding:7px 8px;border-bottom:1px solid var(--border);text-align:left;}
.payhelp-note{background:var(--warning-bg);padding:10px 12px;border-radius:10px;}
.payhelp-foot{font-size:12px;color:var(--text-secondary);}
