/* ===== Migalink ICT — HIMS component kit (Trust Blue) =====
   Tokens live in tokens.css (loaded first). This file = shared components. */
*{box-sizing:border-box;}
body{margin:0;font-family:var(--font-sans);background:var(--color-bg);color:var(--color-ink);font-size:var(--fs-body);line-height:1.5;}
/* D-254 #5: the 12px floor (--fs-label) also covers Bootstrap's two RELATIVE sizes. .badge is .75em and
   small/.small is .875em of the parent, so a badge in a 14px grid cell came out at 10.5px. max() keeps them
   relative wherever they are already big enough and lifts them only where they would drop under the floor. */
.badge{font-size:max(.75em,var(--fs-label));}
small,.small{font-size:max(.875em,var(--fs-label));}
/* F-616 (BOSS 2026-11-03): Edge draws its own reveal (eye) and clear buttons inside every password box, next to
   the IFMIS eye button. Hide the browser's ones system-wide so each password box shows exactly one eye: ours. */
input[type="password"]::-ms-reveal,input[type="password"]::-ms-clear{display:none;}
.app{display:flex;min-height:100vh;}

/* sidebar (dark) */
.rail{width:var(--rail-w,232px);position:relative;background:var(--sidebar-bg);border-right:1px solid rgba(255,255,255,.08);padding:18px 14px;flex-shrink:0;position:sticky;top:0;height:100vh;align-self:flex-start;overflow-y:auto;}
/* BOSS finding #56 (2026-09-01): the brand is centred in the rail and a size down (24px mark, 14px wordmark). */
.brand{display:flex;align-items:center;justify-content:center;gap:8px;margin:4px 6px 22px;}
.brand .wordmark{font-size:14px;color:#fff;letter-spacing:-.01em;}
.brand .wordmark b{font-weight:800;}
.brand .wordmark .ict{color:var(--blue-200);font-weight:700;margin-left:2px;}
/* D-318 N1 (BOSS 2026-11-02): the main sidebar brand is "Powered by Migalink" — the sign-in page's .auth-powered look. */
.brand .brand-powered{font-size:12px;color:var(--powered-text);white-space:nowrap;}
.brand .brand-powered b{color:var(--color-surface);font-weight:800;letter-spacing:.04em;}
.nav{display:flex;flex-direction:column;gap:2px;}
.nav-group{display:flex;flex-direction:column;}
.nav-mod{display:flex;align-items:center;gap:11px;width:100%;padding:11px 13px;border:none;background:transparent;color:var(--blue-200);font-size:14px;font-weight:600;border-radius:var(--radius-md);cursor:pointer;text-align:left;}
.nav-mod .ico{width:18px;opacity:.85;display:inline-flex;justify-content:center;}
.nav-mod .nav-mod-title{flex:1;}
.nav-mod .chev{font-size:12px;opacity:.8;transition:transform .2s ease;}
.nav-mod:hover{background:rgba(255,255,255,.10);color:#fff;}
.nav-mod[aria-expanded="true"]{background:rgba(255,255,255,.06);color:#fff;}
.nav-mod[aria-expanded="true"] .chev{transform:rotate(180deg);}
.nav-sub{display:flex;flex-direction:column;gap:1px;padding:2px 0 6px;}
a.nav-item{display:block;padding:9px 12px 9px 42px;color:var(--blue-200);text-decoration:none;font-size:13.5px;border-radius:var(--radius-md);}
a.nav-item:hover{background:rgba(255,255,255,.08);color:#fff;}
a.nav-item.active{background:var(--color-primary);color:#fff;font-weight:600;}
.nav-mod:focus-visible,a.nav-item:focus-visible{outline:2px solid #fff;outline-offset:2px;}

/* ===== Function-first sidebar (Concept C — Setup / Entry / Reports tabs, D-64) ===== */
.navc{display:flex;flex-direction:column;gap:2px;}
.navc-pins{display:flex;flex-direction:column;gap:2px;margin-bottom:8px;}
/* D-296 DB = C: the Dashboard button is an outlined row with a blue icon tile. */
.navc-pin{display:flex;align-items:center;min-height:48px;gap:12px;padding:6px 10px;color:var(--color-surface);text-decoration:none;font-size:14px;font-weight:700;background:transparent;border:1.5px solid var(--blue-400);border-radius:10px;}
.navc-pin i{width:32px;height:32px;display:grid;place-items:center;background:var(--color-primary);color:var(--color-surface);border-radius:8px;font-size:17px;}
.navc-pin:hover,.navc-pin.active{background:var(--blue-200);color:var(--blue-900);border-color:var(--blue-200);}
.navc-tabs{display:flex;gap:4px;background:rgba(0,0,0,.18);padding:4px;border-radius:10px;margin:2px 0 10px;}
.navc-tab{flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;border:0;background:transparent;color:var(--blue-200);font:inherit;font-weight:700;font-size:12px;padding:8px 4px;border-radius:7px;cursor:pointer;}
.navc-tab .navc-tab-c{font-size:var(--fs-label);font-weight:700;opacity:.7;}
.navc-tab:hover{color:#fff;}
.navc-tab.on{background:#fff;color:var(--color-primary-hover);}
.navc-tab.on .navc-tab-c{color:var(--color-primary);opacity:1;}
.navc-sec{display:none;flex-direction:column;gap:1px;}
.navc-sec.show{display:flex;}
/* D-254 #5: a module name is a LONG label ("Treasury — Collections & Cashiering" is 35 characters), so it is
   shown as written rather than in caps. Bold weight and --rail-muted keep it reading as the group heading. */
.navc-modhead{display:flex;align-items:center;gap:9px;font-size:var(--fs-label);font-weight:700;letter-spacing:var(--tracking-long-label);text-transform:var(--case-long-label);color:var(--rail-muted);margin:13px 8px 3px;}
.navc-modhead i{font-size:13px;color:var(--blue-400);}
a.navc-scr{display:block;padding:8px 12px 8px 30px;color:var(--blue-200);text-decoration:none;font-size:13.5px;border-radius:var(--radius-md);}
a.navc-scr:hover{background:rgba(255,255,255,.08);color:#fff;}
a.navc-scr.active{background:var(--color-primary);color:#fff;font-weight:600;}
.navc-empty{color:var(--blue-400);font-size:12px;font-style:italic;margin:12px 10px;opacity:.7;}
.navc-tab:focus-visible,a.navc-scr:focus-visible,.navc-pin:focus-visible{outline:2px solid #fff;outline-offset:2px;}

/* main */
.main{flex:1;padding:0 0 40px;min-width:0;}  /* T3: min-width:0 lets inner table-scroll areas scroll instead of widening the page */
.topbar{display:flex;align-items:center;justify-content:space-between;padding:15px 26px;border-bottom:1px solid var(--color-border);background:var(--color-surface);position:sticky;top:0;z-index:10;}
.topbar .title{display:flex;align-items:center;gap:11px;font-weight:700;font-size:15px;color:var(--color-primary);}
.user{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--color-muted);}
.user .av{width:32px;height:32px;border-radius:50%;background:var(--blue-400);}
.wrap{padding:24px 26px;}
.crumb{font-size:13px;color:var(--color-muted);margin-bottom:16px;}
.crumb a{color:var(--color-primary);text-decoration:none;font-weight:600;}

/* BOSS 2026-08-04 — overflow:CLIP, not hidden. Both clip the same way (they keep the rounded corners off
   tables and toolbars), but `hidden` makes the card a scroll container, and a scroll container is where a
   position:sticky child sticks. With `hidden` the sticky toolbar below would compile, look correct, and do
   nothing on screen. `clip` does not create one, so the toolbar can pin to the viewport instead. */
.card{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);margin-bottom:20px;box-shadow:var(--shadow-card);overflow:clip;}

/* toolbar */
/* BOSS 2026-08-04 — the toolbar freezes on scroll so New / Save / Process / Delete stay reachable on a long
   entry form instead of making the user scroll back to the top. top:54px clears the sticky .topbar, and
   z-index:9 sits just under it — the same pair .form-actions already uses. No screen carries both, so they
   never collide. Pickers (z-index 1500) and dialogs (3500) still cover it. */
.toolbar{display:flex;align-items:center;gap:4px;padding:10px 14px;background:var(--color-bg);border-bottom:1px solid var(--color-border);position:sticky;top:54px;z-index:9;}
.tb{display:inline-flex;align-items:center;gap:7px;padding:9px 15px;border-radius:9px;font-size:13.5px;font-weight:600;color:var(--color-ink);cursor:pointer;background:transparent;border:none;text-decoration:none;}
.tb .ic{font-size:14px;color:var(--color-primary);}
.tb:hover{background:var(--color-primary-subtle);}
.tb.dis{color:#b3b9c8;cursor:not-allowed;pointer-events:none;}
.tb.dis .ic{color:#cdd2dd;}
.tb-sep{width:1px;height:22px;background:var(--color-border);margin:0 4px;}

/* tabs */
.tabs{display:flex;gap:4px;padding:0 16px;border-bottom:1px solid var(--color-border);background:var(--color-surface);}
.tabs a{padding:14px 22px;font-size:14px;font-weight:600;color:var(--color-muted);text-decoration:none;border-bottom:2px solid transparent;margin-bottom:-1px;}
.tabs a.active{color:var(--color-primary);border-bottom-color:var(--color-primary);}
/* #2: nested sub-tab strip (smaller, on a subtle surface so it reads as a level below the page tabs) */
.tabs.subtab{padding:0 10px;background:var(--color-bg-subtle);border-radius:var(--radius-md);}
.tabs.subtab a{padding:10px 16px;font-size:13px;}
/* D-290 W1 — the List / Forms tabs of every entry screen: one two-part segmented control. D-299 N13 — lightened to the
   field look: inactive = white field surface, field border, muted ink; active = light blue with dark blue text. */
.tabs.tabs-seg{padding:14px 20px;gap:0;}
.tabs-seg .seg{display:inline-flex;max-width:100%;border:1px solid var(--input-border);border-radius:9px;overflow:hidden;background:var(--color-surface);}
.tabs-seg .seg a{display:inline-flex;align-items:center;gap:9px;min-height:44px;padding:0 30px;margin:0;border:0;font-size:16px;font-weight:700;color:var(--color-muted);background:var(--color-surface);white-space:nowrap;}
.tabs-seg .seg a+a{border-left:1px solid var(--input-border);}
.tabs-seg .seg a.active{background:var(--blue-200);color:var(--blue-900);}
.tabs-seg .seg a:focus-visible{outline-offset:-5px;}
.tabs-seg .seg a.active:focus-visible{outline-color:var(--blue-900);}
/* D-299 N13 — List / Forms sits above the toolbar; a selector that belongs right below it (Data Configuration's
   Category, D-294 DC) shares its white band. */
.tabs.tabs-seg:has(+ .tabs-seg-sub){border-bottom:0;}
.tabs-seg-sub{padding:0 20px 14px;background:var(--color-surface);border-bottom:1px solid var(--color-border);}
@media (max-width:420px){ .tabs.tabs-seg{padding:12px 16px;} .tabs-seg .seg a{padding:0 20px;} }

.body{padding:24px 22px;}

/* notices */
.notice{border-radius:var(--radius-md);padding:12px 15px;font-size:14px;margin-bottom:18px;}
.notice.ok{background:var(--ok-bg);border:1px solid var(--ok-line);color:var(--ok);}
.notice.err{background:var(--danger-bg);border:1px solid var(--danger-line);color:var(--danger);}

/* form */
.form{max-width:660px;}
/* D-294 PW: an entry form with wide labels (the RPT forms, form.lbl-wide) uses the full content width, its
   header fields full width like every other entry screen. A form with its own inline max-width keeps it. */
form.form.lbl-wide{max-width:none;}
.frow{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:14px;}   /* R18 AL-LABEL: centred (was flex-start) */
.frow label{width:152px;text-align:right;font-size:13.5px;color:var(--color-ink);font-weight:600;flex-shrink:0;}
.req{color:var(--danger);}
.frow .opt{color:var(--color-muted);font-weight:500;}
.inp{flex:1;border:1px solid #CBD5E1;border-radius:9px;padding:11px 13px;font-size:14.5px;color:var(--color-ink);background:var(--color-surface);min-height:var(--control-h);}
.inp:focus{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(21,101,192,.15);}
.inp.sel{appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%235B6B7E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 13px center;background-size:11px;padding-right:34px;}
.inp.ro,.inp[readonly]{background:var(--color-bg-subtle);color:var(--color-muted);border-style:dashed;display:flex;align-items:center;justify-content:space-between;}
.inp.ro .lk{font-size:var(--fs-label);color:var(--color-muted);}
.inp:disabled{background:var(--color-bg-subtle);color:var(--color-muted);}
.inp.view{background:#fafbfe;color:var(--color-ink);}
.pwwrap{flex:1;display:flex;gap:8px;align-items:center;}
.pwwrap .inp{flex:1;}
.eye{border:1px solid #CBD5E1;background:var(--color-surface);border-radius:9px;padding:0 13px;min-height:var(--control-h);cursor:pointer;font-size:15px;}
.eye.on{background:var(--color-primary-subtle);border-color:var(--blue-400);}
.checks{margin:18px 0 0 166px;display:flex;flex-direction:column;gap:14px;}
.ck{display:flex;align-items:flex-start;gap:11px;}
.ck input{margin-top:2px;width:18px;height:18px;accent-color:var(--color-primary);}
.ck .t{display:block;font-size:14px;color:var(--color-ink);font-weight:600;}
.ck .d{display:block;margin-top:4px;font-size:12px;color:var(--color-muted);line-height:1.45;}
.recinfo{font-size:12.5px;color:var(--color-muted);margin:18px 0 0 166px;}
.actions{display:flex;gap:10px;justify-content:flex-end;margin-top:18px;}
/* sticky form action bar (pinned just below the topbar) */
.form-actions{position:sticky;top:54px;z-index:9;display:flex;gap:10px;justify-content:flex-start;align-items:center;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);box-shadow:var(--shadow-card);padding:12px 16px;margin-bottom:18px;}
.inperr{display:none;color:var(--danger);font-size:var(--fs-label);margin-top:3px;}
@media (max-width:768px){.form-actions{top:74px;}}

/* list / table */
.search-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:16px;}
.field{display:flex;align-items:center;gap:8px;border:1px solid #CBD5E1;border-radius:var(--radius-md);padding:8px 13px;background:var(--color-surface);font-size:14px;color:var(--color-muted);min-height:var(--control-h);}
.field input{border:none;outline:none;font-size:14px;background:transparent;color:var(--color-ink);}
.field.grow{flex:1;min-width:240px;}
.field.grow input{width:100%;}
/* LS — the List tab search box of a live search row: a fixed, shorter box beside the column dropdown
   instead of one stretched across the row. Shrinks on a narrow phone so the row never scrolls sideways. */
.field.grow.live-search{flex:0 1 var(--w-live-search);width:var(--w-live-search);max-width:100%;min-width:min(var(--w-live-search),100%);}
select.sel{border:1px solid #CBD5E1;border-radius:var(--radius-md);padding:10px 13px;font-size:14px;color:var(--color-muted);background:var(--color-surface);min-height:var(--control-h);}
/* inline label for the shared _ListPeriodFilter Year/Month selects that sit in a .search-row */
.lp-lbl{font-size:12.5px;font-weight:600;color:var(--color-ink);margin:0 2px 0 4px;}
table{width:100%;border-collapse:collapse;}
/* D-254 #5: column heads are shown as written (Title Case) instead of in caps. Most are short, but reports
   carry heads such as "Prior-Period Adjustments / Other Movements", and in caps those stacked three or four
   lines deep in a 160px column. Semibold + --color-muted + the --color-bg band keep the head clearly above the
   14px cells (5.1:1 contrast). Acronyms written in caps (UOM, TIN, ATC) stay in caps. */
thead th{background:var(--color-bg);text-align:left;font-size:var(--fs-label);letter-spacing:var(--tracking-long-label);text-transform:var(--case-long-label);color:var(--color-muted);font-weight:600;padding:12px 11px;border-bottom:1px solid var(--color-border);}
thead th.ctr{text-align:center;}
/* UI-05 (S-39): an amount / number column head sits right-aligned over its right-aligned amounts. The
   extra "table" keeps it above a page's own plain `table.grid th{text-align:left}`. */
table thead th.num{text-align:right;}
tbody td{padding:13px 11px;border-bottom:1px solid #EEF1F6;font-size:14px;vertical-align:middle;}
tbody td.ctr{text-align:center;}
tbody tr{cursor:pointer;}
tbody tr:hover{background:var(--color-bg);}
tbody tr.sel{background:var(--color-primary-subtle);box-shadow:inset 3px 0 0 var(--color-primary);}
.mono{font-variant-numeric:tabular-nums;color:var(--color-muted);}
.pill{display:inline-block;padding:4px 11px;border-radius:var(--radius-pill);font-size:var(--fs-label);font-weight:700;}
.pill.role{background:var(--color-bg-subtle);color:var(--color-muted);}
.pill.admin{background:var(--color-primary);color:#fff;}
.pill.no{background:var(--color-bg-subtle);color:var(--color-muted);}
/* UI-06 (S-63) — the one status-chip colour list (StatusDisplay.PillClass): green = done, blue = in progress,
   red = stopped, grey = draft / none. Amber (.pill.warn) only for a real warning. */
.pill.ok{background:var(--ok-bg);color:var(--ok);}
.pill.info{background:var(--info-bg);color:var(--info);}
.pill.danger{background:var(--danger-bg);color:var(--danger);}
.pill.neutral{background:var(--color-bg-subtle);color:var(--color-muted);}
.pill.warn{background:var(--warn-bg);color:var(--warn);}
/* Breach Alerts — severity + status pills (blue=info, amber/red=alert, per brand) */
.pill.sev-crit{background:var(--danger-bg);color:var(--danger);border:1px solid var(--danger-line);}
.pill.sev-high{background:var(--warn-bg);color:var(--warn);border:1px solid var(--warn-line);}
.pill.sev-med{background:var(--color-primary-subtle);color:var(--color-primary);}
.pill.sev-low{background:var(--color-bg-subtle);color:var(--color-muted);}
.pill.st-new{background:var(--warn-bg);color:var(--warn);border:1px solid var(--warn-line);}
.pill.st-ack{background:var(--color-primary-subtle);color:var(--color-primary);}
.pill.st-esc{background:var(--color-primary);color:#fff;}
.status{display:inline-flex;align-items:center;gap:7px;font-size:13.5px;color:var(--ok);font-weight:600;}
.status .dot{width:9px;height:9px;border-radius:50%;background:var(--ok);display:inline-block;}
.status.off{color:var(--color-muted);font-weight:500;}
.status.off .dot{background:#C4C9D4;}

.btn{border:none;border-radius:9px;padding:11px 18px;font-size:14px;font-weight:600;cursor:pointer;display:inline-flex;align-items:center;gap:7px;text-decoration:none;min-height:var(--control-h);}
.btn-primary{background:var(--color-primary);color:#fff;}
.btn-primary:hover{background:var(--color-primary-hover);}
.btn-ghost{background:var(--color-surface);border:1px solid #CBD5E1;color:var(--color-ink);}
.btn-ghost:hover{background:var(--color-bg);}
.btn-link{background:none;border:none;color:var(--color-primary);font-weight:700;cursor:pointer;font-size:13px;}

/* search modal */
.ua-modal-overlay{position:fixed;inset:0;background:rgba(13,43,94,.4);display:flex;align-items:flex-start;justify-content:center;padding-top:84px;z-index:50;}
.ua-modal{width:580px;max-width:92vw;background:var(--color-surface);border:1px solid var(--color-border);border-radius:14px;box-shadow:0 12px 36px rgba(13,43,94,.28);overflow:hidden;}
.ua-modal .mhead{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;border-bottom:1px solid var(--color-border);background:var(--color-bg);}
/* D-254 #5: the look belongs to the modal header, not to one heading level. A dialog's title is properly an h2;
   the screens use h3 today, and either now gets the same 15px primary title, so fixing the level later moves
   nothing on screen. (:is() keeps the specificity of the old `h3` selector.) */
.ua-modal .mhead :is(h2,h3){margin:0;font-size:15px;color:var(--color-primary);}
.ua-modal .mbody{padding:16px 18px;}
/* D-268 — the footer of a lookup pop-up that had none (dismiss on the left, then Select); same look as .acs-foot. */
.lookup-foot{display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:14px 18px;border-top:1px solid var(--color-border);background:var(--color-bg);}
/* A long list must not push that footer below the screen (the overlay is fixed, so it cannot be scrolled to): the
   modal stops at the viewport and its body scrolls instead. */
.ua-modal:has(> .lookup-foot){display:flex;flex-direction:column;max-height:calc(100vh - 100px);}
.ua-modal:has(> .lookup-foot) > .mbody{overflow:auto;min-height:0;}
.x{color:var(--color-muted);cursor:pointer;font-size:17px;text-decoration:none;}

/* keyboard focus visibility + table row links (accessibility batch 1) */
.btn:focus-visible,.tb:focus-visible,.tabs a:focus-visible,.eye:focus-visible,.btn-link:focus-visible,.rowlink:focus-visible,.x:focus-visible,.field input:focus-visible,select.sel:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px;border-radius:6px;}
/* nav focus handled by accordion rules above */
.rowlink{color:var(--color-muted);text-decoration:none;}
.rowlink:hover{text-decoration:underline;}

/* ===== Batch 2: responsive + polish ===== */
/* smooth hover/focus transitions */
.btn,.tb,.tabs a,.nav-mod,a.nav-item,.rowlink,.eye,tbody tr,.field,.inp,select.sel{transition:background-color .15s ease,color .15s ease,box-shadow .15s ease,border-color .15s ease;}

/* toolbar touch target */
.tb{min-height:44px;}

/* tighten inline row-link focus ring */
.rowlink:focus-visible{border-radius:3px;}

/* horizontal scroll for wide tables on small screens */
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;}

/* ===== Shared grid column widths (single source of truth) =====
   Every screen used to hand-set an inline `style="width:NNNpx"` on each <th>, so the same
   logical column drifted to a different width on every page — and several were sized by eye
   and quietly clipped real data. Use these classes on the <th> instead of a new inline width.

   Sizes are measured against REAL data (IFMIS_LIVE maxima) at the app's body font
   (Segoe UI 14px — note `.mono` only sets tabular-numerals, it is NOT a monospace family)
   plus the real cell chrome, so each width fits its longest value AND its header. The header sizes below were
   measured when heads were set in caps; since D-254 #5 they are Title Case, which is narrower, so they still fit:
     cell chrome = 16px td padding; input adds 28px; a <select> adds 28px; a lookup
     magnifier button adds 42px + a 6px flex gap.

   IMPORTANT: a column only gets the width you declare if the table has room for it. When the
   sum of the declared widths exceeds the table's width, the browser silently shrinks EVERY
   column proportionally and these values stop meaning anything. If you add a column, keep the
   table's `min-width` >= the sum of its column widths (the wrapping .table-scroll then scrolls).

   Deliberately scoped to `th`: `.col-` is Bootstrap's grid-column prefix and this sheet loads
   AFTER bootstrap, so an unscoped `.col-*` here would be a landmine the day someone writes a
   `.col-6` layout. These are table-header widths only — apply them to a <th>, never to a div. */
th.col-code{width:140px;}        /* plain (read-only) item/master code — max 15 ch "14111507-PP-M01" needs 131px */
th.col-code-sm{width:114px;}     /* short config / ATC / employee code (<=8 ch) — sized for the "EMPLOYEE ID" header in 12px caps (~111px) */
th.col-code-pick{width:215px;}   /* item code + lookup magnifier — 115 text + 28 input + 6 gap + 42 button + 16 pad = 211px */
th.col-acct-pick{width:180px;}   /* account code + lookup magnifier — the app's established Obligation/DV value */
th.col-uom{width:95px;}          /* plain-text UOM — shows the DESCRIPTION, max "Cubic Meter" needs 91px */
th.col-uom-sel{width:130px;}     /* UOM as a <select> — "Cubic Meter" + select arrow chrome needs 122px */
th.col-status{width:90px;}       /* status pill / PASS-FAIL — the "STATUS" header itself needs 67px */
th.col-check{width:80px;}        /* checkbox-only column — the "ACTIVE" header needs ~70px */
th.col-qty{width:95px;}          /* comma-formatted quantity */
th.col-tax{width:200px;}         /* DV VAT / EWT — a tax <select> + its computed amount underneath */
/* ===== E2E304 — shared report-filter field widths (single source of truth) =====
   `.fg` below carries `flex:1` (basis 0, grow 1), so a filter field STRETCHES to fill its row, and an
   inline `style="min-width:240px"` on a .fg only raises the shrink floor — it never caps the width. That
   is why the SAAOB Fund select rendered ~1288px to show a 22-character value, and why the same logical
   filter is a different width on every screen (Fund alone had six declared widths, in three different
   properties). Cap with a fixed flex BASIS, not a max-width: a max-width does cap the growth, but it
   still lets the field SHRINK in a crowded row, which is the same drift in the other direction.

   Measured against real data at the 14.5px control font plus the real control chrome (a <select> costs
   13px left pad + 34px right pad for the arrow + 2px border = 49px; each lookup button costs 40px + a
   6px gap):
     Fund   — longest FUND label "Special Education Fund" (22 ch ~163px) + 49px chrome = 212px -> 240px
     Date   — mm/dd/yyyy + the calendar button ~122px + 28px .inp padding = 150px            -> 170px
     Office — a disabled display box + 2 lookup buttons = 92px of chrome before any text     -> 300px
     Lookup — the same picker shape for a document no. / person (RFQ No, PO No, PR No,
              Custodian, Supplier, Payee, Account)                                            -> 300px
   The filter rows wrap (`flex-wrap:wrap` on .filt-row and .search-row), so a narrow viewport drops a
   field to the next line instead of squashing it; below 820px every capped field takes the full width.
   The very wide description controls are DELIBERATELY not in this standard and keep their own inline
   width: the PPE Property select (420px), the Asset Account / PPE Unit lookups (380px) and the Item
   pickers (340px) all show a full description, not a code.

   WHY EACH SELECTOR IS DOUBLED (`.fg.fg-fund`, not `.fg-fund`): `.fg{flex:1}` is declared further down this
   same sheet (line ~425). A single-class `.fg-fund` has the SAME specificity and loses to it purely on source
   order, so the cap would silently do nothing. Two classes (0,0,2,0) win regardless of where either rule sits,
   which keeps the standard safe against future edits that move blocks around. */
.fg.fg-fund{flex:0 0 240px;}
.fg.fg-date{flex:0 0 170px;position:relative;}
.fg.fg-office{flex:0 0 300px;}
.fg.fg-lookup{flex:0 0 300px;}
/* D-295 — a Year dropdown's field box is sized to the year (--w-year select), never stretched, so the next field
   sits right beside it. */
.fg.fg-year{flex:0 0 auto;min-width:0;}
/* Desc — a <select> over COA titles rather than short config labels. Measured on the longest ITEM_SUBCATEGORY
   description, "Information and Communication Technology Equipment" (50 ch ~365px), but capped at 340px: past that
   the filter row starts pushing a field to the next line on a laptop, and 340px still keeps two long sub-groups
   distinguishable in the closed select. This is the E2E304 home for the wide description controls that were
   previously carrying their own inline widths. */
.fg.fg-desc{flex:0 0 340px;}
/* E2E303 badge, protected: the range-error badge is appended INSIDE the To field's .fg. Inside a capped
   170px column its 76-character message would wrap to five lines and shove the whole filter row taller
   every time it appeared. Float it under the field instead — out of flow, so the row never changes
   height, and readable at its natural width. */
.fg-date > .cell-err{position:absolute;top:100%;left:0;z-index:3;width:max-content;max-width:320px;}
/* D-311 - the report Fund "Showing" chip (consolidated value): its own box at the right end of the filter row, as in
   the approved wb-report-AFTER picture. _FundFilterSelect moves it out of the 240px Fund field into the row; order
   places it after every field and margin-left:auto pushes it right. A full row wraps the chip alone to the next line,
   the fields keep their places. */
.fund-showing{order:999;margin-left:auto;align-self:center;flex:0 0 auto;max-width:250px;background:var(--color-primary-subtle);color:var(--blue-900);border:1px solid var(--blue-200);border-radius:var(--radius-sm);padding:8px 12px;font-size:12.5px;font-weight:600;line-height:1.35;}
/* a right-pushed field before it (e.g. the Post-Closing tick) keeps its place beside the chip */
.fg-actions ~ .fund-showing{margin-left:16px;}
@media print{.fund-showing{display:none !important;}}
@media (max-width:820px){
  /* phones: one filter per line beats four squashed ones. Doubled for the same reason as above — a media
     query adds no specificity, so a single-class rule here would lose to `.fg{flex:1}` too. */
  .fg.fg-fund,.fg.fg-date,.fg.fg-office,.fg.fg-lookup,.fg.fg-desc{flex:1 1 100%;}
  .fg-date > .cell-err{position:static;width:auto;max-width:none;}
}

/* mobile hamburger + drawer */
.topbar-left{display:flex;align-items:center;gap:11px;}
.rail-toggle{display:none;align-items:center;justify-content:center;width:42px;height:42px;border:1px solid var(--color-border);background:var(--color-surface);border-radius:var(--radius-md);color:var(--color-primary);font-size:20px;cursor:pointer;}
.rail-backdrop{display:none;position:fixed;inset:0;background:rgba(13,43,94,.4);z-index:55;}

@media (max-width:768px){
  .rail-toggle{display:inline-flex;}
  .rail{position:fixed;left:0;top:0;height:100vh;transform:translateX(-100%);transition:transform .2s ease;z-index:60;}
  .app.rail-open .rail{transform:translateX(0);}
  .app.rail-open .rail-backdrop{display:block;}
  .frow{flex-direction:column;align-items:stretch;gap:6px;}
  .frow label{width:auto;text-align:left;}
  .checks{margin-left:0;}
  .recinfo{margin-left:0;}
  .field-error{margin-left:0;}
  .inp,.field input,select.sel{font-size:16px;}
  .wrap{padding:16px;}
}

/* honor reduced motion */
@media (prefers-reduced-motion: reduce){
  *{transition:none !important;}
  .rail{transition:none !important;}
}

/* ===== Batch 3: inline field validation ===== */
/* ===== E2E40 — THE standard on-save validation badge (one definition, used app-wide) =====
   BOSS's finding: "in the purchase request under the field unit cost the prompt(badge) that appears
   upon saving if no value/incorrect value the badge appear — apply these to all menu items."
   Until now the SAME event looked three different ways: the browser's own grey "Please fill out this
   field" bubble wherever a bare `required` survived, a plain red sentence beside some fields, and a
   toast that faded before the operator could read it. From here a field that fails validation on Save
   wears ONE badge everywhere — house danger tokens, a warning glyph, sitting directly under the
   offending control, wrapping instead of clipping, and staying on screen until the value is fixed.
   Never amber and never green: amber/red are reserved for alerts, and this IS an alert.

   This is PRESENTATION ONLY. The server rules that decide whether a document saves are unchanged, and
   the red summary at the top of each form (what a keyboard/screen-reader user hits first, and what the
   server produces) is kept — the badge is the same message repeated AT the field so the operator does
   not have to hunt for which of nine rows the summary means.

   Two ways in, one look:
     .cell-err    — a badge placed by hand under a grid cell (line grids), shown/hidden via [hidden].
     .field-error — the asp-validation-for span the entry screens already render for each field; the
                    tag helper owns its text, so the warning glyph is drawn by CSS (::before). */
.cell-err,
.field-error{display:inline-flex;align-items:center;gap:6px;background:var(--danger-bg);border:1px solid var(--danger-line);color:var(--danger);border-radius:6px;padding:3px 8px;font-size:var(--fs-label);font-weight:600;line-height:1.35;
             /* the header columns are column-flex containers, where a flex item would otherwise
                stretch edge to edge — the badge must hug its message */
             align-self:flex-start;}
.cell-err{margin-top:5px;}
.cell-err[hidden]{display:none;}
.cell-err .ic{font-weight:700;}
/* The badge is a sibling of its row, so a left indent is what puts it UNDER the input instead of under the
   label. Every entry screen sizes its own label column, so the indent is a variable the screen overrides with
   its own (label width + row gap); 166px is the .frow default (152px label + 14px gap) used everywhere else. */
.field-error{margin:2px 0 8px var(--field-error-indent, 166px);}
.field-error::before{content:"\26A0";font-weight:700;line-height:1;}
.field-error:empty{display:none;}   /* this field is fine -> no badge at all */
/* The offending input itself: danger border plus a soft danger ring in the same token as the badge's
   fill, so the eye lands on the control the badge is talking about. */
.inp.bad{border-color:var(--danger);box-shadow:0 0 0 3px var(--danger-bg);}
.fld-err{color:var(--danger);font-size:12.5px;}
.fld-err:empty{display:none;}
/* top-of-form error summary: visible only when there are errors */
.val-summary.validation-summary-valid{display:none;}
.val-summary ul{margin:6px 0 0;padding-left:18px;}

/* logout button in topbar */
.logout-form{margin:0;}
.logout-btn{display:inline-flex;align-items:center;gap:6px;background:transparent;border:1px solid var(--color-border);color:var(--color-muted);border-radius:var(--radius-md);padding:6px 12px;font:600 13px var(--font-sans);cursor:pointer;min-height:36px;}
.logout-btn:hover{background:var(--color-bg);color:var(--color-primary);}
.logout-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px;}

/* ===== User Account Assignment (1B) ===== */
.gridbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:6px 0 10px;}
#assignGrid th.ctr,#assignGrid td.ctr{text-align:center;}
#assignGrid th.ctr a{font-size:var(--fs-label);color:var(--color-primary);text-decoration:none;font-weight:600;}
#assignGrid td.modc{font-weight:600;color:var(--color-muted);}
#assignGrid td.itemc{color:var(--color-ink);}
#assignGrid tr.newmod td{border-top:2px solid var(--color-border);}
#assignGrid input.gcb{width:17px;height:17px;accent-color:var(--color-primary);cursor:pointer;}
#assignGrid .modall-lbl{display:inline-flex;align-items:center;gap:8px;margin:0;color:var(--color-primary);font-weight:700;cursor:pointer;}
#assignGrid input.modall{width:17px;height:17px;accent-color:var(--color-primary);cursor:pointer;}
#assignGrid .cb-na{color:#c4c9d4;}
/* BOSS 2026-11-01 A1: the column heads stay in view just below the card's sticky Save toolbar. The page script
   sets --aa-head-top from the toolbar's measured bottom (54px + its height); 119px is the 1366 desktop value.
   Like table.sticky-head, the .table-scroll opens up (its sideways scroll would defeat vertical sticky) and the
   cells keep their own borders so scrolled rows never show through the opaque head. Below 821px the grid
   scrolls sideways as before and the head is not pinned. */
@media (min-width:821px){
  #assignGrid{border-collapse:separate;border-spacing:0;}
  #assignGrid > thead{position:sticky;top:var(--aa-head-top,119px);z-index:2;}
  .table-scroll:has(> #assignGrid){overflow:visible;}
}

/* ===== Authentication screens — Trust Blue blended redesign ===== */
.auth-body{
    margin:0; min-height:100vh; min-height:100dvh; color:#fff; position:relative; overflow-x:hidden; overflow-y:auto;
    display:flex; align-items:center; justify-content:center; padding:32px;
    background:
        radial-gradient(820px 560px at 14% 18%, rgba(91,155,213,.42), transparent 60%),
        radial-gradient(780px 680px at 88% 82%, rgba(13,71,161,.55), transparent 55%),
        radial-gradient(620px 460px at 72% 12%, rgba(21,101,192,.38), transparent 60%),
        linear-gradient(135deg, #0a2150 0%, var(--blue-900) 46%, #103a78 100%);
}
.auth-body::after{ content:""; position:fixed; inset:0; pointer-events:none; opacity:.05; mix-blend-mode:overlay;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
.auth-watermark{ position:fixed; left:-80px; bottom:-90px; width:560px; height:560px; opacity:.06; transform:rotate(-8deg); pointer-events:none; z-index:0; }
/* Municipality seal watermark (the Office Information logo) — large, faint, bottom-left, behind the split.
   seal-mode (the login page) hides the Migalink brand watermark so the office seal takes that corner. */
.auth-body .watermark{ position:fixed; left:-230px; bottom:-230px; width:600px; height:600px; object-fit:contain; opacity:.16; filter:grayscale(1) brightness(1.55); mix-blend-mode:soft-light; pointer-events:none; z-index:0; }
.auth-body.seal-mode .auth-watermark{ display:none; }
@media (max-width:820px){ .auth-body .watermark{ width:340px; height:340px; left:-150px; bottom:-150px; opacity:.08; } }
.auth-split{ position:relative; z-index:2; width:100%; max-width:1000px; display:grid; grid-template-columns:1.05fr .95fr; gap:48px; align-items:center; background:none; }
.auth-brand{ background:none; padding:8px 8px 8px 12px; animation:authrise .7s ease both; }
.auth-mark{ display:flex; align-items:center; gap:14px; }
.auth-mark svg{ filter:drop-shadow(0 6px 16px rgba(0,0,0,.35)); }
.auth-wordmark{ font-size:30px; letter-spacing:-.01em; color:#fff; }
.auth-wordmark b{ font-weight:800; } .auth-wordmark span{ color:var(--blue-200); font-weight:700; margin-left:3px; }
.auth-headline{ font-size:38px; font-weight:300; line-height:1.15; margin:28px 0 14px; letter-spacing:-.02em; }
.auth-headline b{ font-weight:700; }
.auth-tagline{ color:#cfe0f5; font-size:15px; line-height:1.7; max-width:380px; }
.auth-accent{ width:54px; height:4px; border-radius:2px; background:linear-gradient(90deg,var(--blue-400),var(--blue-200)); margin:22px 0 0; }
.auth-bullets{ list-style:none; padding:0; margin:22px 0 0; display:flex; flex-wrap:wrap; gap:10px 24px; color:#cfe0f5; font-size:14px; }
.auth-bullets li{ position:relative; padding-left:16px; }
.auth-bullets li::before{ content:""; position:absolute; left:0; top:50%; transform:translateY(-50%); width:6px; height:6px; border-radius:50%; background:var(--blue-200); }
/* Finding #116 — DPA notice is fine-print, de-emphasized. MT151: sits a little higher in the brand column (was margin-top:64px).
   D-254 #5: 12px, and --auth-fineprint so it still passes WCAG AA on the lightest part of the login gradient. */
.auth-privacy{ display:flex; align-items:flex-start; gap:8px; margin-top:32px; color:var(--auth-fineprint); font-size:var(--fs-label); line-height:1.55; max-width:360px; }
.auth-privacy i{ font-size:13px; opacity:.7; margin-top:1px; }
.auth-form{ display:flex; align-items:center; justify-content:center; padding:0; }
.auth-card{ width:100%; max-width:380px; background:rgba(255,255,255,.10); backdrop-filter:blur(16px) saturate(120%); -webkit-backdrop-filter:blur(16px) saturate(120%); border:1px solid rgba(255,255,255,.20); border-radius:20px; padding:34px 32px; box-shadow:0 24px 60px rgba(5,17,40,.45); animation:authrise .7s .12s ease both; }
.facility{ display:flex; flex-direction:column; align-items:center; text-align:center; margin-bottom:16px; }
.facility-logo{ max-height:60px; max-width:200px; object-fit:contain; }
.facility-name{ margin-top:8px; font-weight:700; font-size:12.5px; letter-spacing:.08em; color:#dce8fb; }
.auth-title{ font-size:22px; font-weight:700; color:#fff; margin:2px 0 2px; text-align:center; }
.auth-sub-card{ color:#bcd0ec; font-size:13px; margin:0 0 18px; text-align:center; }
.auth-label{ display:block; font:600 var(--fs-label) var(--font-sans); letter-spacing:var(--tracking-short-label); text-transform:var(--case-short-label); color:#bcd0ec; margin:12px 0 6px; }
.auth-card .inp{ width:100%; height:46px; border-radius:11px; padding:0 14px; font-size:15px; color:#fff; background:rgba(255,255,255,.10); border:1px solid rgba(255,255,255,.22); }
.auth-card .inp::placeholder{ color:rgba(255,255,255,.55); }
.auth-card .inp:focus{ outline:none; border-color:var(--blue-200); box-shadow:0 0 0 3px rgba(191,217,242,.22); background:rgba(255,255,255,.14); }
.auth-card .pwwrap{ position:relative; }
.auth-card .pwwrap .inp{ width:100%; padding-right:66px; }
.auth-card .eye{ position:absolute; right:6px; top:50%; transform:translateY(-50%); height:34px; border-radius:8px; padding:0 12px; background:transparent; border:none; color:#bcd0ec; cursor:pointer; font-size:var(--fs-label); font-weight:700; letter-spacing:.06em; }
.auth-card .eye:hover{ background:rgba(255,255,255,.14); color:#fff; }
.auth-submit{ width:100%; height:48px; border:0; border-radius:11px; font-size:15px; font-weight:700; cursor:pointer; background:#fff; color:var(--blue-900); box-shadow:0 10px 24px rgba(0,0,0,.28); transition:transform .12s ease, box-shadow .15s; margin-top:18px; }
.auth-submit:hover{ transform:translateY(-1px); box-shadow:0 14px 30px rgba(0,0,0,.34); }
.auth-card .notice{ margin-bottom:14px; }
.auth-forgot{ text-align:center; margin-top:14px; }
.auth-forgot a{ color:#bcd0ec; font-size:13px; font-weight:600; text-decoration:none; }
.auth-forgot a:hover{ color:#fff; text-decoration:underline; }
.auth-powered{ display:flex; align-items:center; justify-content:center; gap:8px; margin-top:18px; padding-top:14px; border-top:1px solid rgba(255,255,255,.14); color:#bcd0ec; font-size:12px; }
.auth-powered b{ color:#fff; font-weight:800; letter-spacing:.04em; }
.auth-powered svg{ width:18px; height:18px; }
@keyframes authrise{ from{opacity:0; transform:translateY(14px);} to{opacity:1; transform:none;} }
@media (max-width:820px){ .auth-body{ align-items:flex-start; padding:20px 16px 40px; } .auth-split{ grid-template-columns:1fr; gap:26px; max-width:440px; } .auth-brand{ text-align:center; } .auth-mark{ justify-content:center; } .auth-accent{ margin-inline:auto; } .auth-tagline{ margin-inline:auto; } .auth-headline{ font-size:30px; } }
@media (prefers-reduced-motion:reduce){ .auth-brand, .auth-card{ animation:none; } }

/* ===== Global mobile responsiveness for the shared entry forms (2026-07-24) =====
   The 17 transactional entry screens share .pr-head / .pr-col / .prow / .lookup / .toolbar.
   On phones & portrait tablets (<=820px) this stacks the two-column header to one column,
   puts each field's label ABOVE its input (so the input gets full width instead of being
   pushed off-screen), and wraps the action toolbar so Save/Process/Print stay reachable.
   Scoped to <=820px so desktop and landscape-tablet layouts are unchanged; !important is
   needed only to override the per-page inline .prow/.pr-head definitions. Line-item grids
   keep their own .table-scroll horizontal scroll. */
@media (max-width:820px){
  .toolbar{ flex-wrap:wrap !important; row-gap:2px; }
  .tabs{ overflow-x:auto; -webkit-overflow-scrolling:touch; }
  .pr-head, .ob-head, .dv-head, .jev-head, .be-head, .adj-head, .iss-head{ grid-template-columns:1fr !important; gap:12px 0 !important; }
  /* grid items default to min-width:auto and won't shrink to their column — let them, so wide
     lookup rows (code-box + name + magnifier) stay inside the card instead of clipping the button */
  .pr-col, .ob-col, .dv-col, .jev-col, .be-col, .adj-col, .iss-col{ min-width:0; }
  .prow{ flex-direction:column !important; align-items:stretch !important; gap:5px !important; }
  .prow.align-top{ align-items:stretch !important; }
  .prow > label{ width:auto !important; flex:0 0 auto !important; }
  /* E2E40 — stacked rows have no label column left to clear, so the badge starts at the edge like its
     input. !important because each screen sets its own indent in its page <style>, which loads after us. */
  .field-error{ margin-left:0 !important; }
  .prow > .inp, .prow > .lookup, .prow > .coa-lookup, .prow > .type-radios{ width:100%; }
  /* keep the magnifier lookup button visible: let the name field shrink (flexbox min-width trap)
     and pin the magnifier so it never gets pushed off the card edge */
  .lookup, .coa-lookup{ min-width:0; flex-wrap:nowrap; }
  .lookup .inp, .coa-lookup .inp, .lookup .grow, .coa-lookup .grow{ min-width:0; }
  .coa-mag{ flex:0 0 auto; }
  .type-radios{ flex-wrap:wrap; gap:10px 18px; }
  .actions{ flex-wrap:wrap; }
  /* topbar: reclaim the 30px overflow the office-name + account cluster caused on small phones */
  .topbar{ padding-inline:12px !important; gap:8px; }
  .topbar .title, .topbar-left{ min-width:0; overflow:hidden; }
  .topbar .title{ font-size:13.5px; white-space:nowrap; text-overflow:ellipsis; }
  .user{ gap:6px; }
  body, .main{ overflow-x:hidden; }
}

/* ===== Patient screens ===== */
.sec{font-size:13px;font-weight:700;color:#3a3f4c;margin:2px 0 14px;}
.fg{display:flex;flex-direction:column;gap:6px;flex:1;min-width:160px;}
/* D-254 #5: the field caption is 12px (the floor) and takes --color-muted, the token for secondary text, in
   place of the stray #6a7080 it used to hard-code. */
.fg label{font-size:var(--fs-label);font-weight:600;color:var(--color-muted);width:auto;text-align:left;}
/* field-block: legacy field wrapper used on several screens (Receive/Adjust/Orders/Rx/Dispense/Lab/Billing).
   Align it to the .fg standard — label above box, 6px gap — without .fg's flex:1/min-width so fixed-width
   inline fields (e.g. the receipt's Qty/Unit columns) keep their widths. */
.field-block{display:flex;flex-direction:column;gap:6px;}
.field-block > label{font-size:var(--fs-label);font-weight:600;color:var(--color-muted);text-align:left;}
.val{border:1px solid #EDF0F5;background:#FAFBFE;border-radius:9px;padding:10px 12px;font-size:14px;color:var(--color-ink);}

/* ===== Notification bell (topbar) ===== */
.notif-bell{position:relative;display:inline-flex;}
.notif-bell-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border:0;border-radius:var(--radius-pill);background:transparent;color:var(--color-muted);cursor:pointer;font-size:18px;}
.notif-bell-btn:hover{background:var(--color-bg-subtle);color:var(--color-primary);}
.notif-badge{position:absolute;top:4px;right:4px;min-width:17px;height:17px;padding:0 4px;border-radius:var(--radius-pill);background:var(--danger);color:#fff;font-size:var(--fs-label);font-weight:700;line-height:17px;text-align:center;box-shadow:0 0 0 2px var(--color-surface);}
.notif-pop{position:absolute;right:0;top:46px;width:340px;max-width:88vw;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);box-shadow:0 18px 50px rgba(13,43,94,.18);z-index:1500;overflow:hidden;}
.notif-pop-head{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;border-bottom:1px solid var(--color-border);font-weight:700;font-size:14px;color:var(--color-ink);}
.notif-pop-allread{border:0;background:transparent;color:var(--color-primary);font-size:12.5px;font-weight:600;cursor:pointer;}
.notif-pop-allread:hover{text-decoration:underline;}
.notif-pop-list{max-height:340px;overflow-y:auto;}
.notif-pop-empty{padding:22px 14px;text-align:center;color:var(--color-muted);font-size:13px;}
.notif-pop-item{display:flex;gap:10px;padding:11px 14px;border-bottom:1px solid var(--color-border);color:inherit;text-decoration:none;}
.notif-pop-item:last-child{border-bottom:0;}
/* Only linkable items (rendered as <a>) look clickable. */
a.notif-pop-item{cursor:pointer;}
a.notif-pop-item:hover{background:var(--color-bg);text-decoration:none;color:inherit;}
.notif-pop-item.unread{background:var(--color-primary-subtle);}
.notif-pop-item-title{font-size:13.5px;font-weight:600;color:var(--color-ink);}
.notif-pop-item-body{font-size:12.5px;color:var(--color-muted);margin-top:2px;}
.notif-pop-item-meta{font-size:var(--fs-label);color:var(--color-muted);margin-top:3px;}
.notif-pop-foot{display:block;padding:11px 14px;text-align:center;font-size:13px;font-weight:600;color:var(--color-primary);border-top:1px solid var(--color-border);text-decoration:none;}
.notif-pop-foot:hover{background:var(--color-bg);}
.notif-dot{flex:0 0 auto;width:8px;height:8px;margin-top:6px;border-radius:50%;background:var(--color-primary);}
.notif-pop-item.read .notif-dot,.notif-row.read .notif-dot{background:var(--color-border);}

/* ===== Notifications page (full list) ===== */
.notif-list{list-style:none;margin:0;padding:0;}
.notif-row{display:flex;gap:12px;align-items:flex-start;padding:14px 4px;border-bottom:1px solid var(--color-border);}
.notif-row:last-child{border-bottom:0;}
.notif-row.unread,.notif-row:has(a.notif-open){cursor:pointer;}
.notif-row.unread{background:var(--color-primary-subtle);border-radius:var(--radius-sm);padding-inline:12px;}
.notif-main{flex:1;min-width:0;}
.notif-title{font-size:14.5px;font-weight:600;color:var(--color-ink);}
.notif-body{font-size:13px;color:var(--color-muted);margin-top:3px;}
.notif-meta{font-size:12px;color:var(--color-muted);margin-top:5px;}
.notif-meta a{color:var(--color-primary);}
.notif-mark{flex:0 0 auto;width:36px;height:36px;border:1px solid var(--color-border);border-radius:var(--radius-pill);background:var(--color-surface);color:var(--color-primary);cursor:pointer;}
.notif-mark:hover{background:var(--color-primary-subtle);}

/* ===== N1 profile dropdown / N3 screen close / N10 sidebar minimize / N11 recents (2026-06-11) ===== */
.profile-wrap{position:relative;display:inline-flex;}
.avatar-btn{width:38px;height:38px;border-radius:50%;border:none;background:var(--color-primary);color:#fff;font-weight:700;font-size:13.5px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;letter-spacing:.02em;}
.avatar-btn:hover{background:#0D47A1;}
.profile-menu{position:absolute;right:0;top:46px;min-width:230px;background:var(--color-surface);border:1px solid var(--color-border);border-radius:12px;box-shadow:0 12px 36px rgba(13,43,94,.18);padding:6px;z-index:1500;}
.profile-menu-head{padding:10px 12px;border-bottom:1px solid var(--color-border);margin-bottom:6px;}
.profile-menu a,.profile-menu button{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;font-size:14px;color:var(--color-ink);background:none;border:none;border-radius:8px;text-decoration:none;cursor:pointer;text-align:left;min-height:42px;}
.profile-menu a:hover,.profile-menu button:hover{background:var(--color-primary-subtle);color:var(--color-primary);}
.profile-menu-divider{border-top:1px solid var(--color-border);margin:6px 0;}
.profile-badge{margin-left:auto;background:#B42318;color:#fff;font-size:var(--fs-label);font-weight:700;border-radius:999px;padding:2px 7px;}
.screen-close{width:38px;height:38px;border:1px solid var(--color-border);background:var(--color-surface);border-radius:var(--radius-md);color:var(--color-muted);font-size:15px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;margin-left:4px;}
.screen-close:hover{color:#B42318;border-color:#B42318;background:#FEF3F2;}
.rail-min-toggle{display:inline-flex;align-items:center;justify-content:center;width:42px;height:42px;border:1px solid var(--color-border);background:var(--color-surface);border-radius:var(--radius-md);color:var(--color-primary);font-size:18px;cursor:pointer;}
.app.rail-min .rail{display:none;}
@media (max-width: 900px){ .rail-min-toggle{display:none;} }  /* mobile keeps the overlay hamburger */
.recent-box{margin-top:auto;padding:12px 14px;border-top:1px solid rgba(255,255,255,.12);}
.recent-title{font-size:var(--fs-label);font-weight:700;letter-spacing:var(--tracking-short-label);text-transform:var(--case-short-label);color:var(--rail-muted);margin-bottom:6px;}
.recent-item{display:flex;align-items:center;gap:8px;padding:7px 8px;font-size:12.5px;color:rgba(255,255,255,.75);text-decoration:none;border-radius:7px;}
.recent-item:hover{background:rgba(255,255,255,.08);color:#fff;}

/* ===== Q2/Q3/Q4 sidebar polish (2026-06-12) ===== */
.brand{position:relative;}
.rail-collapse-btn{margin-left:auto;width:30px;height:30px;border-radius:50%;border:1px solid rgba(255,255,255,.25);background:rgba(255,255,255,.08);color:var(--blue-200);font-size:13px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:all .15s ease;}
.rail-collapse-btn:hover{background:#fff;color:var(--color-primary);border-color:#fff;transform:scale(1.06);}
.rail-restore-btn{display:none;width:38px;height:38px;border-radius:50%;border:none;background:var(--color-primary);color:#fff;font-size:14px;cursor:pointer;align-items:center;justify-content:center;box-shadow:0 3px 10px rgba(21,101,192,.35);transition:all .15s ease;}
.rail-restore-btn:hover{background:#0D47A1;transform:scale(1.06);}
.app.rail-min .rail-restore-btn{display:inline-flex;}
.rail-resizer{position:absolute;top:0;right:0;width:6px;height:100%;cursor:col-resize;z-index:5;}
.rail-resizer:hover{background:rgba(21,101,192,.35);}
@media (max-width:900px){ .rail-resizer,.rail-collapse-btn,.rail-restore-btn{display:none !important;} }

/* ===== IFMIS blueprint additions (2026-06-15) ===== */
/* Locked / not-yet-implemented finance modules in the sidebar (shell-dashboard blueprint). */
.nav-locked-head{font-size:var(--fs-label);font-weight:700;letter-spacing:var(--tracking-short-label);text-transform:var(--case-short-label);color:var(--rail-muted);margin:14px 8px 4px;}
.nav-item.locked{display:flex;align-items:center;justify-content:space-between;color:rgba(255,255,255,.38);cursor:not-allowed;pointer-events:none;}
.nav-item.locked .lk{font-size:var(--fs-label);opacity:.8;}

/* Dashboard — finance placeholder cards + clearly-marked sample data (shell-dashboard blueprint). */
.mock-banner{display:flex;align-items:center;gap:10px;background:var(--info-bg);border:1px solid var(--blue-200);color:var(--blue-800);border-radius:var(--radius-md);padding:11px 15px;font-size:13.5px;font-weight:600;margin-bottom:18px;}
.dash-asof{font-size:var(--fs-label);color:var(--color-muted);margin-top:4px;}
.dash-head{display:flex;align-items:center;gap:8px;font-size:var(--fs-sm);font-weight:600;color:var(--color-muted);text-transform:var(--case-short-label);letter-spacing:var(--tracking-short-label);margin:var(--space-5) 0 0;}
.dash-head .sample{background:var(--color-bg-subtle);color:var(--color-muted);font-size:var(--fs-label);font-weight:700;letter-spacing:.05em;padding:2px 8px;border-radius:var(--radius-pill);text-transform:none;}
.dash-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(236px,1fr));gap:var(--space-4);margin-top:var(--space-3);}
.stat{text-decoration:none;display:block;transition:transform .15s ease,box-shadow .15s ease;}
.stat:hover{transform:translateY(-1px);}
.stat .body{display:flex;align-items:center;gap:var(--space-3);padding:18px 18px;}
.stat .ic{width:46px;height:46px;border-radius:var(--radius-md);flex:none;font-size:20px;display:flex;align-items:center;justify-content:center;background:var(--color-primary-subtle);color:var(--color-primary);}
.stat .num{font-size:26px;font-weight:700;color:var(--color-ink);line-height:1;font-variant-numeric:tabular-nums;}
.stat .lbl{font-size:var(--fs-sm);color:var(--color-muted);margin-top:3px;}
.stat .sub{font-size:var(--fs-label);color:var(--color-muted);margin-top:2px;}
.stat .ic.ok{background:var(--ok-bg);color:var(--ok);}
.stat .ic.warn{background:var(--warn-bg);color:var(--warn);}

/* Change Password — live policy checklist (change-password blueprint). Rendered inside the
   glassmorphic .auth-card, so colours match the dark auth chrome rather than the app surface. */
.policy{margin-top:16px;padding:14px 15px;border-radius:12px;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.16);}
.policy-title{font-size:var(--fs-label);font-weight:700;letter-spacing:var(--tracking-short-label);text-transform:var(--case-short-label);color:#bcd0ec;margin-bottom:9px;}
.policy ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px;}
.policy li{display:flex;align-items:center;gap:9px;font-size:13px;color:#cfe0f5;}
.policy li i{font-size:15px;color:rgba(255,255,255,.45);}
.policy li.met{color:#d7f3df;}
.policy li.met i{color:#7ee2a0;}
.match-msg{margin-top:10px;font-size:12.5px;color:#cfe0f5;min-height:18px;}
.match-msg.ok{color:#7ee2a0;}
.match-msg.bad{color:#ffc9c9;}

/* Informational / warning notice variants (Office Information + Audit footer). */
.notice.info{background:var(--info-bg);border:1px solid var(--blue-200);color:var(--blue-800);}
.notice.warn{background:var(--warn-bg);border:1px solid var(--warn-line);color:var(--warn);}
.page-title{font-size:20px;color:var(--color-ink);margin:0 0 14px;}

/* Office Information — logo uploader (office-information blueprint). */
.logo-uploader{display:flex;align-items:center;gap:20px;flex-wrap:wrap;}
.logo-preview{width:120px;height:120px;border:1px dashed var(--color-border);border-radius:var(--radius-md);background:var(--color-bg-subtle);display:flex;align-items:center;justify-content:center;overflow:hidden;flex:none;}
.logo-preview img{max-width:100%;max-height:100%;object-fit:contain;}
.logo-preview .ph{font-size:34px;color:var(--color-muted);}
.uploader-actions{display:flex;flex-direction:column;gap:8px;align-items:flex-start;}
.file-hint{font-size:12px;color:var(--color-muted);}

/* ===== Finding #9 — required-field asterisk =====
   Add class "req-star" to a <span> after a required label, OR class "req-label" on the
   label itself to auto-append the red *. (.req already exists for inline use.) */
.req-star{color:var(--danger);font-weight:700;margin-left:2px;}
.req-label::after{content:" *";color:var(--danger);font-weight:700;}

/* ===== Finding #4 — shared styled confirm/alert dialog + toast (tokens only) ===== */
.ifmis-dialog-overlay{position:fixed;inset:0;background:rgba(13,43,94,.45);z-index:3500;display:flex;align-items:center;justify-content:center;padding:24px;animation:ifmisDlgFade .12s ease both;}
.ifmis-dialog{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);max-width:420px;width:100%;padding:22px 24px;box-shadow:0 18px 50px rgba(13,43,94,.28);animation:ifmisDlgPop .14s ease both;}
.ifmis-dialog-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px;}
.ifmis-dialog-icon{font-size:22px;line-height:1;margin-top:1px;color:var(--color-primary);}
.ifmis-dialog-icon.k-danger{color:var(--danger);}
.ifmis-dialog-icon.k-warn{color:var(--warn);}
.ifmis-dialog-icon.k-ok{color:var(--ok);}
.ifmis-dialog-icon.k-info{color:var(--color-primary);}
.ifmis-dialog-title{font-size:17px;font-weight:700;color:var(--color-ink);margin:0;line-height:1.3;}
.ifmis-dialog-body{color:var(--color-muted);line-height:1.55;font-size:14.5px;margin-bottom:20px;white-space:pre-line;}
.ifmis-dialog-actions{display:flex;justify-content:flex-end;gap:10px;}
.ifmis-dialog-actions .btn{min-height:44px;}
.ifmis-dialog-danger.btn-primary{background:var(--danger);border-color:var(--danger);}
.ifmis-dialog-danger.btn-primary:hover{filter:brightness(.92);}
@keyframes ifmisDlgFade{from{opacity:0;}to{opacity:1;}}
@keyframes ifmisDlgPop{from{opacity:0;transform:translateY(10px) scale(.98);}to{opacity:1;transform:none;}}

/* toast stack — top-right, stacks downward */
#ifmisToastHost{position:fixed;top:18px;right:18px;z-index:3600;display:flex;flex-direction:column;gap:10px;max-width:380px;width:calc(100vw - 36px);pointer-events:none;}
.ifmis-toast{pointer-events:auto;display:flex;align-items:flex-start;gap:10px;padding:13px 14px;border-radius:var(--radius-md);background:var(--color-surface);border:1px solid var(--color-border);border-left:4px solid var(--color-primary);box-shadow:0 10px 30px rgba(13,43,94,.18);font-size:14px;color:var(--color-ink);opacity:0;transform:translateX(16px);transition:opacity .2s ease,transform .2s ease;}
.ifmis-toast.show{opacity:1;transform:none;}
.ifmis-toast-ic{font-size:17px;line-height:1.4;color:var(--color-primary);flex:none;}
.ifmis-toast-msg{flex:1;line-height:1.45;}
.ifmis-toast-x{flex:none;border:0;background:transparent;color:var(--color-muted);cursor:pointer;font-size:13px;padding:2px 4px;border-radius:6px;}
.ifmis-toast-x:hover{background:var(--color-bg-subtle);color:var(--color-ink);}
.ifmis-toast.t-success{border-left-color:var(--ok);}
.ifmis-toast.t-success .ifmis-toast-ic{color:var(--ok);}
.ifmis-toast.t-error{border-left-color:var(--danger);}
.ifmis-toast.t-error .ifmis-toast-ic{color:var(--danger);}
.ifmis-toast.t-warn{border-left-color:var(--warn);}
.ifmis-toast.t-warn .ifmis-toast-ic{color:var(--warn);}
.ifmis-toast.t-info{border-left-color:var(--color-primary);}
@media (prefers-reduced-motion:reduce){.ifmis-dialog-overlay,.ifmis-dialog,.ifmis-toast{animation:none !important;transition:none !important;}}

/* numeric data-entry inputs — right-aligned, no spinners (shared utility for money/qty/rate fields) */
.num-input{text-align:right;}
input[type=number].num-input::-webkit-outer-spin-button,
input[type=number].num-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
.num-input[type=number]{-moz-appearance:textfield;}

/* ===== TABLET TOUCH TARGETS — the 44px house standard (2026-07-29) =====
   A live audit at 1280x800 with touch enabled measured a set of controls below the 44px minimum
   CLAUDE.md sets (`--control-h:44px`). They are raised here, in ONE place, rather than in the
   seventeen page <style> blocks that each carry their own copy of `.spec-rm` / `.spec-add`.

   HOW THESE RULES WIN. This sheet is linked in <head> BEFORE each page's own <style> (the Razor
   "Styles" section), so a same-specificity rule here would silently lose on source order. Every
   rule below is therefore ELEMENT-QUALIFIED (`button.spec-rm`, specificity 0,0,1,1) so it beats
   the page's single-class copy (0,0,1,0) on specificity, in whatever order the two sheets land.
   That is deliberate: no `!important`, and a screen that genuinely needs something different can
   still say so with two classes.

   TWO TECHNIQUES, chosen per control:
     (a) REAL SIZE — `min-height` / `width` — used where the extra pixels land in space the screen
         already has (a table row that is taller than its button, a sidebar that already scrolls).
     (b) INVISIBLE HIT AREA — a transparent, absolutely-positioned ::after centred on the control —
         used where growing the box would push the page around: the topbar, the sidebar brand row,
         a modal header, the "Add" link under a grid. The glyph does not move by one pixel and
         nothing reflows; only the tappable rectangle grows.
   Technique (b) is used ONLY on controls that stand alone. It is deliberately NOT used on stacked
   lists (the sidebar), because a 44px strip over a 36px row would overlap its neighbours and the
   overlap would tap whichever row paints last — a mis-tap is worse than a small target. */

/* --- (a) real-size raises ------------------------------------------------ */

/* Transaction Approval + Workflow Report row actions — 36px -> 44px.
   THE priority of the audit: this is the screen a department head works on a tablet. The inbox row
   is a grid row with nothing else in it, so the 8px lands in the row and no column moves. */
button.btn-approve,button.btn-disapprove,button.btn-hist,a.btn-hist{min-height:44px;}

/* Line-grid remove (trash) button — 38/40px -> 44px, every entry screen.
   The line rows already stand ~54px tall (they hold `.inp`, min-height 44), so the row does not
   grow; the action column widens by 4px, which the grid's own .table-scroll absorbs. */
button.spec-rm{min-height:44px;min-width:44px;width:44px;}

/* Bid Evaluation "View" for the technical / financial requirements — 38.3px -> 44px. */
@media (pointer:coarse){ button.dotbtn{min-height:44px;} }   /* touch only — on a mouse this grew the abstract table 17px for nothing */

/* Sidebar screen links — 36.3px -> 44.3px, and the pinned Dashboard link 43px -> 44px.
   Padding only: the label, the indent and the type size are untouched. This is the one raise that
   costs real estate (the rail's content grows ~216px and it already scrolls), and it is taken
   anyway because these ARE the navigation targets on the tablet. The uppercase module headings
   (.navc-modhead) are NOT raised — they are labels, not controls — and the Setup/Entry/Reports
   tab strip is already 51.8px. */
/* GATED TO TOUCH DEVICES (2026-07-29 review). Raising all 28 rail links adds 217px to a rail that already
   scrolls in an 800px viewport — a real cost, and a mouse does not need a 44px target. pointer:coarse means a
   finger, so tablets get the bigger targets and the laptops in the room keep their rail exactly as it was. */
@media (pointer:coarse){
    a.navc-scr{padding-top:12px;padding-bottom:12px;}
}

/* --- (b) invisible hit areas (zero reflow) ------------------------------- */
/* `min-width/height:100%` keeps a control that is ALREADY wider or taller than 44px at its own
   size — the rectangle only ever grows. `border-radius:inherit` keeps the (invisible) shape
   honest for anything that ever gets a debug outline. */
.screen-close,.rail-collapse-btn,button.spec-add,.x{position:relative;}
.screen-close::after,.rail-collapse-btn::after,button.spec-add::after,.x::after{
    content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
    width:44px;min-width:100%;height:44px;min-height:100%;border-radius:inherit;}

/* Grid row links (the document-number link in every register) — the LINK is 19px tall, but its
   CELL is ~48px and the whole <tr> already carries `onclick="location.href='?id=…'"`. So the fix
   is the one the brief asks for: make the CELL the hit area. The ::after fills the cell (it is
   absolutely positioned against the <td>, which :has() makes the containing block), so the tap
   target becomes the full cell while the link text, the row height and the register's row count
   stay EXACTLY as they are. Scoped to `:only-child` so a cell that mixes a rowlink with other
   content is never covered. */
td:has(> a.rowlink:only-child){position:relative;}
td > a.rowlink:only-child::after{content:"";position:absolute;inset:0;}

/* ===== SCROLL AFFORDANCE ON WIDE GRIDS (2026-07-29) =====
   Wide grids have always scrolled correctly inside .table-scroll — the defect is that nothing said
   so. `offsetHeight - clientHeight` is 0, and with touch enabled Chrome draws overlay scrollbars
   that only appear mid-gesture, so on Disbursement the operator saw "Account Code / Account
   Description / SL Type / SL Reference" with DEBIT and CREDIT off-screen and no sign they existed.

   Two parts, both driven generically by js/table-scroll-cue.js — no per-screen code:
     .ts-more  a soft fade over the last 34px of the scrollport, so the grid visibly continues.
     .ts-cue   a small in-flow line under the grid NAMING the columns that are currently off-screen.

   The fade is a MASK on .table-scroll itself, not an overlay element. That matters: a mask paints
   with the element (it does not scroll away like an absolutely-positioned child would), it needs
   no wrapper div in markup no page controls, and — verified in Chrome — it does NOT take part in
   hit testing, so a cell or an action button under the fade is still clickable. Both parts appear
   only while there is more to the right and both vanish at the end of the scroll, so the last
   column (on the approval inbox: View and Action) is never faded at the moment you reach for it.
   The cue is in normal flow BELOW the grid, so it can never cover a cell or a row's buttons. */
/* `black`/`transparent` here are MASK ALPHA, not colour — "keep this" / "fade this out". No brand
   colour is being hard-coded: the grid fades to whatever the card behind it is painted with, so it
   follows the tokens automatically. */
.table-scroll.ts-more{
    -webkit-mask-image:linear-gradient(to right,black calc(100% - 34px),transparent 100%);
    mask-image:linear-gradient(to right,black calc(100% - 34px),transparent 100%);}
.ts-cue{display:flex;flex-basis:100%;justify-content:flex-end;align-items:center;gap:6px;
    margin:6px 2px 0;font-size:var(--fs-label);font-weight:600;color:var(--color-muted);}
.ts-cue .ts-cue-cols{color:var(--color-primary);}
.ts-cue i{font-size:12px;}

/* Printing stays clean (report-print.css sets `@page{margin:0}` and opens .table-scroll back up to
   `overflow:visible`): a fade or a cue on paper would undo that ruling. */
@media print{
    /* BOSS 2026-08-04 — a sticky element in print can repeat on every page or overlap the body. The toolbar
       is screen furniture, so it goes back to normal flow (screens that print already hide it themselves). */
    .toolbar{position:static !important;}
    .ts-cue{display:none !important;}
    .table-scroll.ts-more{-webkit-mask-image:none !important;mask-image:none !important;}
}

/* ============================================================================================
   PER-ACCOUNT WRITE ACTIONS (BOSS 2026-07-30, reported from training)
   A view-only account used to SEE New / Edit / Delete, open the entry form, fill it in, and only
   learn at Save that it was never permitted. The refusal was correct; letting them get that far
   was not. RequireMenuPermissionAttribute now records the screen's Create/Edit/Delete grants and
   _Layout turns them into these body classes, so the toolbar shows only what the account holds.

   SCOPED TO .toolbar ON PURPOSE: a grid's per-row trash button is NOT a toolbar action and is left
   alone (there are ~112 bi-trash icons in the app and most are row controls inside an entry form a
   view-only user never reaches).

   PRESENTATION ONLY — the per-action handler gates (F-060 / H-2) remain the real control. An
   untagged button simply stays clickable and is still refused server-side: a cosmetic gap, never a
   hole.

   BOSS 2026-10-24 (release 18) — "if viewing access only, the other buttons like New, Save are
   disabled". The ungranted actions now stay on the toolbar, greyed and not clickable — the same look
   as the toolbar's own `tb dis` placeholder — instead of being hidden. js/write-grant-guard.js also
   makes them unfocusable and swallows any click on them.
   ============================================================================================ */
body.no-create .toolbar .tb-new,
body.no-delete .toolbar .tb-del,
/* BOSS 2026-08-04 — Save / Process / Post are write actions too.
   BOTH classes are required on the selector, so these grey out only when the account has NEITHER Create NOR Edit.
   That matters because Edit is a real grant here — 24 accounts hold Edit without Create (17 of them approvers, who
   need Save/Process to act on a document they may not create). Keying off no-create alone would have taken the
   Save button away from every approver in the LGU. `tb-write` is any other toolbar write that needs Create or Edit.

   Deliberately NOT greyed: Search, Print and View. Those are read actions a view-only account is entitled to. */
body.no-create.no-edit .toolbar .tb-save,
body.no-create.no-edit .toolbar .tb-process,
body.no-create.no-edit .toolbar .tb-post,
body.no-create.no-edit .toolbar .tb-write {
    color: #b3b9c8 !important; background: transparent !important; cursor: not-allowed; pointer-events: none;
}
body.no-create .toolbar .tb-new .ic,
body.no-delete .toolbar .tb-del .ic,
body.no-create.no-edit .toolbar .tb-save .ic,
body.no-create.no-edit .toolbar .tb-process .ic,
body.no-create.no-edit .toolbar .tb-post .ic,
body.no-create.no-edit .toolbar .tb-write .ic { color: #cdd2dd !important; }

/* The same rule for a write action that is NOT on a toolbar — the row / panel actions of the screens whose work is
   done from the grid (Transaction Approval, Transaction Cancellation, PR and PO Closing, Document Management, the
   Document Archive, the Queue Console …). Tag the control data-needs="create" | "edit" | "delete" with the grant its
   handler checks; "edit" is Create or Edit, as on the toolbar. */
body.no-create [data-needs="create"],
body.no-create.no-edit [data-needs="edit"],
body.no-delete [data-needs="delete"] { opacity: .45; cursor: not-allowed; pointer-events: none; }

/* Reason box inside a confirm dialog (BOSS 2026-08-10, ruling #3 — a deletion must say why, because the
   register keeps the document number and shows the reason beside it). */
.ifmis-dialog-input{width:100%;margin-top:10px;padding:8px 10px;font:inherit;color:var(--color-ink);
  background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-sm);
  resize:vertical;min-height:64px;}
.ifmis-dialog-input:focus{outline:2px solid var(--color-primary);outline-offset:1px;border-color:var(--color-primary);}
.ifmis-dialog-input.is-invalid{border-color:var(--danger);background:var(--danger-bg);}

/* ============================================================================================
   EXCEL-STYLE RANGE COPY ON GRIDS (D-203, BOSS 2026-09-01 — "approved add lists too")
   wwwroot/js/grid-select.js marks the grids it drives with data-select (report grids and the
   entry screens' List registers; never an editable entry grid). These three rules are the whole
   visual half: the spreadsheet cell cursor, the highlighted block, and the anchor cell the block
   was dragged from. Tokens only — the fill and outline live in tokens.css as --sel-bg/--sel-line.
   ============================================================================================ */
table.grid[data-select] td,
table.grid[data-select] th { cursor: cell; user-select: none; -webkit-user-select: none; }
table.grid[data-select] .gs-sel { background: var(--sel-bg) !important; box-shadow: inset 0 0 0 1px var(--sel-line); }
table.grid[data-select] .gs-anchor { box-shadow: inset 0 0 0 2px var(--color-primary); }

/* ============================================================================================
   R21 HEADER FIELDS FILL THEIR COLUMN (FS-FULL; replaces R18 FS-DATE, BOSS 2026-10-24 — "don't
   shorten it, just make it a shared site.css standard for all of those fields"). In an entry header
   form row (.prow / .frow) every field — date, year, document / reference number, status box, header
   amount / total box, dropdown — takes the full width of its field column, like every other field on
   the card, so all of them share the same left and right edges. Date inputs are matched by type,
   status and amount boxes by their existing class; w-date / w-year / w-code / w-status / w-amt / w-sel
   stay on the markup only as markers. The selectors carry the row class + the element so they beat
   each page's own `.prow .grow{flex:1}` (0,2,0) whatever order the sheets load in. Amounts stay
   right-aligned (AF-FMT below); a lookup's code box keeps --w-lookup-code (FS-CLIP below).
   ============================================================================================ */
:is(.prow,.frow) > input.inp:is([type=date],[type=month]),
:is(.prow,.frow) > :is(input,select,div).inp:is(.w-date,.w-year,.w-code,.w-status,.status-box,.w-amt,.amt-box,.total-box,.w-sel){flex:1 1 0;width:auto;max-width:none;min-width:0;}
/* a short value typed in a grid cell keeps the standard code width (grids are not header fields) */
td > :is(input,select).inp.w-code{width:var(--w-code);max-width:100%;}
/* where the rows stack into a column (.prow at 820px, .frow at 768px) a flex basis would become a
   HEIGHT, so the field drops it; align-items:stretch then gives it the full row width */
@media (max-width:820px){
  .prow > input.inp:is([type=date],[type=month]),
  .prow > :is(input,select,div).inp:is(.w-date,.w-year,.w-code,.w-status,.status-box,.w-amt,.amt-box,.total-box,.w-sel){flex:0 0 auto;}
}
@media (max-width:768px){
  .frow > input.inp:is([type=date],[type=month]),
  .frow > :is(input,select,div).inp:is(.w-date,.w-year,.w-code,.w-status,.status-box,.w-amt,.amt-box,.total-box,.w-sel){flex:0 0 auto;}
}

/* ============================================================================================
   R18 LOOKUPS AND DROPDOWNS (FS-CLIP). A lookup row is a small fixed code box, a name box that takes
   the rest (min-width:0, so it no longer stops at an input's 198px default) and the magnifier. A
   dropdown with long option text takes w-sel: the full field column in a header form row (FS-FULL
   above), the --w-select width in a List filter field, at least --w-grid-select in a grid cell.
   js/elide-title.js shows a cut-off value in full on hover.
   ============================================================================================ */
:is(.coa-lookup,.lookup) > input.inp:not([type=hidden]){min-width:0;}
:is(.coa-lookup,.lookup) > input.inp:is(.code-box,.sup-code,.lk-code){flex:0 0 var(--w-lookup-code);width:var(--w-lookup-code);}
:is(.coa-lookup,.lookup) > .coa-mag{flex:0 0 auto;min-width:var(--control-h);justify-content:center;}
/* R18 fix: a grid line's account-code box keeps room for the full 11-character code (1-01-01-010) — the
   min-width:0 above otherwise lets the table squeeze it down to a few characters. */
table td input.mono:is(.row-acctcode,.j-code,.jrow-codebox,.jl-code-text):not([type=hidden]){min-width:var(--w-grid-acct-code);}
.fg.fg-sel{flex:0 1 var(--w-select);max-width:100%;}
.fg.fg-sel.fg-qwin{flex:0 0 var(--w-queue-window);}   /* R23 X1c: the Queue Console window filter keeps its longest option whole */
select.sel.w-sel{min-width:min(var(--w-select),100%);}
td > select.w-sel{min-width:var(--w-grid-select);}
td > input.w-gtext{min-width:var(--w-grid-text);}

/* ============================================================================================
   R18 AMOUNT INPUTS (FS-AMT). One rule for every amount box in a grid (.money-input, .amt-inp, or
   .amt): at least --w-grid-amt wide so 999,999,999.99 shows in full, right-aligned, tabular figures.
   The width comes back from quantity / stock / balance columns (th.col-qty-in, --w-grid-qty, whose
   long head may wrap instead of widening the column).
   ============================================================================================ */
td input:is(.money-input,.amt-inp,.amt){min-width:var(--w-grid-amt);text-align:right;font-variant-numeric:tabular-nums;}
.lf:has(> input.amt){width:auto;}
.lf > input.inp.amt{min-width:var(--w-grid-amt);text-align:right;font-variant-numeric:tabular-nums;}
table.grid th.col-qty-in{width:var(--w-grid-qty);white-space:normal;}

/* ============================================================================================
   R18 ONE CONTROL HEIGHT (FS-HEIGHT). Inputs, selects, buttons, magnifiers, search boxes and file
   inputs that share a row are all --control-h tall; inputs and selects inside a grid cell use the
   compact --control-h-grid. Inputs and selects get a fixed height; buttons and read-only boxes keep a
   min-height with 10px vertical padding, so one line is exactly 44px and a wrapped label still fits.
   Scoped to .main so the login card keeps its own sizes. Textareas are left alone.
   ============================================================================================ */
.main :is(input.inp:not([type=checkbox],[type=radio],[type=file]),select.inp,select.sel){height:var(--control-h);min-height:var(--control-h);padding-top:0;padding-bottom:0;box-sizing:border-box;}
.main .btn,.main div.inp.ro{padding-top:10px;padding-bottom:10px;}
.main .coa-mag{min-height:var(--control-h);box-sizing:border-box;}
.main .search-row > .field{height:var(--control-h);padding-top:0;padding-bottom:0;box-sizing:border-box;}
.main input.inp[type=file]{height:var(--control-h);min-height:var(--control-h);padding:0 13px 0 0;line-height:calc(var(--control-h) - 2px);box-sizing:border-box;}
.main input.inp[type=file]::file-selector-button{height:100%;margin:0 12px 0 0;padding:0 14px;border:0;border-right:1px solid var(--input-border);background:var(--color-bg);color:var(--color-ink);font:inherit;font-weight:600;cursor:pointer;}
.main td :is(input:not([type=checkbox],[type=radio],[type=hidden],[type=file]),select):is(.inp,.ginp,.gsel){height:var(--control-h-grid);min-height:var(--control-h-grid);padding-top:0;padding-bottom:0;box-sizing:border-box;}
.main td .coa-mag{height:var(--control-h-grid);min-height:var(--control-h-grid);}

/* R18 FS-SEARCH — the list search box is at least --w-live-search (360px) wide (rule at .field.grow.live-search
   above) and a Year filter select is --w-year wide. */
select.sel.w-year{width:var(--w-year);min-width:0;}
/* D-298 item 9 — a field-styled Year dropdown in a list search row keeps the Year width (.inp would stretch it). */
.search-row > select.inp.w-year{flex:0 0 auto;}

/* ============================================================================================
   R18 LABELS LEVEL WITH THE FIELD (AL-LABEL). A one-line row centres its label on the field (.frow
   above, .prow on every page); a textarea row (.frow with a textarea, .prow.align-top) puts the
   label at the first text line with a fixed 12px top padding. The label column is one --label-w
   wide in every entry header card and on the RPT forms (form.lbl-wide), so labels stay on one line;
   the field-error badge and the check list follow it. A three-column header (.hdr-3col) keeps its own.
   ============================================================================================ */
.frow:has(> textarea){align-items:flex-start;}
.frow:has(> textarea) > label,.prow.align-top > label{padding-top:12px;}
:is(.pr-head,.ob-head,.dv-head,.jev-head,.be-head,.adj-head,.iss-head,.headgrid):not(.hdr-3col) .prow > label{width:var(--label-w);}
:is(.pr-head,.ob-head,.dv-head,.jev-head,.be-head,.adj-head,.iss-head,.headgrid):not(.hdr-3col) .field-error{--field-error-indent:calc(var(--label-w) + 12px);}
.lbl-wide .frow > label{width:var(--label-w);}
.lbl-wide .field-error{--field-error-indent:calc(var(--label-w) + 14px);}
.lbl-wide :is(.checks,.recinfo){margin-left:calc(var(--label-w) + 14px);}
@media (max-width:768px){
  .lbl-wide .frow > label{width:auto;text-align:left;}
  .lbl-wide .field-error,.lbl-wide :is(.checks,.recinfo){margin-left:0;}
}
@media (max-width:820px){ .prow.align-top > label{padding-top:0;} }

/* ============================================================================================
   R18 ONE TWO-COLUMN HEADER GRID (AL-COLS). Every entry header card is two equal columns whose
   width never depends on what is typed in them (minmax(0,1fr)), with the one --label-w label
   column, so field edges line up between columns, sections and records. A lookup (input +
   magnifier) takes the same width as a select. A row that belongs to the card spans both columns
   (.hdr-span); a field row that sits below the card lines up with the card's fields (.hdr-out).
   Above 980px only, so each screen's own stacked layout on a tablet / phone is unchanged.
   ============================================================================================ */
@media (min-width:981px){
  :is(.pr-head,.ob-head,.dv-head,.jev-head,.be-head,.adj-head,.iss-head,.headgrid):not(.hdr-3col){grid-template-columns:minmax(0,1fr) minmax(0,1fr);}
}
:is(.pr-head,.ob-head,.dv-head,.jev-head,.be-head,.adj-head,.iss-head,.headgrid) > *{min-width:0;}
:is(.pr-head,.ob-head,.dv-head,.jev-head,.be-head,.adj-head,.iss-head,.headgrid) .prow > :is(.coa-lookup,.lookup){flex:1 1 0;min-width:0;}
/* R18 fix: a dropdown (its widest option) or a wrapper div around a lookup must not hold the column open
   either — without min-width:0 it overflows into the next column / past the card edge. */
:is(.pr-head,.ob-head,.dv-head,.jev-head,.be-head,.adj-head,.iss-head,.headgrid) .prow > :is(select,div){min-width:0;}
:is(.pr-head,.ob-head,.dv-head,.jev-head,.be-head,.adj-head,.iss-head,.headgrid) > .hdr-span{grid-column:1 / -1;}
.prow.hdr-out{padding-left:19px;padding-right:19px;}
.prow.hdr-out > label{width:var(--label-w);}

/* ============================================================================================
   R18 TEXT COLUMNS GET THE ROOM (GR-SQUEEZE). A description / name / payee / account-title column
   (th.col-desc) and a description box in a grid (.row-desc, .w-gtext) are at least --w-grid-text
   wide and the box fills its cell; code, number and quantity columns keep their standard widths and
   a document number stays on one line (Bootstrap .text-nowrap). A read-only box that is still cut
   shows its full value on hover (js/elide-title.js).
   ============================================================================================ */
table th.col-desc{min-width:var(--w-grid-text);}
td > input:is(.w-gtext,.row-desc){width:100%;min-width:var(--w-grid-text);}

/* ============================================================================================
   R19 LIST VALUES STAY ON ONE LINE (GR-LISTWRAP). A List tab register (table.list-grid) keeps its
   document numbers (.mono), dates (.text-nowrap), status pills and column heads on one line, so
   "PR-2026-0081" no longer breaks at a hyphen and a row stays one line tall. The document-number
   column is at least --w-list-no wide.
   ============================================================================================ */
table.list-grid :is(thead th,td.mono,td .mono,td .pill,td .status){white-space:nowrap;}
table.list-grid td:has(> a.rowlink){min-width:var(--w-list-no);}

/* =====================================================================================   R19 LONG LISTS ARE PAGED (GR-PAGE). js/list-pager.js pages any table[data-pager]: 25 rows (or 50) a
   page and a bar under the grid with the record count, the rows-per-page choice and the page buttons.
   A short grid that must fit one screen takes .grid-compact (4px 10px cells) and .sticky-head (the
   column heads stay in view under the top bar while the page scrolls).
   ============================================================================================ */
tr.lp-off{display:none;}
.list-pager{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px;padding:10px 14px;border-top:1px solid var(--color-border);background:var(--color-surface);font-size:var(--fs-sm);color:var(--color-ink);}
.list-pager .lp-nav{display:flex;align-items:center;flex-wrap:wrap;gap:6px;}
.list-pager .lp-size{display:flex;align-items:center;gap:6px;margin-right:6px;color:var(--color-muted);font-weight:600;}
.list-pager .lp-size select.sel{min-height:var(--control-h-grid);height:var(--control-h-grid);padding-top:0;padding-bottom:0;}
.list-pager .lp-btn{min-width:var(--control-h-grid);height:var(--control-h-grid);padding:0 10px;border:1px solid var(--blue-200);border-radius:var(--radius-sm);background:var(--color-surface);color:var(--color-ink);font:inherit;font-weight:600;cursor:pointer;font-variant-numeric:tabular-nums;}
.list-pager .lp-btn:hover:not(:disabled){background:var(--color-primary-subtle);}
.list-pager .lp-btn.on{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-surface);}
.list-pager .lp-btn:disabled{color:var(--color-muted);opacity:.5;cursor:not-allowed;}
.list-pager .lp-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px;}
.list-pager .lp-gap{color:var(--color-muted);padding:0 2px;}
table.grid-compact > tbody > tr > td{padding:4px 10px;}
table.sticky-head > thead{position:sticky;top:54px;z-index:2;}
@media (min-width:821px){ .table-scroll:has(> table.sticky-head){overflow:visible;} }

/* ============================================================================================
   R19 TOTALS UNDER THEIR COLUMN (GR-TOTAL). A grid footer uses the same cell padding and type size as
   the body rows (a screen whose own grid rule sets the cell padding keeps it for the footer too), the
   total label (.tot-lbl) is bold and right-aligned, and a total (.num) is right-aligned in its amount
   column with tabular figures. Under a column of amount INPUTS the total takes .tot-in, which moves it
   in by --inp-text-inset so its last digit lines up with the inputs' figures.
   ============================================================================================ */
table tfoot :is(td,th){padding:13px 11px;font-size:14px;}
table tfoot :is(td,th).tot-lbl{text-align:right;font-weight:700;}
table tfoot :is(td,th):is(.num,.tot-in){text-align:right;font-variant-numeric:tabular-nums;}
table tfoot td.tot-in::after{content:"";display:inline-block;width:var(--inp-text-inset);}

/* ============================================================================================
   R19 BALANCED, STEADY COLUMNS (GR-BAL). A grid that must keep its shape between records and between
   the edit and read-only views takes .grid-fixed: on a desktop it is laid out from its column widths
   (table-layout:fixed), not from what is typed in the cells, and it keeps its (empty) action column when
   read-only. Below 981px it stays a normal, scrollable grid. A text column that follows a right-aligned
   number column gets 24px left padding so the two never touch.
   ============================================================================================ */
@media (min-width:981px){ table.grid-fixed{table-layout:fixed;} }
table :is(thead th.num + th, tbody td.num + td):not(.num,:last-child){padding-left:24px;}

/* ============================================================================================
   R19 AMOUNTS RIGHT-ALIGNED (AF-CENTRE). An amount or quantity cell is td.num: right-aligned with
   tabular figures, so 7.20 / 218.88 / 4,478.40 end on the same edge. Only a row number stays centred.
   ============================================================================================ */
table :is(tbody,tfoot) td.num{text-align:right;font-variant-numeric:tabular-nums;}

/* ============================================================================================
   R19 AMOUNT FORMAT (AF-FMT). A header amount box (.w-amt, .amt-box, .total-box), read-only or not,
   shows its figure right-aligned with tabular figures. The selector carries .inp and the element so it
   beats .inp.ro (a read-only box is a flex row whose space-between otherwise left-aligns the figure).
   ============================================================================================ */
:is(.prow,.frow) > :is(input,div).inp:is(.w-amt,.amt-box,.total-box){text-align:right;justify-content:flex-end;font-variant-numeric:tabular-nums;}

/* ============================================================================================
   R19 VISUAL 17-24 (release 19 visual standards). One rule per concern, shared by every screen.
   ============================================================================================ */

/* 17 TB-TARGET — ONE ROW ACTION, ONE CLOSE X, ONE TICK BOX.
   - A button is exactly --control-h tall on one line: no vertical padding, a fixed line box, so a bordered
     (ghost) button and a filled one come out the same height side by side.
   - A row action or row link is the standard .btn.btn-ghost.btn-sm: at least 44 x 44, blue outline;
     .tone-danger turns it red for a destructive action (Delete, Cancel ticket).
   - The "Add" control under a line grid (button.spec-add) is the same outlined button, at least 44px tall.
   - Approve / Disapprove sit side by side in one row (.row-acts never wraps) and share one width.
   - A pop-up close X (button.x) is a real 44 x 44 box; the negative margin keeps the header height unchanged.
   - A tick box is the 18px checkbox inside a label.tick, and the label is the 44px hit area (in a grid cell
     it fills the cell's width).
   - th.col-act is the width of an action column holding one 44px button. */
.main .btn{padding-top:0;padding-bottom:0;line-height:22px;}
.main .btn.btn-sm{min-width:var(--control-h);padding:0 12px;font-size:13px;gap:6px;justify-content:center;white-space:nowrap;}
.main .btn.btn-ghost.btn-sm{color:var(--color-primary);}
.main .btn.btn-ghost.btn-sm:hover{background:var(--color-primary-subtle);}
.main .btn.btn-ghost.btn-sm.tone-danger{color:var(--danger);border-color:var(--danger-line);}
.main .btn.btn-ghost.btn-sm.tone-danger:hover{background:var(--danger-bg);}
.main button.spec-add{display:inline-flex;align-items:center;gap:6px;min-height:var(--control-h);padding:0 14px;border:1px solid var(--input-border);border-radius:9px;background:var(--color-surface);color:var(--color-primary);font:600 13.5px var(--font-sans);cursor:pointer;text-decoration:none;}
.main button.spec-add:hover{background:var(--color-primary-subtle);text-decoration:none;}
.row-acts{display:flex;flex-wrap:nowrap;gap:6px;justify-content:center;align-items:center;}
button.btn-approve,button.btn-disapprove{min-width:96px;justify-content:center;white-space:nowrap;}
button.x{display:inline-flex;align-items:center;justify-content:center;width:var(--control-h);height:var(--control-h);margin:-10px -8px -10px 0;border-radius:var(--radius-sm);flex:none;}
button.x:hover{background:var(--color-bg-subtle);}
label.tick{display:inline-flex;align-items:center;gap:8px;min-height:var(--control-h);min-width:var(--control-h);cursor:pointer;white-space:nowrap;}
td > label.tick:only-child{display:flex;justify-content:center;width:100%;}
label.tick > input[type=checkbox]{width:18px;height:18px;margin:0;flex:none;accent-color:var(--color-primary);cursor:pointer;}
table th.col-act{width:calc(var(--control-h) + 22px);}

/* 18 TB-BAR — STANDARD TOOLBAR ITEMS. Every toolbar entry is a .tb (icon in .ic + label). A gap that pushes the
   rest of the toolbar to the right is a plain .tb-spacer (never a .tb-sep, which draws a divider). A filter form
   inside a toolbar stays on one line (its fields shrink) so the toolbar does not wrap at 1366; it wraps again on
   a phone with the rest of the toolbar. */
.toolbar .tb{white-space:nowrap;}   /* a toolbar label stays on one line ("Open self-service kiosk") */
.tb-spacer{flex:1 1 auto;}
.toolbar > form.search-row{flex-wrap:nowrap;min-width:0;}
@media (max-width:820px){ .toolbar > form.search-row{flex-wrap:wrap;} }

/* 21 CO-RO — ONE READ-ONLY LOOK. Every read-only or disabled box (header input, select, textarea, grid input, and
   the div.inp.ro display box) is the same grey fill with a dashed border and no resize grip, whatever screen or
   grid it is on. js/readonly-dash.js shows the house em dash in an empty one. A locked record (.locked-doc on its
   form) does not show the required-field asterisks, because nothing on it can be filled in. */
.main :is(input,select,textarea):is(.inp,.ginp,.gsel):is([readonly],:disabled):not([type=checkbox],[type=radio],[type=hidden],[type=file]),
.main td input[readonly]:not([type=checkbox],[type=radio],[type=hidden]),
.main div.inp.ro{background:var(--color-bg-subtle);color:var(--color-muted);border:1px dashed var(--input-border);resize:none;}
.main div.inp.ro:has(> .pill){padding-top:0;padding-bottom:0;}   /* a status pill in the box: same height as its neighbours */
.locked-doc :is(.req,.req-star){display:none;}
.locked-doc .req-label::after{content:none;}

/* 22 CO-LABEL — ONE STACKED LABEL. A label above its field (the RPT add-line rows, .lf) reads like every other
   stacked caption (.fg label): 12px, semibold, muted, as written — not 11.5px capitals. */
.main .lf > label{font-size:var(--fs-label);font-weight:600;color:var(--color-muted);text-transform:none;letter-spacing:0;}

/* 23 CO-EMPTY — ONE PILL, ONE EMPTY STATE. A status pill is one size and shape everywhere (a page may still set its
   colours) and never wraps. An empty grid shows one message row: td.empty-state, centred, muted, italic; the text
   sits in a .empty-msg that stays inside the visible part of a wide, scrolled grid. */
.main .pill{display:inline-block;padding:4px 11px;border-radius:var(--radius-pill);font-size:var(--fs-label);font-weight:700;line-height:1.5;letter-spacing:0;white-space:nowrap;}
td.empty-state{padding:18px 12px;text-align:center;color:var(--color-muted);font-size:var(--fs-sm);font-style:italic;}
td.empty-state > .empty-msg{display:inline-block;position:sticky;left:12px;right:12px;}

/* ============================================================================================
   R20 FIX 8 LINE GRIDS FIT THE CARD (GR-FIT). A line grid that scrolled sideways at 1366 x 768 takes
   .grid-fit: on a desktop it is exactly as wide as its card (table-layout:fixed, width 100%, the screen's
   own min-width dropped), so every column is in view with no sideways scroll. Each short column takes one
   standard width from tokens.css through a gw-* class on its head; the description / name columns have no
   class and share what is left. Inputs, dropdowns and look-ups shrink to their cell (min-width 0, width
   100%) and a column head may wrap. A value longer than its cell is cut with an ellipsis (a text cell marked
   td.ell, or any box) and shown in full on hover (js/elide-title.js). The delete column holds one 44px
   button with no side padding. .grid-dense narrows the amount, date and quantity columns of a grid with
   many of them (PPE Issuance); .grid-small is a 14-column register (12px type, 5px cells). Below 981px the
   grid keeps the screen's own min-width and scrolls sideways as before.
   ============================================================================================ */
table.grid-fit th.gw-no{width:var(--gw-no);}
table.grid-fit th.gw-short{width:var(--gw-short);}
table.grid-fit th.gw-qty{width:var(--gw-qty);}
table.grid-fit th.gw-sel{width:var(--gw-sel);}
table.grid-fit th.gw-btn{width:var(--gw-btn);}
table.grid-fit th.gw-ref{width:var(--gw-ref);}
table.grid-fit th.gw-code{width:var(--gw-code);}
table.grid-fit th.gw-acct{width:var(--gw-acct);}
table.grid-fit th.gw-date{width:var(--gw-date);}
table.grid-fit th.gw-dt{width:var(--gw-dt);}
table.grid-fit th.gw-amt{width:var(--gw-amt);}
table.grid-fit th.gw-act{width:var(--gw-act);}
table.grid-fit th.gw-acts{width:var(--gw-acts);}
table.grid-fit td.ell{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
table.grid-fit > tbody > tr > td:has(> :is(.spec-rm,.rm-btn)){padding-left:0;padding-right:0;text-align:center;}
table.grid-dense{--gw-amt:98px;--gw-date:116px;--gw-qty:66px;--gw-short:56px;--gw-sel:94px;--gw-amt-in:120px;}   /* R22 Fix 8 follow-up — 5px cells (below) */
table.grid-small{--gw-code:118px;--gw-date:74px;--gw-amt:96px;--gw-short:48px;--gw-ref:82px;}   /* R22 Fix 8 follow-up — BIR Filing detailed report */
table.grid-fit.grid-small > * > tr > :is(th,td){padding:5px;font-size:var(--fs-label);}
table.grid-fit.grid-small > * > tr > td .mono,table.grid-fit.grid-small > * > tr > td.mono{font-size:var(--fs-label);}
@media (min-width:981px){
  table.grid-fit{table-layout:fixed;width:100% !important;min-width:0 !important;}
  table.grid-fit > thead > tr > th{white-space:normal;min-width:0;}
  table.grid-fit td :is(input:not([type=checkbox],[type=radio],[type=hidden]),select,textarea){min-width:0 !important;width:100%;max-width:100%;text-overflow:ellipsis;}
  table.grid-fit td :is(.coa-lookup,.lookup){min-width:0;}
}

/* ============================================================================================
   R22 CLEANUP CL-01..03 (release 22 visual cleanup, owner 2026-10-24).
   CL-01 LIST ROWS STAY ONE LINE AT 1366. A List register marks its columns with one lc-* class on the
   head AND the cells: Fund (lc-fund), Created By (lc-by), a date (lc-date) and a bank account number
   (lc-bank, the bank name on hover) never wrap; a type column (lc-type) gets the --lw-type width;
   Remarks (lc-rmk) is one line cut with "..." and shown in full on hover (js/elide-title.js); a long
   name column (lc-wide) takes its --lw-wide share of what the fixed columns leave; one small View
   button column (lc-view) is --lw-view. A date head, and a long head over a short value (lc-hwrap:
   "Total Appropriation", "Budget Year"), may wrap so the head does not widen the column. List cells
   use 8px side padding so a nine- or ten-column register fits the 1366 card.
   ============================================================================================ */
table.list-grid > :is(thead,tbody) > tr > :is(th,td){padding-left:8px;padding-right:8px;}
table :is(th,td):is(.lc-fund,.lc-by,.lc-bank){white-space:nowrap;}
table td.lc-date{white-space:nowrap;}
table:is(.grid,.list-grid) thead th:is(.lc-date,.lc-hwrap){white-space:normal;}
table th.lc-fund{width:var(--lw-fund);}
table th.lc-by{width:var(--lw-by);}
table th.lc-type{width:var(--lw-type);}
table th.lc-date{width:var(--lw-date);}
table th.lc-wide{width:var(--lw-wide);}
table th.lc-view{width:var(--lw-view);}
table th.lc-rmk{width:var(--lw-rmk);}
table td.lc-rmk{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
/* CL-01 browser check on real rows (2026-10-24): content-sized columns still wrapped and pushed some
   registers wider than the card at 1366. A register marked .list-fit is laid out from its column widths
   on a desktop (table-layout:fixed, exactly the card's width), so no value can widen it: it never
   scrolls sideways. Every cell stays one line; a longer value is cut with "..." and shown in full on
   hover (js/elide-title.js). A column with an lc-* class takes its width (doc number lc-no, or
   lc-no-long for PAYREL-2026-10-0058, status lc-stat, amount lc-amt, quantity lc-qty, year lc-yr,
   bank account lc-bank, a date under a "Transaction Date" head lc-tdate, Submitted lc-when, Approve +
   Disapprove lc-approve, View lc-view); the long text columns (type, office, payee, location, current level,
   remarks: lc-type, lc-wide, lc-rmk or no class) share what is left. Fund and Created By are a share
   of the table so they grow on a wide screen. A head may wrap, between words only. Below 981px the
   register keeps its content widths and scrolls sideways as before. */
table th.lc-no{width:var(--lw-no);}
table th.lc-no-long{width:var(--lw-no-long);}
table th.lc-stat{width:var(--lw-stat);}
table th.lc-amt{width:var(--lw-amt);}
table th.lc-qty{width:var(--lw-qty);}
table th.lc-yr{width:var(--lw-yr);}
table th.lc-when{width:var(--lw-when);}
table th.lc-approve{width:var(--lw-approve);}
@media (min-width:981px){
  table.list-fit th.lc-bank{width:var(--lw-bank);}
  table.list-fit th.lc-tdate{width:var(--lw-tdate);}
  table.list-fit{table-layout:fixed;width:100%;--lw-type:auto;--lw-rmk:auto;--lw-wide:auto;--lw-date:var(--lw-date-fit);--lw-fund:var(--lw-fund-fit);--lw-by:var(--lw-by-fit);}
  table.list-grid.list-fit > thead > tr > th{white-space:normal;word-break:normal;overflow-wrap:normal;}
  table.list-fit > tbody > tr > td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  table.list-fit > tbody > tr > td > div{overflow:hidden;text-overflow:ellipsis;}
}

/* CL-02 LOOKUP ROWS. The code box of a code + name lookup (input.code-box: the office lookups of Purchase
   Request and Obligation) is --w-lookup-code-sm wide, so the name box beside it takes the rest of the
   field; the magnifier / clear buttons keep their 44px (FS-CLIP). A read-only name box, and a read-only display box
   (div.inp.ro), shows its full value on hover — set when the page loads and again right after a picker
   writes it (js/elide-title.js). */
:is(.coa-lookup,.lookup) > input.inp.code-box{flex:0 0 var(--w-lookup-code-sm);width:var(--w-lookup-code-sm);}

/* CL-03 DROPDOWNS. A header dropdown with long option text takes the full field column (w-sel, FS-FULL above —
   no new rule) and shows its chosen text in full on hover (js/elide-title.js, now also for a .frow or filter
   dropdown when the page loads, so a locked one has it too). */

/* ============================================================================================
   R22 CLEANUP CL-04..06 (line grids, release 22).
   CL-04 CODES, ACCOUNTS AND QUANTITIES GET THEIR ROOM. More Fix 8 gw-* widths (tokens.css) for the
   columns that were too narrow: an item code beside its magnifier (gw-code-pick) or alone (gw-item), an
   account code alone (gw-acct-code), a unit-of-measure dropdown (gw-uom), a quantity box (gw-qty-in, fits 999,999.99), a unit price
   (gw-price), an SL type beside its magnifier (gw-sl-type) or as a dropdown (gw-sl-sel), an SL reference
   (gw-sl-ref) and an expense account with its magnifier (gw-exp-acct). The description / name columns
   carry no class and give up the space. The grid still fits the card at 1366 (no sideways scroll);
   a value longer than its box shows in full on hover (js/elide-title.js).
   ============================================================================================ */
table.grid-fit th.gw-code-pick{width:var(--gw-code-pick);}
table.grid-fit th.gw-item{width:var(--gw-item);}
table.grid-fit th.gw-acct-code{width:var(--gw-acct-code);}
table.grid-fit th.gw-uom{width:var(--gw-uom);}
table.grid-fit th.gw-qty-in{width:var(--gw-qty-in);}
table.grid-fit th.gw-price{width:var(--gw-price);}
table.grid-fit th.gw-sl-type{width:var(--gw-sl-type);}
table.grid-fit th.gw-sl-sel{width:var(--gw-sl-sel);}
table.grid-fit th.gw-sl-ref{width:var(--gw-sl-ref);}
table.grid-fit th.gw-exp-acct{width:var(--gw-exp-acct);}
/* Browser check on real rows: Payment Release "Disbursement Vouchers to Release" takes .grid-fit — the tick column
   is gw-tick, DV No gw-dvno, the amounts shown as text gw-amt-txt, Check / ADA and Reference No gw-ref-sm, Date
   Received gw-date-in, and Payee takes the rest; every column is in view at 1366 with no sideways scroll. */
table.grid-fit th.gw-amt-txt{width:var(--gw-amt-txt);}
table.grid-fit th.gw-ref-sm{width:var(--gw-ref-sm);}
table.grid-fit th.gw-dvno{width:var(--gw-dvno);}

/* CL-05 BOXES STAY IN THEIR CELL. In a grid laid out from its column widths (.grid-fixed, desktop) a box
   that sits straight in a cell takes the cell's width and may shrink with it, so it can no longer run
   under the next column (OR / Invoice Ref. under Particulars, Amount under the delete button). The OR /
   invoice reference column is gw-or wide. A date box (type=date) takes gw-date-in, so the full MM/DD/YYYY
   shows beside the picker icon (gw-date left a 110px box that cut it to "10/23/202..."). */
table.grid-fit th.gw-or{width:var(--gw-or);}
table.grid-fit th.gw-date-in{width:var(--gw-date-in);}
@media (min-width:981px){
  table.grid-fixed td > input.inp:not([type=checkbox],[type=radio],[type=hidden]){width:100%;min-width:0;}
}

/* CL-06 COLUMNS STAY PUT BETWEEN EDIT AND READ-ONLY. A grid that must not move takes .grid-fixed with its
   gw-* widths and keeps its (empty) delete column when read-only (markup). In such a grid a look-up shown
   without its magnifier (read-only) keeps the magnifier's room, so the box is as wide as in edit. A column
   head over amount inputs may take .tot-in, like the total under it: it moves in by --inp-text-inset so
   the head ends where the figures in the boxes end. */
table.grid-fixed td .coa-lookup:not(:has(> .coa-mag))::after{content:"";flex:0 0 var(--control-h);}
table thead th.tot-in::after{content:"";display:inline-block;width:var(--inp-text-inset);}

/* ============================================================================================
   R22 CLEANUP CL-11..12 (release 22 visual cleanup, BOSS 2026-10-24).
   CL-11 LABELS LEVEL WITH THEIR VALUE. The label column stays the one --label-w (200px).
   - A read-only box on a top-aligned row (.prow.align-top: Purpose) shows its text at the top of the
     box, level with the label's first line, not centred in the taller box.
   - A read-only box marked .ell (Charge Account) stays on one line; a longer value ends in "..." and
     the page writes the full value into title="" so it shows on hover.
   ============================================================================================ */
.main .prow.align-top > div.inp.ro{align-items:flex-start;}
.main div.inp.ro.ell{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}

/* CL-12 ONE READ-ONLY AND EMPTY LOOK (with release 19 CO-RO above).
   - An empty read-only display box (div.inp.ro with nothing in it) shows the house em dash, the same as
     js/readonly-dash.js shows in an empty read-only input. Display only: the dash is drawn by CSS and is
     never a value, so nothing posts it.
   - The tick column of a fitted grid (th.gw-tick / td.gw-tick) is a fixed 40px holding one checkbox. */
.main div.inp.ro:empty::before{content:"\2014";}
table.grid-fit th.gw-tick{width:40px;}
table.grid-fit :is(th,td).gw-tick{padding-left:0;padding-right:0;text-align:center;}

/* ============================================================================================
   R22 FIX 8 FOLLOW-UP (browser check of Fix 8, 2026-10-24).
   PPE Issuance (.grid-dense): the Unit Cost and Amount boxes take gw-amt-in, wide enough to show
   9,999,999.99 in full. A dense grid's cells have 5px side padding (as .grid-small), so the other
   amount, date, quantity and asset-type columns are 6px narrower with the same room inside them, and
   the grid still fits the card at 1366. Details keeps gw-btn: its head has the 24px left padding of a
   column after a number column, and "Details" needs the 80px.
   (The dense widths are on the table.grid-dense rule in the R20 FIX 8 block.)
   ============================================================================================ */
table.grid-fit th.gw-amt-in{width:var(--gw-amt-in);}

/* BIR Filing detailed report (.grid-small, 14 columns): DV No., DV Date and the amounts (to 9,999,999.99)
   show in full; every cell is td.ell, so a longer Payee / Nature / Fund / Mode / TIN / Check-ADA No. is cut
   with "..." and shown in full on hover; Status takes gw-stat so its head never breaks inside the word.
   Each column is at least as wide as the longest word of its head, so heads break between words only. */
table.grid-fit th.gw-stat{width:var(--gw-stat);}
/* N5 option B (owner 25 Oct, D-281): the TIN shows in full (gw-tin); Payee and Nature take the room left, cut with
   "..." and shown in full on hover. Their heads break between words only (as the list-fit heads): a head word wider
   than its 45px column (NATURE) runs on into the empty start of the head beside it instead of breaking inside. */
table.grid-fit th.gw-tin{width:var(--gw-tin);}
table.grid-fit > thead > tr > th.gw-word{word-break:normal;overflow-wrap:normal;}
table.grid-fit.grid-dense > * > tr > :is(th,td){padding-left:5px;padding-right:5px;}

/* ============================================================================================
   R25 CLEANUP CL-09 (release 25 visual cleanup, owner 2026-10-26, D-282 item 8).
   ONE MONEY BOX. An amount or quantity typed in a grid uses the shared money box (Pages/Shared/_MoneyInputScript:
   commas while typing, 2 decimals on leaving the box, right-aligned): its column head takes gw-money, so the box
   is the --w-grid-amt 150px that shows 999,999,999.99 in full. A header amount keeps the full width of the other
   header fields (R21 FS-FULL above). A quantity box (qty-input) gets the commas without forced decimals.
   ============================================================================================ */
table.grid-fit th.gw-money{width:var(--gw-money);}
/* CL-09 option C (owner 26 Oct): a description column may hold a set width (gw-desc) instead of taking what is left.
   When the set widths add up to more than the card, the fixed-layout grid grows past 100% and scrolls sideways
   inside its own .table-scroll wrapper (with the shared scroll cue); the page itself never scrolls sideways. */
table.grid-fit th.gw-desc{width:var(--gw-desc);}
/* R29 PRhead option B (owner 27 Oct, D-285 item 9): the Purchase Request line grid's two description columns hold
   190px each (gw-desc-sm), the same set-width scroll as CL-09 option C; its heads take gw-word (break between words only). */
table.grid-fit th.gw-desc-sm{width:var(--gw-desc-sm);}
td input.qty-input{min-width:var(--w-grid-amt);text-align:right;font-variant-numeric:tabular-nums;}

/* ============================================================================================
   R25 CLEANUP CL-08 CL-13 CL-14 CL-15 (release 25 visual cleanup, owner 2026-10-26, D-282 item 8).
   CL-08 lives on PR and PO Closing itself: Open Balance is the normal text colour, bold (no amber).
   ============================================================================================ */
:root{--cw-code:130px;--cw-chk:130px;--cw-size:80px;--cw-fund:110px;--cw-payee:240px;--cw-why:360px;--w-pct:110px;--row-h-edit:56px;--row-h-view:48px;}

/* CL-13 TOOLBAR AND FILTER ROWS LINE UP.
   - A number box that holds a year (Depreciation Run) reads left, like the Month and Fund beside it.
   - Queue Console (.qc-bar): the toolbar links sit on the bottom line of the fields. D-294 PW: the toolbar
     runs the full card width (the old content-width stop is gone).
   - A list filter label and its dropdown (.lp-pair) wrap together; the last pair (.lp-grow) takes what is
     left of the line, so its box shrinks on the line instead of dropping alone to the next one.
   - Collection: the Pull / Re-pull button and "Last pull" on one line (.pull-line); the sub-tabs centre
     their text, so a tab with a pill sits level with the others (.tabs-mid).
   - Assessment Transaction: Adjustment % is --w-pct wide, so Add land line stays on the first row. */
.search-row input.num-input.yr-left{text-align:left;}
.toolbar.qc-bar{align-items:flex-end;}
.search-row > .lp-pair{display:inline-flex;align-items:center;gap:10px;min-width:0;}
.search-row > .lp-pair > .lp-lbl{margin:0;white-space:nowrap;}
.search-row > .lp-pair.lp-grow{flex:1 1 0;min-width:min(100%,320px);max-width:calc(var(--w-select) + 120px);}
.search-row > .lp-pair.lp-grow > select.sel.w-sel{flex:1 1 auto;min-width:0;width:auto;}
.pull-line{flex:1;display:flex;align-items:center;gap:12px;flex-wrap:wrap;min-width:0;}
.pull-line > .cap{margin:0;white-space:nowrap;}
.tabs.tabs-mid > a{display:inline-flex;align-items:center;}
.lf.w-pct{width:var(--w-pct);}

/* CL-14 GRID HEADS AND SHORT COLUMNS DO NOT WRAP.
   - A grid marked .hd-nw keeps every head on one line (the doubled class outranks the per-column
     white-space:normal rules such as th.col-qty-in).
   - Code (cw-code), Check / ADA (cw-chk), size (cw-size) and fund (cw-fund) cells stay on one line with a
     least width; cw-nw keeps a number or date on one line; Payee (cw-payee) gets a least width.
   - In a grid laid out from its column widths (.grid-fit) Check / ADA takes gw-chk.
   - A left-aligned column straight after a right-aligned one (.after-num) starts 16px in. */
table.hd-nw.hd-nw > thead > tr > th{white-space:nowrap;}
.cw-nw{white-space:nowrap;}
table :is(th,td).cw-code{white-space:nowrap;min-width:var(--cw-code);}
table :is(th,td).cw-chk{white-space:nowrap;min-width:var(--cw-chk);}
table :is(th,td).cw-size{white-space:nowrap;min-width:var(--cw-size);}
table :is(th,td).cw-fund{white-space:nowrap;min-width:var(--cw-fund);}
table :is(th,td).cw-payee{min-width:var(--cw-payee);}
table.grid-fit th.gw-chk{width:var(--cw-chk);}
table > :is(thead,tbody) > tr > :is(th,td).after-num{padding-left:16px;}

/* CL-15 ONE ROW HEIGHT PER GRID. A grid marked .row-eq gives every body row the one view height
   (--row-h-view, 48px); with .row-edit (the grid is being edited) the one edit height (--row-h-edit, 56px).
   The cell's own top / bottom padding is dropped so the 36px grid boxes and 44px buttons sit centred in it.
   - Bid Evaluation: the bidder name stays on one line; a longer name ends in "..." (full name on hover).
   - Bank Reconciliation: Add memo is a 44px button (.h-ctl).
   - Order of Payment: the Why text is 14px in at least --cw-why. */
table.row-eq > tbody > tr > td{height:var(--row-h-view);padding-top:0;padding-bottom:0;}
table.row-eq.row-edit > tbody > tr > td{height:var(--row-h-edit);}
table.bidders td.bidder-name{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.add-line.h-ctl{min-height:var(--control-h);}
table.dues-tbl td.basis{font-size:14px;min-width:var(--cw-why);}
p.muted.dues-note{margin-top:var(--space-3);}

/* ============================================================================================
   R25 CLEANUP CL-16..19 (release 25 visual cleanup, owner 2026-10-26, D-282 item 8).
   CL-16 SHARED CONTROL SIZES. Pop-up boxes 44px with the 14.5px control text, toggles 36px, menu items
   44px, Call Next 44px, grid picker buttons 44px wide (the 36px grid height stays). Most of these are
   the screens' own rules (Bid Evaluation, Post-Qualification, Document Entry, Queue Console,
   Disbursement); here: the Document Entry inline Rename / Move box in a file row is a form box (44px,
   14.5px), not the compact 36px grid box, so it is as high as the Save beside it.
   ============================================================================================ */
.main td form.dm-rowform :is(input,select).inp{height:var(--control-h);min-height:var(--control-h);font-size:14.5px;}

/* CL-17 ONE WIDTH PER PAGE, STICKY HEAD.
   - (D-294 PW: the Inventory Issuance card stop is retired; the card runs the full width.)
   - Lot Sketch: the Courses, Corner coordinates and Boundary lines tables (.lt-grid) are laid out from one set
     of column widths (lt-no, lt-brg, lt-dist) and are the full content width, so they end at one right edge;
     the five Result stat cards (.lt-stats) are equal and span the same width. */
table.lt-grid{table-layout:fixed;width:100%;}
table.lt-grid th.lt-no{width:90px;}
table.lt-grid th.lt-brg{width:260px;}
table.lt-grid th.lt-dist{width:240px;}
.stat-row.lt-stats > .stat{flex:1 1 0;}
/* - Period Close: the month grid's head (table.sticky-head) sticks right under the top bar, which stands 71px
     on a desktop (15px padding, 40px avatar, 1px line); at 54px its first row slid under the bar and the head
     looked as if it scrolled away. The table's cells keep their own borders (separate, no spacing) so no
     collapsed border line lets the scrolled rows show through the head. */
table.sticky-head > thead{top:71px;}
.main table.sticky-head{border-collapse:separate;border-spacing:0;}

/* CL-19 DOCUMENT ARCHIVE COLUMNS.
   - Deleted Files (.rb-files): fixed Type 110, Ver 60, Size 90, Deleted On 170, Actions 190 and File Name
     170px (one line, "..." and the full name on hover); Folder takes the rest: 240px or more wherever the
     card gives the room (1366 without a classic scrollbar, any wider screen). The table is never narrower
     than the 1366 card with a classic scrollbar (1020px, Folder about 230px) so it does not scroll sideways
     there; on a narrower window it scrolls sideways inside its card before Folder gets narrower.
   - Deleted Folders: a folder name shows at most 2 lines, the full name on hover (title); the icon stays on
     the first line. */
table.rb-files th.rb-c-name{width:170px;}
table.rb-files th.rb-c-type{width:110px;}
table.rb-files th.rb-c-size{width:90px;}
table.rb-files th.rb-c-ver{width:60px;}
table.rb-files th.rb-c-dt{width:170px;}
table.rb-files th.rb-c-acts{width:190px;}
@media (min-width:981px){
  table.grid-fit.rb-files{min-width:1020px !important;}
}
.rb-fname{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;overflow-wrap:anywhere;}
/* R25 check fix: the icon and the name start together on line 1. A Bootstrap icon is an inline-block, which
   is always a line-break point, so a long unbroken name dropped to line 2 and left the icon alone. The icon now
   sits in the name's left padding (first line), and a second line starts under the text, not under the icon. */
.rb-fname{position:relative;padding-left:calc(1em + var(--space-1));}
.rb-fname > i{position:absolute;left:0;top:0;}

/* ============================================================================================
   R25 CLEANUP CL-20..24 (release 25 visual cleanup, BOSS 2026-10-26, D-282 item 8).
   CL-20 Bank Reconciliation: no new rule (the grey card is the page's plain .gate with a .pill.neutral).
   CL-21 DOCUMENT MANAGEMENT ROW MENU. The open "..." menu is laid over the page (position:fixed; the page's
   placeRowMenu() sets top / right from its button), so the table frame no longer cuts it; it is as wide
   as its longest item ("Move to folder...") and opens above the row, clear of the Status pill.
   ============================================================================================ */
.rowmenu > .rowmenu-pop{position:fixed;top:auto;right:auto;width:max-content;}
.rowmenu > .rowmenu-pop .rowmenu-item{white-space:nowrap;}
/* R25 check fix: a fixed menu is still painted through its .table-scroll, so the scroll cue's fade MASK
   (.ts-more) erased every item outside the table frame (only "Archive" showed). The mask is dropped while
   a menu is open. And the file list fits its pane at 1366 (with or without a classic scrollbar), so no
   fade cuts the "..." column: the Document column may narrow to --cw-file (a long name wraps). */
:root{--cw-file:210px;}
.table-scroll.rowmenu-open{-webkit-mask-image:none;mask-image:none;}
table.dm-files th.col-desc{min-width:var(--cw-file);}
.dm-files td.dm-fcell{overflow-wrap:anywhere;}

/* CL-22 TEXT INSIDE ITS BOX. Purchase Request charging rows: the charging, requested amount and balance
   boxes line up at the top; the short "Exceeds balance" badge sits under the row at the balance box's
   right edge. A read-only text box marked .ro-fit grows to its text (the page sets its height on load). */
table.chg-grid > tbody > tr.chg-row > td{vertical-align:top;}
table.chg-grid td.chg-baltd{text-align:right;}
