:root[data-theme="dark"]{
  --bg:#16181d; --bg2:#1e2128; --card:#23262e; --card2:#2a2e37; --border:#32363f;
  --text:#e8eaed; --text2:#9aa0ab; --accent:#7c6cf0; --accent2:#9d8ff5;
  --accent-rgb:124,108,240; --accent2-rgb:157,143,245;
  --green:#2ecc8f; --red:#f0616d; --amber:#f5b041;
  --heat-1:#ffffb2; --heat-2:#fecc5c; --heat-3:#fd8d3c; --heat-4:#f03b20; --heat-5:#bd0026;
  --flag-can-rgb:213,0,50; --flag-usa-red-rgb:178,34,52; --flag-usa-blue-rgb:60,59,110; --card2-rgb:42,46,55;
  --shadow:0 4px 14px rgba(0,0,0,.35); --logoFilter:none;
}
:root[data-theme="light"]{
  --bg:#f4f5f7; --bg2:#ffffff; --card:#ffffff; --card2:#f0f1f4; --border:#e2e4e9;
  --text:#20232a; --text2:#6b7280; --accent:#6c5ce7; --accent2:#8577ec;
  --accent-rgb:108,92,231; --accent2-rgb:133,119,236;
  --green:#0ea371; --red:#dc4854; --amber:#d97706;
  --heat-1:#ffffb2; --heat-2:#fecc5c; --heat-3:#fd8d3c; --heat-4:#f03b20; --heat-5:#bd0026;
  --flag-can-rgb:213,0,50; --flag-usa-red-rgb:178,34,52; --flag-usa-blue-rgb:60,59,110; --card2-rgb:240,241,244;
  --shadow:0 2px 10px rgba(20,20,40,.08); --logoFilter:invert(1) opacity(.85);
}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Segoe UI',system-ui,-apple-system,sans-serif;background:var(--bg);color:var(--text);overflow-x:hidden}
a{color:var(--accent2)}
/* ---------- utility bar (far-left icon rail) ---------- */
.utilbar{position:fixed;left:0;top:0;bottom:0;width:56px;background:var(--bg2);border-right:1px solid var(--border);display:flex;flex-direction:column;align-items:center;justify-content:space-between;padding:14px 0;z-index:60}
.ub-top,.ub-bottom{display:flex;flex-direction:column;gap:10px}
.ub-btn{width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text2);border:1px solid transparent;transition:.15s}
.ub-btn:hover{background:var(--card);color:var(--text)}
.ub-btn.active{background:linear-gradient(135deg,var(--accent),var(--accent2));color:#fff;box-shadow:0 4px 12px rgba(124,108,240,.35)}
.ub-btn svg{width:19px;height:19px}
/* ---------- sidebar (navigation pane) ---------- */
.sidebar{position:fixed;left:56px;top:0;bottom:0;width:232px;background:var(--bg2);border-right:1px solid var(--border);display:flex;flex-direction:column;z-index:50}
.welcome{padding:14px 18px;border-bottom:1px solid var(--border);font-size:13.5px;color:var(--text2)}
.welcome b{color:var(--text);text-transform:capitalize}
.nav-sec{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.8px;color:var(--text2);padding:4px 14px 6px}
.nav-subsec{font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--text2);opacity:.7;padding:10px 14px 4px}
.nav-add{border:1px dashed var(--border);color:var(--text2);margin-top:6px}
.nav-add:hover{border-color:var(--accent);color:var(--accent2)}
.logo-wrap{padding:22px 18px 14px;border-bottom:1px solid var(--border);cursor:pointer}
.logo-wrap img{max-width:160px;filter:var(--logoFilter)}
.logo-fallback{display:none;font-weight:700;font-size:17px;letter-spacing:.5px}
.nav{flex:1;padding:14px 10px;display:flex;flex-direction:column;gap:4px;overflow-y:auto;min-height:0}
.nav-empty{font-size:12px;color:var(--text2);padding:12px 14px;line-height:1.6;border:1px dashed var(--border);border-radius:10px}
.nav-item{display:flex;align-items:center;gap:12px;padding:11px 14px;border-radius:10px;cursor:pointer;color:var(--text2);font-size:14.5px;font-weight:500;transition:all .15s;border:1px solid transparent;user-select:none}
.nav-item:hover{background:var(--card);color:var(--text)}
.nav-item.active{background:linear-gradient(135deg,var(--accent),var(--accent2));color:#fff;box-shadow:0 4px 12px rgba(124,108,240,.35)}
.nav-item svg{width:19px;height:19px;flex-shrink:0}
.nav-item .nav-label{flex:1;min-width:0;line-height:1.3}
.nav-fav{flex-shrink:0;padding:2px 5px;border-radius:6px;font-size:15px;line-height:1;color:var(--text2);opacity:.45}
.nav-fav:hover{opacity:1}
.nav-fav.active{opacity:1;color:#f0b429}
.nav-item.active .nav-fav{color:rgba(255,255,255,.75)}
.nav-item.active .nav-fav.active{color:#ffe08a}
.side-bottom{padding:14px 10px;border-top:1px solid var(--border);display:flex;flex-direction:column;gap:8px}
.side-bottom .nav-item{font-size:13.5px;padding:9px 14px}
.theme-toggle{display:flex;align-items:center;justify-content:space-between;padding:9px 14px;border-radius:10px;background:var(--card);border:1px solid var(--border);cursor:pointer;font-size:13px;color:var(--text2)}
.switch{width:38px;height:20px;border-radius:20px;background:var(--border);position:relative;transition:.2s;flex-shrink:0}
.switch::after{content:'';position:absolute;width:16px;height:16px;border-radius:50%;background:#fff;top:2px;left:2px;transition:.2s}
[data-theme="dark"] .switch{background:var(--accent)}
[data-theme="dark"] .switch::after{left:20px}
/* ---------- main ---------- */
.main{margin-left:288px;padding:22px 26px 60px;min-height:100vh}
.topbar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:14px;margin-bottom:20px}
.page-title h1{font-size:22px;font-weight:700}
.page-title p{display:none}
.controls{display:flex;gap:9px;flex-wrap:wrap;align-items:center}
.topbar-right{display:flex;gap:12px;flex-wrap:wrap;align-items:center}

/* Privacy Mode toggle — persistent top-right switch (index.html), lives outside #pageControls/#page
   so it never gets masked itself (the user needs to see it to turn masking back off). */
.privacy-toggle{display:flex;align-items:center;gap:9px;padding:7px 12px;border-radius:10px;background:var(--card);
  border:1px solid var(--border);font-size:12.5px;font-weight:600;color:var(--text2);cursor:pointer;user-select:none;flex-shrink:0;transition:.15s}
.pm-label{display:inline-flex;align-items:center;gap:6px}
.pm-label svg{width:14px;height:14px;flex-shrink:0}
.privacy-toggle:hover{color:var(--text);border-color:var(--accent2)}
.privacy-toggle.active{color:var(--red);border-color:var(--red);background:rgba(240,97,109,.1)}
.pm-switch{position:relative;display:inline-flex;width:36px;height:20px;flex-shrink:0}
.pm-switch input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer;width:100%;height:100%}
.pm-track{position:absolute;inset:0;background:var(--border);border-radius:20px;transition:.2s}
.pm-thumb{position:absolute;width:16px;height:16px;border-radius:50%;background:#fff;top:2px;left:2px;transition:.2s;box-shadow:0 1px 3px rgba(0,0,0,.3)}
.pm-switch input:checked+.pm-track{background:var(--red)}
.pm-switch input:checked+.pm-track .pm-thumb{left:18px}
select,.btn,input[type=text]{background:var(--card);border:1px solid var(--border);color:var(--text);padding:8px 12px;border-radius:9px;font-size:13px;outline:none;font-family:inherit}
select:focus,input[type=text]:focus{border-color:var(--accent)}
.btn{cursor:pointer;font-weight:600;display:inline-flex;align-items:center;gap:7px;transition:.15s}
.btn:hover{border-color:var(--accent);color:var(--accent2)}
.btn.primary{background:linear-gradient(135deg,var(--accent),var(--accent2));color:#fff;border:none}
.btn.primary:hover{opacity:.9;color:#fff}
.btn.danger:hover{border-color:var(--red);color:var(--red)}
.btn:disabled{opacity:.4;cursor:default;pointer-events:none}
.btn-icon{padding:6px 9px}
.btn-icon svg{width:19px;height:19px;display:block}
.btn-icon.syncing svg{animation:ua-spin .8s linear infinite}
@keyframes ua-spin{to{transform:rotate(360deg)}}
/* ---------- cards ---------- */
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));gap:14px;margin-bottom:18px}
.kpi{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:18px;box-shadow:var(--shadow);position:relative;overflow:hidden}
.kpi::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--accent),transparent)}
.kpi .lbl{font-size:12px;color:var(--text2);font-weight:600;text-transform:uppercase;letter-spacing:.6px}
.kpi .val{font-size:26px;font-weight:700;margin-top:6px}
.kpi .sub{font-size:12px;margin-top:5px;color:var(--text2)}
.card{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:18px;box-shadow:var(--shadow)}
.card h3{font-size:14.5px;font-weight:700;margin-bottom:4px}
.card .hint{font-size:12px;color:var(--text2);margin-bottom:12px}
/* ---------- tables ---------- */
.tbl-wrap{overflow-x:auto;max-height:480px;overflow-y:auto}
table{width:100%;border-collapse:collapse;font-size:13px}
th{position:sticky;top:0;background:var(--card2);color:var(--text2);font-size:11.5px;text-transform:uppercase;letter-spacing:.5px;text-align:left;padding:9px 10px;z-index:2;white-space:nowrap}
td{padding:8px 10px;border-top:1px solid var(--border);white-space:nowrap}
tr:hover td{background:var(--card2)}
.tag{display:inline-block;padding:2px 9px;border-radius:20px;font-size:11px;font-weight:600;background:var(--card2);color:var(--text2)}
.tag.acc{background:rgba(var(--accent-rgb),.15);color:var(--accent2)}
.tag.red{background:rgba(240,97,109,.13);color:var(--red)}
.tag.grn{background:rgba(46,204,143,.13);color:var(--green)}
.tag.amb{background:rgba(245,176,65,.15);color:var(--amber)}
/* modifier for a tag carrying a multi-word phrase (e.g. "Requires Classification!") instead of a
   single short code — the base .tag is a tight single-line pill, so a long phrase forced into it
   wraps under aggressive break-word/anywhere rules and reads as garbled/overlapping text. This
   drops the pill shape and lets the phrase wrap normally (only at spaces) with real line-height. */
.tag.wrap{display:inline;white-space:normal;line-height:1.4;word-break:normal;overflow-wrap:normal;padding:1px 0}
/* ---------- placeholder ---------- */
.placeholder{background:var(--card);border:1px dashed var(--border);border-radius:16px;padding:60px 30px;text-align:center;margin-top:10px}
.placeholder svg{width:52px;height:52px;color:var(--text2);margin-bottom:16px}
.placeholder h2{font-size:19px;margin-bottom:8px}
.placeholder p{color:var(--text2);font-size:14px;max-width:520px;margin:0 auto 22px;line-height:1.6}

/* ---------- login gate ---------- */
.login-bg{position:fixed;inset:0;background:var(--bg);display:none;align-items:center;justify-content:center;z-index:200}
.login-card{background:var(--card);border:1px solid var(--border);border-radius:16px;box-shadow:var(--shadow);padding:38px 34px;width:360px;max-width:92vw;display:flex;flex-direction:column;gap:11px;text-align:center}
.login-card img{max-width:180px;margin:0 auto 4px;filter:var(--logoFilter)}
.login-card .logo-fallback{margin:0 auto}
.login-card h2{font-size:18px;font-weight:700}
.login-card p{font-size:13px;color:var(--text2);margin-bottom:6px}
.login-card input{background:var(--bg2);border:1px solid var(--border);color:var(--text);padding:11px 13px;border-radius:10px;font-size:14px;outline:none;font-family:inherit;width:100%}
.login-card input:focus{border-color:var(--accent)}
.login-card .btn{justify-content:center;padding:11px;font-size:14px;margin-top:2px}
.login-err{font-size:12.5px;color:var(--red);min-height:16px}
.login-remember{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text2);cursor:pointer;user-select:none;margin-top:-2px}
.login-remember input{accent-color:var(--accent);width:15px;height:15px;cursor:pointer;flex-shrink:0}

/* ---------- modal ---------- */
.modal-bg{position:fixed;inset:0;background:rgba(0,0,0,.55);display:none;align-items:center;justify-content:center;z-index:100}
.modal-bg.open{display:flex}
.modal{background:var(--card);border:1px solid var(--border);border-radius:16px;padding:24px;width:640px;max-width:94vw;max-height:84vh;display:flex;flex-direction:column;overflow-y:auto}
.modal h2{font-size:17px;margin-bottom:6px}
.modal p{font-size:13px;color:var(--text2);line-height:1.55;margin-bottom:14px}
.modal-actions{margin-top:16px;display:flex;justify-content:flex-end;gap:9px}
.modal input[type=text],.modal input[type=password]{width:100%;background:var(--card2);border:1px solid var(--border);color:var(--text);padding:9px 12px;border-radius:9px;font-size:13px;outline:none;font-family:inherit}
.modal input:focus{border-color:var(--accent)}
/* version history */
.ver-list{overflow-y:auto;display:flex;flex-direction:column;gap:10px;margin-top:4px}
.ver{border:1px solid var(--border);border-radius:12px;padding:12px 14px;background:var(--card2)}
.ver-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ver-head .vt{font-weight:700;font-size:13.5px}
.ver-head .vd{font-size:11.5px;color:var(--text2)}
.ver-head .grow{flex:1}
.ver-changes{margin-top:9px;border-top:1px solid var(--border);padding-top:8px;display:flex;flex-direction:column;gap:4px;max-height:200px;overflow-y:auto}
.ver-chg{font-size:12px;color:var(--text2);line-height:1.5}
.ver-chg b{color:var(--text);font-weight:600}
.ver-more{font-size:11.5px;color:var(--text2);font-style:italic;margin-top:2px}
/* junk-row cleanup */
.clean-pick{display:flex;align-items:center;gap:9px;cursor:pointer}
.clean-pick input{accent-color:var(--accent);width:15px;height:15px;cursor:pointer;flex-shrink:0}

/* ================= Developer workspace ================= */
.dev-layout{display:grid;grid-template-columns:248px 1fr 230px;gap:14px;align-items:start}
@media(max-width:1300px){.dev-layout{grid-template-columns:230px 1fr}.dev-steps{grid-column:1/-1}}
@media(max-width:1000px){.dev-layout{grid-template-columns:1fr}.dev-steps{grid-column:auto}}
.dev-side{background:var(--card);border:1px solid var(--border);border-radius:14px;box-shadow:var(--shadow);display:flex;flex-direction:column;overflow:hidden;position:sticky;top:22px}
.dev-side-head{padding:14px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}
.dev-side-head h3{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--text2)}
.dev-files{padding:10px;display:flex;flex-direction:column;gap:6px;overflow-y:auto;max-height:52vh}
.dev-file{padding:10px 12px;border-radius:10px;border:1px solid transparent;cursor:pointer;transition:.15s;position:relative}
.dev-file:hover{background:var(--card2)}
.dev-file.active{background:var(--card2);border-color:var(--accent)}
.dev-file .fn{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-right:20px}
.dev-file .fs{font-size:11.5px;color:var(--text2);margin-top:3px}
.dev-file .dev-sync{font-size:10.5px;font-weight:600;color:var(--green);margin-top:4px;display:flex;align-items:center;gap:4px;cursor:help}
.dev-file .del{position:absolute;top:8px;right:8px;width:20px;height:20px;border-radius:6px;display:none;align-items:center;justify-content:center;color:var(--text2);font-size:14px;line-height:1}
.dev-file:hover .del{display:flex}
.dev-file .del:hover{background:var(--border);color:var(--red)}
.dev-empty{font-size:12.5px;color:var(--text2);padding:14px;line-height:1.6;text-align:center}
.dev-drop{margin:10px;border:2px dashed var(--border);border-radius:12px;padding:22px 14px;text-align:center;cursor:pointer;transition:.15s;font-size:12.5px;color:var(--text2)}
.dev-drop:hover,.dev-drop.over{border-color:var(--accent);color:var(--accent2)}
.dev-main{background:var(--card);border:1px solid var(--border);border-radius:14px;box-shadow:var(--shadow);padding:16px;min-width:0}
.dev-toolbar{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:12px}
.dev-toolbar .grow{flex:1}
.dev-status{font-size:12px;color:var(--text2)}
.dev-status.saving{color:var(--amber)}
.dev-status.saved{color:var(--green)}
.sheet-tabs{display:flex;gap:6px;overflow-x:auto;margin-bottom:12px;padding-bottom:4px}
.sheet-tab{display:flex;align-items:center;gap:7px;padding:6px 14px;border-radius:8px;font-size:12.5px;font-weight:600;background:var(--card2);border:1px solid var(--border);color:var(--text2);cursor:pointer;white-space:nowrap;transition:.15s}
.sheet-tab:hover{color:var(--text)}
.sheet-tab.active{background:linear-gradient(135deg,var(--accent),var(--accent2));color:#fff;border-color:transparent}
.sheet-tab .tab-del{display:none;width:15px;height:15px;align-items:center;justify-content:center;border-radius:5px;font-size:11px;line-height:1;margin-right:-4px}
.sheet-tab:hover .tab-del{display:inline-flex}
.sheet-tab .tab-del:hover{background:rgba(240,97,109,.25);color:var(--red)}
.sheet-tab.active .tab-del:hover{background:rgba(255,255,255,.25);color:#fff}
.sheet-tab.add{padding:6px 11px;font-size:14px;border-style:dashed}
.sheet-tab.add:hover{border-color:var(--accent);color:var(--accent2)}
/* grid */
.grid-wrap{overflow:auto;max-height:64vh;border:1px solid var(--border);border-radius:10px}
.grid-wrap table{width:auto;min-width:100%}
.grid-wrap th{cursor:default;text-transform:none;font-size:11px}
.grid-wrap th.colhead{text-align:center;min-width:90px}
.grid-wrap td.rownum,.grid-wrap th.corner{position:sticky;left:0;background:var(--card2);color:var(--text2);font-size:11px;text-align:center;min-width:52px;z-index:3;user-select:none}
.grid-wrap th.corner{z-index:4}
.grid-wrap td.rownum .rn{display:inline}
.grid-wrap td.rownum .rowdel{display:none;color:var(--red);cursor:pointer;font-weight:700}
.grid-wrap tr:hover td.rownum .rn{display:none}
.grid-wrap tr:hover td.rownum .rowdel{display:inline}
.grid-wrap td.cell{min-width:90px;max-width:340px;overflow:hidden;text-overflow:ellipsis;outline:none;cursor:cell}
.grid-wrap td.cell:focus{outline:2px solid var(--accent);outline-offset:-2px;background:var(--bg2);cursor:text;white-space:normal;overflow:visible;max-width:none}
.grid-wrap td.cell.num{text-align:right;font-variant-numeric:tabular-nums}
/* alignment (cell overrides column; both override the automatic number right-align) */
.grid-wrap td.cell.al-l{text-align:left}
.grid-wrap td.cell.al-c{text-align:center}
.grid-wrap td.cell.al-r{text-align:right}
.grid-wrap th.colhead{cursor:pointer;position:relative;padding-right:24px;padding-left:18px;user-select:none}
.grid-wrap th.colhead.sel{background:rgba(124,108,240,.28);color:var(--accent2)}
.grid-wrap td.cell.colsel{background:rgba(124,108,240,.07)}
.grid-wrap th.colhead .flt-btn{position:absolute;right:4px;top:50%;transform:translateY(-50%);font-size:8px;padding:3px 5px;border-radius:5px;color:var(--text2);cursor:pointer}
.grid-wrap th.colhead .flt-btn:hover{background:var(--border);color:var(--text)}
.grid-wrap th.colhead .flt-btn.on{color:#fff;background:var(--accent)}
.grid-wrap th.colhead .col-del{display:none;position:absolute;left:4px;top:50%;transform:translateY(-50%);font-size:11px;font-weight:700;color:var(--text2);cursor:pointer;padding:3px 4px;border-radius:5px}
.grid-wrap th.colhead:hover .col-del{display:inline}
.grid-wrap th.colhead .col-del:hover{background:rgba(240,97,109,.25);color:var(--red)}
/* segmented toolbar buttons (alignment) */
.btn-seg{display:inline-flex}
.btn-seg .btn{border-radius:0;margin-left:-1px;padding:8px 9px}
.btn-seg .btn:first-child{border-radius:9px 0 0 9px;margin-left:0}
.btn-seg .btn:last-child{border-radius:0 9px 9px 0}
.btn-seg .btn.on{border-color:var(--accent);color:var(--accent2);position:relative;z-index:1;background:rgba(124,108,240,.12)}
.btn-seg .btn svg{width:14px;height:14px}
/* promoted header row (Use first row as headers): names live in the thead */
.grid-wrap th.colhead.named{padding-top:5px;padding-bottom:5px;vertical-align:top}
.grid-wrap th.colhead.named .cl{display:block;font-size:9px;color:var(--text2);opacity:.8;letter-spacing:.5px}
.grid-wrap th.colhead.named .cn{display:block;font-size:12px;font-weight:700;color:var(--accent2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px;border-radius:5px;padding:1px 3px;cursor:text}
.grid-wrap th.colhead.named .cn i{color:var(--text2);font-weight:400}
.grid-wrap th.colhead.named .cn[contenteditable="true"]{outline:2px solid var(--accent);background:var(--bg2);color:var(--text);white-space:normal;overflow:visible}
/* select-all corner */
.grid-wrap th.corner{cursor:pointer}
.grid-wrap th.corner:hover{color:var(--accent2)}
.grid-wrap th.corner.sel{background:rgba(124,108,240,.28)!important;color:var(--accent2)}
/* transform dropdown menu */
.menu-pop{position:fixed;z-index:130;min-width:224px;background:var(--card);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow);padding:6px;display:flex;flex-direction:column}
.menu-item{padding:8px 12px;font-size:13px;border-radius:8px;cursor:pointer;user-select:none}
.menu-item:hover{background:var(--card2);color:var(--accent2)}
.menu-div{height:1px;background:var(--border);margin:5px 8px}
/* modal form rows (transform dialogs) */
.form-row{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.form-row label{font-size:12.5px;color:var(--text2);width:104px;flex-shrink:0}
.form-row select,.form-row input{flex:1;width:auto;background:var(--card2);border:1px solid var(--border);color:var(--text);padding:8px 11px;border-radius:9px;font-size:13px;outline:none;font-family:inherit}
.form-row select:focus,.form-row input:focus{border-color:var(--accent)}
/* column filter popup */
.flt-pop{position:fixed;z-index:130;width:258px;background:var(--card);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow);padding:11px;display:flex;flex-direction:column;gap:8px}
.flt-title{font-weight:700;font-size:12.5px}
.flt-title span{color:var(--text2);font-weight:400}
.flt-pop input[type=text]{width:100%;background:var(--card2);border:1px solid var(--border);color:var(--text);padding:6px 9px;border-radius:8px;font-size:12.5px;outline:none;font-family:inherit}
.flt-pop input[type=text]:focus{border-color:var(--accent)}
.flt-list{overflow-y:auto;max-height:230px;display:flex;flex-direction:column}
.flt-item{display:flex;align-items:center;gap:8px;font-size:12.5px;padding:4px 6px;border-radius:6px;cursor:pointer;user-select:none}
.flt-item:hover{background:var(--card2)}
.flt-item input{accent-color:var(--accent);flex-shrink:0}
.flt-item .v{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.flt-item .v i{color:var(--text2)}
.flt-item .n{margin-left:auto;font-size:11px;color:var(--text2);flex-shrink:0}
.flt-all{border-bottom:1px solid var(--border);border-radius:6px 6px 0 0}
.flt-note{font-size:11px;color:var(--text2)}
.flt-actions{display:flex;gap:6px;align-items:center}
.flt-actions .grow{flex:1}
.flt-actions .btn{padding:5px 10px;font-size:12px}
/* Applied Steps panel (Power BI-style) */
.dev-steps{background:var(--card);border:1px solid var(--border);border-radius:14px;box-shadow:var(--shadow);display:flex;flex-direction:column;overflow:hidden;position:sticky;top:22px;max-height:calc(100vh - 44px)}
.steps-list{padding:8px;display:flex;flex-direction:column;gap:4px;overflow-y:auto}
.step-row{display:flex;align-items:center;gap:8px;padding:8px 9px;border-radius:9px;font-size:12.5px;position:relative;border:1px solid transparent}
.step-row:hover{background:var(--card2)}
.step-row.cur{border-color:var(--accent);background:rgba(124,108,240,.08)}
.step-n{width:18px;height:18px;border-radius:5px;background:var(--card2);color:var(--text2);font-size:10.5px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.step-row.cur .step-n{background:var(--accent);color:#fff}
.step-lbl{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.step-x{display:none;width:18px;height:18px;border-radius:5px;align-items:center;justify-content:center;font-size:11px;color:var(--text2);cursor:pointer;flex-shrink:0}
.step-row:hover .step-x{display:flex}
.step-x:hover{background:rgba(240,97,109,.2);color:var(--red)}
.pager{display:flex;align-items:center;gap:10px;margin-top:12px;font-size:12.5px;color:var(--text2);flex-wrap:wrap}
.pager .btn{padding:5px 11px;font-size:12px}
.footer-note{font-size:11.5px;color:var(--text2);margin-top:24px;line-height:1.6}
/* ================= Data model page ================= */
.model-bar{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:14px}
.model-bar .grow{flex:1}
.model-canvas{position:relative;background:var(--card);border:1px solid var(--border);border-radius:14px;box-shadow:var(--shadow);height:calc(100vh - 240px);min-height:420px;overflow:auto}
.model-inner{position:relative;width:2200px;height:1500px}
.model-svg{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.model-svg .rel{stroke:var(--accent);stroke-width:2;fill:none;opacity:.75;pointer-events:none}
.model-svg .rel-hit{stroke:transparent;stroke-width:16;fill:none;cursor:pointer;pointer-events:stroke}
.model-svg .rel-hit:hover+.rel{stroke-width:3.5;opacity:1}
.model-svg text{fill:var(--accent2);font-size:12px;font-weight:700;pointer-events:none}
.mt{position:absolute;width:208px;background:var(--card2);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow);z-index:2}
.mt.missing{border-color:var(--red)}
.mt-head{padding:9px 12px;border-bottom:1px solid var(--border);cursor:grab;user-select:none;background:linear-gradient(135deg,rgba(124,108,240,.22),transparent);border-radius:12px 12px 0 0;position:relative}
.mt-head:active{cursor:grabbing}
.mt-head b{font-size:13px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding-right:18px}
.mt-head .sub{font-size:10.5px;color:var(--text2);display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}
.mt-head .del{position:absolute;top:7px;right:7px;width:18px;height:18px;border-radius:5px;display:none;align-items:center;justify-content:center;color:var(--text2);font-size:12px;cursor:pointer}
.mt:hover .mt-head .del{display:flex}
.mt-head .del:hover{background:var(--border);color:var(--red)}
.mt-cols{max-height:176px;overflow-y:auto;padding:5px 0}
.mt-col{padding:3px 12px;font-size:12px;color:var(--text2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mt-col.linked{color:var(--accent2);font-weight:600}
.mt-col.linked::before{content:'🔗 ';font-size:10px}
.mt-col.err{color:var(--red);white-space:normal}
.model-empty{position:absolute;top:60px;left:50%;transform:translateX(-50%);text-align:center;max-width:460px}
.model-empty h2{font-size:18px;margin-bottom:8px}
.model-empty p{color:var(--text2);font-size:13.5px;line-height:1.6;margin-bottom:18px}
/* ================= report pages & visuals (Power BI-style) ================= */
/* free canvas: visuals carry x/y/w/h, drag by header, resize from the corner */
.canvas-wrap{overflow-x:auto}
.page-canvas{position:relative;width:1240px;min-height:480px;background-image:radial-gradient(var(--border) 1px,transparent 1px);background-size:32px 32px;border-radius:8px}
.vis{position:absolute;background:var(--card);border:1px solid var(--border);border-radius:14px;padding:12px 14px;box-shadow:var(--shadow);min-width:0;display:flex;flex-direction:column;overflow:hidden}
.vis.editing{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent),var(--shadow);z-index:5}
.vis-rsz{position:absolute;right:0;bottom:0;width:16px;height:16px;cursor:nwse-resize;opacity:0;border-right:3px solid var(--accent);border-bottom:3px solid var(--accent);border-bottom-right-radius:12px}
.vis:hover .vis-rsz{opacity:.75}
.vis-body{overflow:auto}
.vis-head{display:flex;align-items:center;gap:6px;margin-bottom:10px;cursor:grab;user-select:none;flex-shrink:0}
.vis-head:active{cursor:grabbing}
.vis-head h3{font-size:13.5px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vis-head .grow{flex:1}
.vis-act{display:none;width:22px;height:22px;border-radius:6px;align-items:center;justify-content:center;font-size:11px;color:var(--text2);cursor:pointer;flex-shrink:0}
.vis:hover .vis-act{display:inline-flex}
.vis-act:hover{background:var(--card2);color:var(--accent2)}
.vis-body{flex:1;min-height:60px}
.vis-load,.vis-err,.vis-note{font-size:12px;color:var(--text2);padding:6px 0}
.vis-err{color:var(--red)}
.vis-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;min-height:150px;color:var(--text2);font-size:12.5px;border:1px dashed var(--border);border-radius:10px}
.vis-empty svg{width:38px;height:38px;opacity:.6}
.vis-num{font-size:34px;font-weight:700;margin-top:4px}
.vis-num-sub{font-size:11.5px;color:var(--text2);margin-top:4px}
/* series legend */
.vlegend{display:flex;flex-wrap:wrap;gap:4px 14px;margin-bottom:8px}
.vleg-i{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--text2)}
.vleg-i .dot,.pie-li .dot{width:10px;height:10px;border-radius:3px;flex-shrink:0;display:inline-block}
/* horizontal bar chart (grouped) */
.bars{display:flex;flex-direction:column;gap:8px}
.bar-grp{display:grid;grid-template-columns:minmax(60px,32%) 1fr;align-items:center;gap:9px;font-size:12px}
.bar-lbl{color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:right}
.bar-set{display:flex;flex-direction:column;gap:2px}
.bar-track{position:relative;background:var(--card2);border-radius:5px;height:16px;display:flex;align-items:center}
.bar-fill{display:block;height:100%;border-radius:5px;flex-shrink:0}
.bar-val{font-weight:600;font-size:11px;font-variant-numeric:tabular-nums;white-space:nowrap;margin-left:6px}
/* XY charts (column / line / area) */
.vis-xy{width:100%;height:auto;display:block}
.vis-xy .ln{fill:none;stroke-width:2.5;stroke-linejoin:round}
.vis-xy .gl{stroke:var(--border);stroke-width:1}
.vis-xy .ax{fill:var(--text2);font-size:10px}
.vis-xy .dl{fill:var(--text);font-size:10px;font-weight:600}
/* pie / donut */
.pie-wrap{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.pie-wrap svg{width:170px;height:170px;flex-shrink:0}
.pie-leg{display:flex;flex-direction:column;gap:5px;min-width:0;flex:1}
.pie-li{display:flex;align-items:center;gap:8px;font-size:12px}
.pie-li .v{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text2)}
.pie-li .n{margin-left:auto;font-weight:600;white-space:nowrap}
/* matrix */
.matrix th,.matrix td{white-space:nowrap}
.matrix td{text-align:right;font-variant-numeric:tabular-nums}
.matrix .mx-rh{text-align:left;font-weight:600;position:sticky;left:0;background:var(--card);z-index:1}
.matrix .mx-corner{position:sticky;left:0;z-index:3}
.matrix .mx-tot{font-weight:700;border-left:1px solid var(--border)}
.matrix .mx-trow td{font-weight:700;border-top:2px solid var(--border)}
/* slicer */
.slicer-top{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.slicer-q{flex:1;background:var(--card2);border:1px solid var(--border);color:var(--text);padding:5px 9px;border-radius:7px;font-size:12px;outline:none;font-family:inherit;min-width:0}
.slicer-q:focus{border-color:var(--accent)}
.slicer-clear{margin-left:auto;color:var(--text2);cursor:pointer;font-size:13px;padding:3px 6px;border-radius:6px}
.slicer-clear:hover{background:var(--card2);color:var(--red)}
.slicer-dd{width:100%;background:var(--card2);border:1px solid var(--border);color:var(--text);padding:7px 10px;border-radius:8px;font-size:12.5px;outline:none;font-family:inherit}
.slicer-list{display:flex;flex-direction:column;max-height:260px;overflow-y:auto}
.slicer-item{display:flex;align-items:center;gap:9px;padding:4px 6px;border-radius:6px;font-size:12.5px;cursor:pointer;user-select:none;color:var(--text2)}
.slicer-item:hover{background:var(--card2)}
.slicer-item.on{color:var(--text);font-weight:600}
.slicer-item input{accent-color:var(--accent);flex-shrink:0}
.slicer-item span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* ---------- editor pane (Visualizations + Format) ---------- */
#visDrawer{position:fixed;top:0;right:0;bottom:0;width:304px;background:var(--bg2);border-left:1px solid var(--border);box-shadow:-6px 0 22px rgba(0,0,0,.25);z-index:95;display:flex;flex-direction:column}
.vd-head{display:flex;align-items:center;gap:8px;padding:14px 16px;border-bottom:1px solid var(--border);font-size:13.5px}
.vd-head .grow{flex:1}
.vd-x{cursor:pointer;color:var(--text2);width:22px;height:22px;display:flex;align-items:center;justify-content:center;border-radius:6px}
.vd-x:hover{background:var(--card);color:var(--red)}
.vd-gallery{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;padding:12px 14px;border-bottom:1px solid var(--border)}
.vg-i{aspect-ratio:1;display:flex;align-items:center;justify-content:center;border-radius:8px;border:1px solid var(--border);color:var(--text2);cursor:pointer;transition:.12s;background:var(--card)}
.vg-i:hover{border-color:var(--accent);color:var(--accent2)}
.vg-i.on{background:linear-gradient(135deg,var(--accent),var(--accent2));color:#fff;border-color:transparent}
.vg-i svg{width:19px;height:19px}
.vd-tabs{display:flex;gap:2px;padding:10px 14px 0}
.vd-tab{padding:7px 14px;font-size:12.5px;font-weight:600;color:var(--text2);cursor:pointer;border-bottom:2px solid transparent}
.vd-tab.on{color:var(--accent2);border-bottom-color:var(--accent)}
.vd-body{flex:1;overflow-y:auto;padding:12px 16px;display:flex;flex-direction:column;gap:11px}
.vd-foot{padding:12px 16px;border-top:1px solid var(--border)}
.vd-foot .btn{width:100%;justify-content:center}
/* field wells */
.well{display:flex;flex-direction:column;gap:5px}
.well>label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--text2)}
.well>label i{font-weight:400;text-transform:none;letter-spacing:0}
.well select,.well input[type=text],.well input[type=number]{width:100%;background:var(--card);border:1px solid var(--border);color:var(--text);padding:7px 10px;border-radius:8px;font-size:12.5px;outline:none;font-family:inherit}
.well select:focus,.well input:focus{border-color:var(--accent)}
.well input[type=color]{width:100%;height:32px;background:var(--card);border:1px solid var(--border);border-radius:8px;padding:3px;cursor:pointer}
.well-add{color:var(--text2)!important;border-style:dashed!important}
.well-hint{font-size:10.5px;color:var(--text2);font-style:italic}
.chip{display:flex;align-items:center;gap:7px;background:var(--card);border:1px solid var(--accent);border-radius:8px;padding:5px 8px;font-size:12.5px}
.chip-n{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.chip-agg{background:var(--card2);border:1px solid var(--border);color:var(--text2);border-radius:6px;font-size:11px;padding:2px 4px;outline:none;font-family:inherit;flex-shrink:0;width:76px}
.chip-fx{font-style:italic;font-weight:700;font-size:11px;color:var(--amber);flex-shrink:0}
/* DAX: measures & calculated columns */
.mt-foot{display:flex;gap:6px;padding:7px 9px;border-top:1px solid var(--border)}
.mt-add{flex:1;text-align:center;font-size:10.5px;font-weight:600;color:var(--text2);border:1px dashed var(--border);border-radius:7px;padding:4px 2px;cursor:pointer}
.mt-add:hover{border-color:var(--accent);color:var(--accent2)}
.mt-col.calc{color:var(--green);cursor:pointer}
.mt-col.calc::before{content:'ƒ ';font-style:italic}
.mt-col.meas{color:var(--amber);cursor:pointer;border-top:1px dashed var(--border);margin-top:2px;padding-top:4px}
.mt-col.meas i{font-style:italic;font-weight:700;font-size:10px;margin-right:3px}
.mt-col.calc:hover,.mt-col.meas:hover{text-decoration:underline}
.dax-src{width:100%;background:var(--bg2);border:1px solid var(--border);color:var(--text);padding:10px 12px;border-radius:9px;font-size:13px;outline:none;font-family:Consolas,'Cascadia Code',monospace;resize:vertical;line-height:1.5}
.dax-src:focus{border-color:var(--accent)}
.dax-check{font-size:12px;min-height:18px;margin:2px 0 6px}
.dax-check .ok{color:var(--green)}
.dax-check .bad{color:var(--red)}
.dax-help{font-size:11px;color:var(--text2);line-height:1.6;background:var(--card2);border-radius:9px;padding:9px 12px}
.chip-x{color:var(--text2);cursor:pointer;flex-shrink:0;width:17px;height:17px;display:flex;align-items:center;justify-content:center;border-radius:5px;font-size:10px}
.chip-x:hover{background:var(--border);color:var(--red)}
/* format pane */
.fmt-sec{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--accent2);border-bottom:1px solid var(--border);padding-bottom:5px;margin-top:4px}
.fmt-row{display:flex;align-items:center;gap:8px;font-size:12.5px;cursor:pointer;user-select:none;padding:2px 0}
.fmt-row .grow{flex:1}
.fmt-row input{accent-color:var(--accent);width:16px;height:16px;cursor:pointer}
/* ================= Homepage (hand-built operations dashboard) ================= */
.home{display:flex;flex-direction:column;gap:14px}
.home-kpis{display:grid;grid-template-columns:repeat(6,1fr);gap:12px}
@media(max-width:1100px){.home-kpis{grid-template-columns:repeat(3,1fr)}}
.home-kpi{background:var(--card);border:1px solid var(--border);border-radius:14px;padding:16px 18px;box-shadow:var(--shadow);position:relative;overflow:hidden}
/* continuously-running accent line (2026-07-15, per the user — "should be running consistently",
   not a static gradient): a two-tone bar that tiles seamlessly (same color at 0% and 100% of one
   tile) so an infinite background-position loop never jumps or resets visibly. */
.home-kpi::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--accent) 0%,var(--accent2) 50%,var(--accent) 100%);background-size:200% 100%;animation:home-kpi-run 3s linear infinite}
.home-kpi.hl::before{background:linear-gradient(90deg,var(--green) 0%,var(--accent2) 50%,var(--green) 100%);background-size:200% 100%}
@keyframes home-kpi-run{from{background-position:0% 0}to{background-position:200% 0}}
@media(prefers-reduced-motion:reduce){.home-kpi::before{animation:none;background-position:0 0}}
.hk-val{font-size:24px;font-weight:700;letter-spacing:-.5px}
.hk-val.neg{color:var(--red)}
.hk-lbl{font-size:12px;color:var(--text2);font-weight:600;margin-top:5px}
.home-mid{display:grid;grid-template-columns:1fr 300px;gap:14px;align-items:stretch}
@media(max-width:760px){.home-mid{grid-template-columns:1fr;align-items:start}.home-gauges{flex-direction:column}}
/* .home-area / .home-legend / .hl-i were built for the Homepage FY trend chart (replaced by the
   Insights ticker 2026-08-08) and are now used by the Inventory Report's monthly bar chart — keep. */
.home-area{width:100%;height:auto;display:block}
.home-area .gl{stroke:var(--border);stroke-width:1}
.home-area .ax{fill:var(--text2);font-size:14px}
.home-area .ax.yr{fill:var(--text2);opacity:.6;font-size:12px}
.home-legend{display:flex;justify-content:flex-end;gap:16px;flex-wrap:wrap;margin-top:6px}
.hl-i{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--text2)}
.hl-i .dot{width:11px;height:11px;border-radius:3px}
/* ---------- Insights rotator (2026-08-08) — the CP24-style headline board that replaced the
   Net Revenue Trend by Fiscal Year chart. Static text, one headline at a time — no flowing/scrolling
   marquee and no "LIVE" badge (the user's explicit call). js/insights.js swaps #homeInsCurrent's
   content on a randomized 6-8s timer (homeInsStart/homeInsTick); .hins-fade is toggled around the
   swap for a brief crossfade. ---------- */
.home-insights{padding:0;overflow:hidden}
.hins-bar{display:flex;align-items:stretch;min-height:46px}
.hins-brand{display:flex;align-items:center;gap:9px;padding:0 16px;flex-shrink:0;font-size:12.5px;font-weight:800;
  letter-spacing:1.4px;color:#fff;background:linear-gradient(135deg,var(--accent),var(--accent2));white-space:nowrap;
  transition:opacity .22s ease}
.hins-brand.hins-fade{opacity:0}
.hins-track{flex:1;min-width:0;overflow:hidden;display:flex;align-items:center;position:relative;padding:0 4px}
.hins-current{width:100%;transition:opacity .22s ease}
.hins-current.hins-fade{opacity:0}
.hins-item{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:6px;cursor:pointer;font-size:13.5px}
.hins-item:hover .hins-txt{color:var(--text);text-decoration:underline;text-underline-offset:3px}
.hins-tag{font-size:10.5px;font-weight:800;letter-spacing:.7px;text-transform:uppercase;border-radius:5px;
  padding:3px 8px;line-height:1.3;border:1px solid transparent;flex-shrink:0}
.hins-txt{color:var(--text2);font-weight:500}
/* tone -> colour, matching the tag/badge palette the report pages already use */
.hins-good .hins-tag{color:var(--green);background:rgba(46,204,143,.13);border-color:rgba(46,204,143,.4)}
.hins-warn .hins-tag{color:var(--amber);background:rgba(245,176,65,.13);border-color:rgba(245,176,65,.4)}
.hins-bad .hins-tag{color:var(--red);background:rgba(240,97,109,.13);border-color:rgba(240,97,109,.4)}
.hins-accent .hins-tag{color:var(--accent2);background:rgba(124,108,240,.14);border-color:rgba(124,108,240,.45)}
.hins-info .hins-tag{color:var(--text2);background:var(--card2);border-color:var(--border)}
.hins-muted .hins-tag{color:var(--text2);background:var(--card2);border-color:var(--border);opacity:.75}
.hins-muted .hins-txt{opacity:.75;font-style:italic}
.hins-ctrls{display:flex;align-items:center;gap:6px;padding:0 12px;flex-shrink:0;border-left:1px solid var(--border);
  opacity:0;pointer-events:none;transition:opacity .15s ease}
.home-insights:hover .hins-ctrls,.home-insights:focus-within .hins-ctrls{opacity:1;pointer-events:auto}
.hins-btn{padding:4px 10px;font-size:11.5px;line-height:1.4;white-space:nowrap}
.hins-empty{font-size:13px;color:var(--text2);padding:0 16px}
/* "▤ All" — the same headlines frozen into a readable list, for anyone who doesn't want to wait
   for one to come back around */
.hins-panel{border-top:1px solid var(--border);padding:14px 16px}
/* "All" panel groups its cards under a Daily / Weekly / Monthly heading per the timeframe on each
   headline (js/insights.js `period`), so a growing headline count stays scannable */
.hins-group{margin-bottom:16px}
.hins-group:last-child{margin-bottom:0}
.hins-group-lbl{font-size:11px;font-weight:800;letter-spacing:.6px;text-transform:uppercase;color:var(--text2);margin-bottom:8px}
.hins-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:10px}
@media(max-width:760px){.hins-grid{grid-template-columns:1fr}}
.hins-card{border:1px solid var(--border);border-radius:11px;background:var(--card2);padding:11px 13px;cursor:pointer;transition:.15s}
.hins-card:hover{transform:translateY(-1px);box-shadow:var(--shadow);border-color:var(--accent2)}
.hins-card-tag{font-size:10.5px;font-weight:800;letter-spacing:.7px;text-transform:uppercase;margin-bottom:6px}
.hins-good .hins-card-tag{color:var(--green)}
.hins-warn .hins-card-tag{color:var(--amber)}
.hins-bad .hins-card-tag{color:var(--red)}
.hins-accent .hins-card-tag{color:var(--accent2)}
.hins-info .hins-card-tag,.hins-muted .hins-card-tag{color:var(--text2)}
.hins-card-txt{font-size:13px;line-height:1.55;color:var(--text)}
.hins-panel .vis-note{margin-top:10px}
@media(max-width:900px){.hins-brand{padding:0 11px}}
/* Narrow screens: brand + controls keep the top row and the headline drops to a full-width row of
   its own. Left inline, the track was squeezed to ~80px between them — a headline could never be read. */
@media(max-width:720px){
  .hins-bar{flex-wrap:wrap}
  .hins-brand{flex:1;min-height:40px}
  .hins-ctrls{border-left:none}
  .hins-track{order:3;flex-basis:100%;min-height:42px;border-top:1px solid var(--border)}
}
/* Reduced motion: the headline still rotates (it's informational, not decorative), just without
   the crossfade — text swaps instantly. */
@media(prefers-reduced-motion:reduce){
  .hins-current,.hins-brand{transition:none}
}
/* Net Revenue Calendar — sits in the column the FY trend chart used to occupy. 7 day columns plus a
   fixed week-total rail; the grid takes the leftover card height (flex:1) so the month always fills
   the card without an internal scrollbar, and rows share it evenly however many weeks the month has. */
/* align-self:stretch keeps the calendar the same height as the chart stack beside it even at the
   ≤1300px breakpoint, where .home-mid switches to align-items:start and cards otherwise shrink to
   their own content (which left the calendar noticeably short next to the two stacked charts). */
.home-cal{display:flex;flex-direction:column;min-height:0;align-self:stretch}
.home-cal-area{flex:1;min-height:0;display:flex;flex-direction:column}
.home-cal-nav{display:flex;align-items:center;gap:7px;margin-bottom:8px;flex-wrap:wrap}
.hcal-nav-btn{padding:2px 9px;font-size:14px;line-height:1.3;font-weight:700}
.hcal-nav-btn[disabled]{opacity:.35;cursor:default}
.hcal-title{font-size:13.5px;font-weight:700;min-width:104px}
.hcal-today{padding:3px 9px;font-size:11px;line-height:1.3}
.hcal-sum{margin-left:auto;display:flex;flex-direction:column;align-items:flex-end;line-height:1.25}
.hcal-sum-v{font-size:14px;font-weight:800}
.hcal-sum-v.pos{color:var(--green)}
.hcal-sum-v.neg{color:var(--red)}
.hcal-sum-d{font-size:10.5px;color:var(--text2)}
/* grid-template-rows:auto sizes only the weekday-header row to its content; every week row after it
   falls to grid-auto-rows and shares the remaining height equally. */
.home-cal-grid{flex:1;min-height:0;display:grid;grid-template-columns:repeat(7,minmax(0,1fr)) 74px;grid-template-rows:auto;grid-auto-rows:minmax(46px,1fr);gap:3px}
.hcal-dow{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--text2);text-align:center;padding-bottom:2px}
.hcal-d{border:1px solid var(--border);border-radius:7px;padding:3px 2px;display:flex;flex-direction:column;overflow:hidden;min-width:0}
.hcal-d.empty{border-color:transparent;background:none}
.hcal-d.today{border-color:var(--accent2);box-shadow:inset 0 0 0 1px var(--accent2)}
.hcal-dn{font-size:10.5px;font-weight:700;color:var(--text2);line-height:1.15}
.hcal-v{font-size:11.5px;font-weight:800;line-height:1.2;margin-top:auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hcal-d.pos .hcal-v{color:var(--green)}
.hcal-d.neg .hcal-v{color:var(--red)}
.hcal-o{font-size:9px;color:var(--text2);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hcal-wk{border-radius:7px;background:var(--card2);padding:3px 6px;display:flex;flex-direction:column;justify-content:center;overflow:hidden}
.hcal-wk-lbl{font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--text2);line-height:1.2}
.hcal-wk-v{font-size:12px;font-weight:800;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hcal-wk-v.pos{color:var(--green)}
.hcal-wk-v.neg{color:var(--red)}
.hcal-wk-d{font-size:9.5px;color:var(--text2);line-height:1.2}
/* heat ramp (2026-07-31): the per-cell rgba fill is set inline in home.js from the day's net vs the
   month's peak. Past ~55% intensity the fill is saturated enough that green-on-green loses contrast,
   so .hot flips the figure and labels to the plain text colours (correct in both themes). */
.hcal-d.hot .hcal-v,.hcal-d.hot.pos .hcal-v,.hcal-d.hot.neg .hcal-v{color:var(--text)}
.hcal-d.hot .hcal-dn,.hcal-d.hot .hcal-o{color:var(--text);opacity:.75}
/* click-to-cross-filter Latest Activity */
.hcal-d.pick{cursor:pointer;transition:transform .1s ease,box-shadow .1s ease}
.hcal-d.pick:hover{transform:translateY(-1px);box-shadow:0 2px 8px rgba(0,0,0,.28)}
.hcal-d.sel{border-color:var(--accent2);box-shadow:inset 0 0 0 2px var(--accent2)}
.hcal-legend{display:flex;align-items:center;gap:4px}
.hcal-lg-lbl{font-size:9.5px;text-transform:uppercase;letter-spacing:.4px;color:var(--text2)}
.hcal-lg-ramp{width:58px;height:8px;border-radius:4px;border:1px solid var(--border);
  background:linear-gradient(90deg,rgba(34,197,94,.07),rgba(34,197,94,.80))}
@media(max-width:1180px){.hcal-legend{display:none}}
@media(max-width:900px){.home-cal-grid{grid-template-columns:repeat(7,minmax(0,1fr));grid-auto-rows:minmax(52px,1fr)}.hcal-wk{display:none}.home-cal-grid>.hcal-dow.wk{display:none}}
.home-gauges{display:flex;flex-direction:column;gap:14px}
.home-gauge{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:14px}
.hg-title{font-size:14px;font-weight:700;text-align:center;margin-bottom:4px}
.hg-svg{width:100%;max-width:280px;height:auto}
.hg-val{fill:var(--text);font-size:38px;font-weight:800}
.hg-ends{display:flex;justify-content:space-between;width:100%;max-width:280px;font-size:12px;color:var(--text2);margin-top:-6px}
.home-activity h3{font-size:15px;font-weight:700;margin-bottom:10px}
/* calendar-day cross-filter chip above the Latest Activity table (2026-07-31) */
.home-act-chip{display:flex;align-items:center;gap:8px;margin:-2px 0 9px;flex-wrap:wrap}
.home-act-chip .hac-day{font-size:12px;font-weight:800;color:var(--accent2);background:rgba(124,108,240,.14);
  border:1px solid var(--accent2);border-radius:999px;padding:2px 10px}
.home-act-chip .hac-n{font-size:11.5px;color:var(--text2)}
.home-act-chip .hac-x{padding:2px 9px;font-size:11px;line-height:1.3}
.home-act td.hac-none{color:var(--text2);padding:18px 12px}
.gvn-head{display:flex;justify-content:space-between;align-items:center;gap:12px}
.gvn-head h3{margin-bottom:10px}
.home-act-wrap{max-height:340px;overflow:auto;border:1px solid var(--border);border-radius:10px}
.home-act{width:100%;border-collapse:collapse;font-size:13px}
.home-act th{position:sticky;top:0;background:var(--card2);color:var(--text2);font-size:11.5px;text-transform:uppercase;letter-spacing:.5px;text-align:center;padding:9px 12px;z-index:2;white-space:nowrap}
.home-act th.r,.home-act td.r{text-align:center}
.home-act td{padding:9px 12px;border-top:1px solid var(--border);white-space:nowrap;text-align:center}
.home-act td.it{white-space:normal;min-width:220px;color:var(--text2);text-align:left}
.home .home-act td.it{text-align:center}
.home-act td.ord,.home-act td.money{color:var(--green);font-weight:600}
.home-act td.money.neg{color:var(--red)}
.home-act td.count{color:var(--green)}
.home-act td.count.neg{color:var(--red)}
.home-act tr:hover td{background:var(--card2)}
.st-matrix .st-grp-row td{font-weight:700;background:var(--card2);white-space:nowrap}
.st-matrix .st-cust-row td{font-weight:600;color:var(--text2);padding-left:26px;background:var(--card2)}
.home-act td.st-sub-label{padding-left:26px;color:var(--text2);font-size:12px;font-weight:400}
.home-act .st-sub-row-2 td.st-sub-label{padding-left:42px}
.st-toggle{display:inline-flex;width:14px;cursor:pointer;user-select:none;color:var(--text2)}
.st-matrix-wrap{max-height:none;overflow:visible}
.st-filters{display:flex;flex-direction:column;gap:12px}
.st-filter-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.st-filter-row .slicer-q{max-width:280px}
.st-filter-lbl{font-size:12.5px;color:var(--text2);font-weight:600;white-space:nowrap}
.home-act tfoot td{position:sticky;bottom:0;background:var(--card2);border-top:2px solid var(--border);font-weight:700;padding:11px 12px}

/* Homepage's own Latest Activity table (2026-07-31, per the user: denser, and must never need a
   sideways scroll). Scoped to .home so the shared .home-act component is untouched on Gross vs Net /
   Sales Tracker / Discontinued. table-layout:fixed + fixed widths on the four narrow columns lets
   Customer and Item wrap into whatever's left instead of pushing the table past the card, which is
   what the base white-space:nowrap + min-width:220px on .it was doing. */
/* 2026-07-31 (design-ux-ui, per the user: "empty space to the right and left of the table"): the
   earlier centred width:auto layout summed its fixed px columns to less than the card, leaving dead
   gutters on both sides. The nine columns are now proportional (% widths summing to 100) on a
   width:100% fixed layout, so the table always fills the card exactly at every breakpoint — the
   proportions still follow each column's widest real value, so nothing stretches unevenly. */
/* SCOPING (fixed 2026-07-31, same day, after these rules broke every report table): `.home` is
   NOT the Homepage — it is the SHARED page-shell class on all 16 report pages (`.home inv-page`,
   `.home disc-page`, `.home cs-page`, plain `.home` on Master Receiving Schedule / Forecast
   Planner / Inventory Management Tool / High Stock / Sales Tracker / Gross vs Net / Inbound
   Shipments...). Scoping to `.home .home-act` therefore hit EVERY report's table, not just the
   Homepage's, with three visible failures: table-layout:fixed + the nine nth-child percentages
   collapsed every column past the 9th to ~0 width (Inventory Report / IMT right-hand columns
   overlapping), white-space:normal + overflow-wrap:anywhere killed the base td nowrap so cells
   wrapped mid-token and rows ballooned to ~300px tall (Master Receiving Schedule), and the
   max-height capped unrelated scroll areas. The Homepage shell now carries its own `dash-page`
   modifier (js/home.js, matching the disc-page/cs-page/inv-page/los-page convention) and these
   rules key off THAT. Kept as a two-class selector so specificity is byte-for-byte what it was —
   the Homepage renders identically and the cascade order against .disc-page/.hs-table is unchanged. */
.dash-page .home-act-wrap{max-height:296px}
.dash-page .home-act{font-size:12px;table-layout:fixed;width:100%}
.dash-page .home-act th{padding:6px 7px;font-size:10.5px;letter-spacing:.3px;white-space:normal;line-height:1.2;vertical-align:bottom}
.dash-page .home-act td{padding:5px 7px;white-space:normal;overflow-wrap:anywhere}
.dash-page .home-act td.it{min-width:0;font-size:11px;line-height:1.3}
.dash-page .home-act tfoot td{padding:7px 7px}
.dash-page .home-act th:nth-child(1),.dash-page .home-act td:nth-child(1){width:8%}
.dash-page .home-act th:nth-child(2),.dash-page .home-act td:nth-child(2){width:13%}
.dash-page .home-act th:nth-child(3),.dash-page .home-act td:nth-child(3){width:18%}
.dash-page .home-act th:nth-child(4),.dash-page .home-act td:nth-child(4){width:12%}
.dash-page .home-act th:nth-child(5),.dash-page .home-act td:nth-child(5){width:5%}
.dash-page .home-act th:nth-child(6),.dash-page .home-act td:nth-child(6){width:12%}
.dash-page .home-act th:nth-child(7),.dash-page .home-act td:nth-child(7){width:13%}
.dash-page .home-act th:nth-child(8),.dash-page .home-act td:nth-child(8){width:8%}
.dash-page .home-act th:nth-child(9),.dash-page .home-act td:nth-child(9){width:11%}
/* the two warehouse columns read as metadata, not figures; "Fulfilled From" goes amber when it
   disagrees with Expected, matching the Incorrect Fulfillments report's warning tone */
.dash-page .home-act td.hac-st{color:var(--text2);font-weight:600}
.dash-page .home-act td.hac-wh{font-size:11px;color:var(--text2)}
.dash-page .home-act td.hac-wh.bad{color:var(--amber);font-weight:700}

/* ABT Recruitment Plan — 5 product-line colour tables (Kitchen Package/455/340/310/FR7) now stack
   directly on one page (2026-08-13, per the user, after states were combined into one nationwide
   total: "ensure the columns all align in distribution"). Each table is its own <table> with
   auto content-based column widths, so stacked one after another their Colour/FY/FY/Total columns
   didn't line up — same class of bug the Homepage's dash-page rules below already fix for its own
   table. table-layout:fixed + matching nth-child % widths (scoped to arp-page so it doesn't touch
   any other report's .home-act) makes every one of the 5 tables use identical column widths.
   Also drops the shared .home-act-wrap's max-height:340px scroll cap on this page: these tables
   top out around 9 colour rows (nowhere near the hundreds of rows that cap exists for elsewhere),
   but 2 of the 5 were just tall enough to trip it — the resulting scrollbar shrank THEIR content
   width by its own thickness while the other 3 stayed full width, so the % columns lined up
   internally per table but the tables themselves were a few px narrower, throwing off alignment
   again. No scrolling is needed at this row count, so removing the cap fixes both at once. */
.arp-page .home-act-wrap{max-height:none;overflow:visible}
.arp-page .home-act{table-layout:fixed}
.arp-page .home-act th:nth-child(1),.arp-page .home-act td:nth-child(1){width:40%}
.arp-page .home-act th:nth-child(2),.arp-page .home-act td:nth-child(2){width:20%}
.arp-page .home-act th:nth-child(3),.arp-page .home-act td:nth-child(3){width:20%}
.arp-page .home-act th:nth-child(4),.arp-page .home-act td:nth-child(4){width:20%}

/* Discontinued Inventory Sales — compress the page to fit one viewport without
   outer-page scroll across desktop sizes (2026-07-16, per the user: "compressed
   into one zoom"). Scoped to .disc-page so the shared home-kpi/home-act
   components stay exactly as-is on the Homepage, Gross vs Net and Sales Tracker.
   Two moves: keep the 6 KPI cards on ONE row much longer (they fit the ~684px
   content column down to ~1000px, so the 6->3 wrap that doubled the KPI row's
   height no longer fires at 1024px), and let the table's scroll area flex to
   fill the leftover height rather than sitting at a fixed cap (see below). */
/* NOTE (fixed 2026-07-17): this was originally `min-height`, which doesn't actually bound
   anything — none of the ancestor chain (.main/#page/.home) has a fixed height, they're all
   min-height too, so a flex child's `flex:1` has no real budget to redistribute against and the
   table below just grew to fit all its content again (worse than the old 230px cap, and outer-page
   scroll came back). A real `height` here makes .home.disc-page a genuinely bounded flex column,
   so .home-act-wrap's flex:1 below actually gets squeezed into the leftover space instead of
   growing unbounded — verified live: no outer scroll AND no leftover dead space. */
.home.disc-page{gap:12px;height:calc(100vh - 153px)}
/* .topbar wraps to 2 lines (49px -> 99px) somewhere between 1100-1180px width (its own
   flex-wrap:wrap, page title + "Since... Refresh" controls no longer fit one row) — the fixed
   153px budget above assumes the 1-line height, so below that width it undershoots by exactly
   the wrap's extra ~50px, reintroducing outer-page scroll. Same breakpoint style as the KPI grid
   below; picked 1200px for a safety margin above the observed 1100-1180px wrap point. */
@media(max-width:1200px){.home.disc-page{height:calc(100vh - 203px)}}
.disc-page .home-kpis{grid-template-columns:repeat(6,minmax(0,1fr));gap:10px}
.disc-page .home-kpi{padding:11px 13px}
.disc-page .hk-val{font-size:21px}
.disc-page .hk-lbl{margin-top:3px}
@media(max-width:1000px){.disc-page .home-kpis{grid-template-columns:repeat(3,minmax(0,1fr))}}
/* Fill the remaining viewport height instead of a fixed 230px cap: the disc-page
   is min-sized to the viewport (100vh minus .main padding + topbar + margin ≈
   150px), the activity card grows to absorb the slack between the KPI row and
   the calc panel, and the table's own scroll area flexes to fill the card —
   still scrolling internally on short viewports / many SKUs, so no outer-page
   scroll (2026-07-17, per the user: "fit the page ... distributed down ...
   unused space at the bottom"). */
.disc-page .home-activity{flex:1;min-height:0;display:flex;flex-direction:column}
.disc-page .home-act-wrap{flex:1;min-height:120px;max-height:none}
/* All 12 columns fit the card width WITHOUT horizontal scroll (re-tightened 2026-07-17, per the
   user: "I should not have to slide across"): smaller font, tighter padding both axes, smaller
   Description min-width, and the JS side now renders money cells as whole dollars (discMoney) —
   cents were costing ~4 characters in each of the three money columns. */
.disc-page .home-act{font-size:12px}
.disc-page .home-act th{padding:7px 7px;font-size:10.5px;letter-spacing:.3px;white-space:normal;line-height:1.2;vertical-align:bottom}
.disc-page .home-act td{padding:6px 7px}
.disc-page .home-act td.it{min-width:120px;max-width:240px;font-size:11.5px;line-height:1.35}
.disc-page .home-act tfoot td{padding:8px 7px}
/* rows drive the KPI cards (2026-07-17): pointer + selected highlight */
.disc-page .home-act tbody tr{cursor:pointer}
.home-act tr.row-sel td{background:rgba(124,108,240,.14)}
.home-act tr.row-sel td:first-child{box-shadow:inset 3px 0 0 var(--accent2);color:var(--accent2)}
.disc-page .vis-note{padding:4px 0}
/* Returns Report cross-filtering (2026-08-11): only SOME home-act tables on a page are clickable
   (tables 1-4, not table 5's drill-through list), so pointer/hover is a per-row class here rather
   than the page-wide ".disc-page .home-act tbody tr" rule above. */
.home-act tr.row-click{cursor:pointer}

.calc-panel{padding:0;overflow:hidden}
.calc-panel summary{cursor:pointer;list-style:none;padding:14px 18px;font-size:13.5px;font-weight:700;color:var(--text2);display:flex;align-items:center;gap:8px;user-select:none}
.calc-panel summary::-webkit-details-marker{display:none}
.calc-panel summary::before{content:'▸';font-size:11px;color:var(--text2);transition:transform .15s}
.calc-panel[open] summary::before{transform:rotate(90deg)}
.calc-panel summary:hover{color:var(--text)}
.calc-body{padding:0 18px 16px;display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px}
.calc-item{background:var(--card2);border:1px solid var(--border);border-radius:10px;padding:12px 14px}
.calc-item-head{display:flex;justify-content:space-between;align-items:baseline;gap:8px;margin-bottom:6px}
.calc-item-name{font-size:12.5px;font-weight:700}
.calc-item-val{font-size:12.5px;font-weight:700;color:var(--accent2)}
.calc-item-rule{font-size:12px;color:var(--text2);margin-bottom:8px;line-height:1.4}
.calc-item-row{font-size:11.5px;color:var(--text2);margin-top:3px;line-height:1.4}
.calc-item-row b{color:var(--text)}
@media(max-width:860px){.sidebar{display:none}.main{margin-left:56px}}

/* Inventory Report */
.inv-filters{display:flex;flex-direction:column;gap:12px}
.inv-filter-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.inv-search{max-width:260px}
.inv-filter-row .slicer-dd{width:auto;min-width:150px}
.inv-table-card{padding-bottom:12px}
.inv-table-wrap{max-height:300px;overflow:auto;border:1px solid var(--border);border-radius:10px}
.inv-table{font-size:11.5px}
.inv-table th{padding:5px 7px;font-size:10px;letter-spacing:.3px;white-space:normal;line-height:1.2;vertical-align:bottom;text-align:center;max-width:82px}
.inv-table th.inv-key{text-align:left;max-width:none}
.inv-table td{padding:4px 7px}
.inv-table tfoot td{padding:6px 7px}
.inv-table .tag{font-size:10px;padding:1px 6px}
.inv-table th.sortable{cursor:pointer;user-select:none}
.inv-table th.sortable:hover{color:var(--text)}
.inv-table th.sorted{color:var(--accent2)}
.inv-table .inv-key{position:sticky;left:0;background:var(--card2);z-index:2;text-align:left;font-weight:600;width:150px;max-width:165px;overflow:hidden;text-overflow:ellipsis}
.inv-table td.inv-key{background:var(--card);font-weight:600}
.inv-table tr:hover td.inv-key{background:var(--card2)}
.inv-table tfoot td.inv-key{background:var(--card2)}
/* Canada/USA flag cue — v6 (2026-07-17, third pass same day). ROOT CAUSE of v4/v5 failing: Chrome
   on WINDOWS does not render flag emoji at all — 🇨🇦/🇺🇸 fall back to the plain regional-indicator
   letters "CA"/"US" (Segoe UI Emoji ships no country flags), which is exactly what the user's
   screenshot showed ("none of the flag requirements showed up"). So the flag is now a tiny inline
   SVG data-URI (nothing external, works from file://), drawn as its own block ABOVE the header
   label per the user's v5 placement ask. Same asset reused by the .flag spans in the region-toggle
   buttons (js/inventory.js + js/high-stock.js), which had the same emoji problem. Data-row cells
   keep the quiet single-color inset edge so each group still reads down the rows. Shared selector —
   covers both the Inventory Report and the High Stock Inventory Report.
   v7 (2026-08-14, per the user: "flags... not aligned"): the flag used to be an in-flow block
   before the label text, with the whole th bottom-aligned (.inv-table th vertical-align:bottom) —
   so a 1-line label ("STG CAL") pushed its flag 12px lower than a 2-line label ("Best Month USA"),
   since the flag+text block as a unit slides down to hug the row's bottom edge. Fixed by taking the
   flag out of flow (position:absolute, pinned to a fixed offset from the th's own top) so every
   flag sits at the same height regardless of label length; padding-top on the th reserves the space
   so the label text still starts right after it.
   v8 (2026-08-14, per the user: Inventory Analysis header column staying put while scrolling):
   this rule used to also set position:relative, which overrides the position:sticky;top:0 every
   other .home-act th gets — so these 9 flag-labeled headers (Canada Available...Best Month USA)
   silently lost their sticky-to-top behavior and scrolled away with the body, while every other
   header (Item, SKU Class, Current Inv. Value, Total Qty Available, etc.) stayed pinned, producing
   a header row that visually split in two once you scrolled. position:sticky is itself a positioned
   value (establishes a containing block for absolutely-positioned descendants same as relative), so
   the ::before flag icon below still anchors correctly without needing position:relative here. */
.inv-table th.inv-can,.inv-table th.inv-usa{padding-top:22px}
.inv-table th.inv-can::before,.inv-table th.inv-usa::before{content:"";position:absolute;top:5px;left:50%;transform:translateX(-50%);width:23px;height:12px;margin:0;border-radius:2px;background-size:100% 100%;box-shadow:0 0 0 1px rgba(128,128,128,.4)}
.inv-table th.inv-can::before,.flag-can{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 12'%3E%3Crect width='24' height='12' fill='%23fff'/%3E%3Crect width='6' height='12' fill='%23d52b1e'/%3E%3Crect x='18' width='6' height='12' fill='%23d52b1e'/%3E%3Cpath fill='%23d52b1e' d='M12 1.6l.8 1.7 1.5-.5-.4 1.7 1.7-.4-.9 1.7 1.5.6-3.3 1.9.3 1.7-1.2-.6-1.2.6.3-1.7-3.3-1.9 1.5-.6-.9-1.7 1.7.4-.4-1.7 1.5.5z'/%3E%3C/svg%3E")}
.inv-table th.inv-usa::before,.flag-usa{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 12'%3E%3Crect width='24' height='12' fill='%23fff'/%3E%3Cpath fill='%23b22234' d='M0 0h24v.92H0zM0 1.85h24v.92H0zM0 3.69h24v.92H0zM0 5.54h24v.92H0zM0 7.38h24v.92H0zM0 9.23h24v.92H0zM0 11.08h24v.92H0z'/%3E%3Crect width='9.6' height='6.46' fill='%233c3b6e'/%3E%3Cg fill='%23fff'%3E%3Ccircle cx='1.9' cy='1.6' r='.4'/%3E%3Ccircle cx='4.8' cy='1.6' r='.4'/%3E%3Ccircle cx='7.7' cy='1.6' r='.4'/%3E%3Ccircle cx='3.35' cy='3.23' r='.4'/%3E%3Ccircle cx='6.25' cy='3.23' r='.4'/%3E%3Ccircle cx='1.9' cy='4.86' r='.4'/%3E%3Ccircle cx='4.8' cy='4.86' r='.4'/%3E%3Ccircle cx='7.7' cy='4.86' r='.4'/%3E%3C/g%3E%3C/svg%3E")}
.flag{display:inline-block;width:20px;height:11px;border-radius:2px;background-size:100% 100%;vertical-align:-1px;box-shadow:0 0 0 1px rgba(128,128,128,.4)}
/* two-axis sticky conflict fix (2026-07-17, visible in the user's screenshot: scrolled item-name
   cells painted OVER the header row): td.inv-key (sticky left, z2) ties with thead th (z2) and
   wins by DOM order once the table scrolls vertically. Header must outrank data cells, and the
   top-left corner cell (sticky both ways) must outrank the header. */
.inv-table thead th{z-index:3}
.inv-table thead th.inv-key{z-index:4}
/* two-row grouped header sticky fix (ABC Deep Dive / Gross Sales by Warehouse): the leaf column-name
   row (Unique/Customer/US/Canada/etc.) inherited the same top:0 as the grouped label row above it
   (Freight Paid By/E-Commerce %/etc.), so once the table scrolled vertically both rows pinned to the
   same spot and overlapped instead of stacking. 22px matches the grouped row's actual rendered height
   (single-line th at this font-size/padding) — it stays fixed since that row's labels never wrap. */
.inv-table thead tr:nth-child(2) th{top:22px}
.inv-table td.inv-can{box-shadow:inset 2px 0 0 rgba(var(--flag-can-rgb),.5)}
.inv-table td.inv-usa{box-shadow:inset 2px 0 0 rgba(var(--flag-usa-blue-rgb),.5)}
/* 2026-08-14 (per the user: "spacing between the columns is off"): every column in a country
   group was getting its OWN left-edge accent line (inv-can/inv-usa applies per-cell), so a
   6-column USA block drew 6 vertical lines — one hugging the left of each narrow column — instead
   of one line marking where the group starts. Numbers ended up visually closer to their own
   left line than to the next column's, reading as uneven column spacing. Suppress the line on
   every column except the first of a run so only the group boundary is marked. Shared by every
   page reusing .inv-table's grouping (Inventory Analysis, High Stock, ABC Deep Dive, etc.). */
.inv-table td.inv-can+td.inv-can,.inv-table td.inv-usa+td.inv-usa{box-shadow:none}
/* Incorrect Fulfillments detail table: Item is the THIRD column (Date, Sales Order #, Item...),
   not the first — reusing .inv-key's position:sticky;left:0 here made the Item column paint over
   the Date/Sales Order # columns once the wide 11-column table scrolled horizontally (same class
   of bug as the vertical sticky-conflict above, just on the other axis). Same bold/ellipsis look,
   no sticky. */
.inv-table th.if-item-col,.inv-table td.if-item-col{text-align:left;font-weight:600;width:150px;max-width:165px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.inv-table tbody tr{cursor:pointer}
.inv-table tr.inv-sel td{background:rgba(var(--accent-rgb),.12)}
.inv-table tr.inv-sel td.inv-key{background:rgba(var(--accent-rgb),.18);color:var(--accent2);box-shadow:inset 3px 0 0 var(--accent2)}
.inv-chip{display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border-radius:20px;background:rgba(var(--accent-rgb),.15);color:var(--accent2);font-size:12px;font-weight:600;white-space:nowrap}
.inv-chip button{background:none;border:0;color:inherit;cursor:pointer;font-size:14px;line-height:1;padding:0}
.inv-flag{color:var(--amber);font-weight:700;cursor:help}
.inv-heatmap-card h3,.inv-bar-card h3,.inv-summary-grid h3{font-size:15px;font-weight:700;margin-bottom:10px}
/* High Stock Inventory Report: reuses .inv-table's grouping/flag styling wholesale. Row-click
   drill-down (2026-07-17, per the user: "when I click on an item row, the graphs should also
   reflect it") narrows the two dashboard visuals (below the table since 2026-08-28) to just that
   item — same row-highlight convention as the Inventory Report/Discontinued Sales row-click.
   Scoped to just .inv-key through 2026-08-29 (the row also holds a 💬 Comments button that needed
   its own click uncontested) — RESTORED to the whole row 2026-08-29, per the user ("click on a
   sku row anywhere, it should filter"); .inv-table tbody tr's own cursor:pointer (above) already
   covers the whole row, so no extra rule is needed here — see hsRowClick, js/high-stock.js, for
   how clicks on the Reviewed checkbox/Comments button/editable Priority/Owner cells still bail
   out of selecting the row. */
.hs-table tbody tr:hover td{background:var(--card2)}
/* Every column fit in one frame with no horizontal scroll through 2026-07-17 (per the user); the
   5 columns added 2026-08-28 (FY26 Forecast/Last 30 Days/Priority/Owner/Comments) no longer fit,
   so .inv-table-wrap's own horizontal scrollbar (inherited from .inv-table-wrap{overflow:auto},
   css above) takes over — the page itself still never scrolls sideways. The two long-text
   Recommendation columns are still the width hogs — they get a hard width band and a smaller
   wrapped font; everything else tightens padding slightly below the .inv-table base. */
.hs-table{font-size:10.5px}
.hs-table td{padding:4px 5px}
.hs-table th{max-width:72px}
.hs-table td.it{min-width:150px;max-width:210px;font-size:10px;line-height:1.4;white-space:normal;color:var(--text2)}
/* Comments column (2026-08-28, per the user): a one-line ellipsized preview of the most recent
   note (title="" carries the full text for a hover tooltip) plus a button that opens the full
   dated history in a devModal — see hsOpenComments/hsSubmitComment, js/high-stock.js. */
.hs-comment-cell{display:flex;flex-direction:column;align-items:flex-start;gap:4px}
.hs-comment-preview{max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hs-comment-cell .btn{font-size:10px;padding:2px 7px}
.hs-comment-add{margin-top:10px;display:flex;flex-direction:column;gap:8px;flex-shrink:0}
.hs-comment-add textarea{width:100%;resize:vertical;font-family:inherit}
/* Deliberately NOT .fcp-hist-wrap (flex:1 + its own overflow:auto) — a comment history is meant to
   be read in full, so it sizes to its own content and the .modal itself scrolls as one piece
   (see .modal{overflow-y:auto} above) on the rare item with enough comments to exceed 84vh. */
.hs-comment-hist{margin:-2px 0 4px;flex-shrink:0}
.hs-comment-hist .fcp-hist-table td{white-space:normal}
/* Next Arrival columns (2026-08-28, per the user): the quantity sits beside the date, muted so
   the date itself (the sortable, primary value) reads first. */
.hs-arrival-qty{color:var(--text2);font-size:10px}
/* "Reviewed" checkbox column (2026-08-29, per the user), to the left of Item — narrow and centered
   like every other checkbox column in this app (.pln-pick-col). */
.hs-table .hs-review-col{width:28px;text-align:center;padding:4px 2px}
/* High Stock dashboard visuals — Gross Sales by Country + Sales Share vs. Inventory Share by
   Warehouse (2026-07-17, per the user, replacing the removed per-item Gross Sales CAN/USA
   columns). Two cards side by side, same card/mini-table visual language as the Inventory
   Report's summary tables — no new component invented. */
.hs-viz-row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:1100px){.hs-viz-row{grid-template-columns:1fr}}
.hs-viz-card{padding:16px 18px}
.hs-viz-card h3{font-size:13px;margin-bottom:10px;text-transform:uppercase;letter-spacing:.7px;color:var(--text2)}
.hs-viz-card .inv-mini-wrap{overflow:visible}
.hs-viz-card .inv-mini td.bar-num{width:auto;white-space:nowrap}
/* Sales Tracker fiscal matrix fits every month through October without clipping (2026-07-17, per
   the user: "months of July are not even fully visible") — up to 13 money columns + the label
   column; combined with the whole-dollar format in js/sales-tracker.js stBlockRows. Placed late
   in the file so these equal-specificity overrides win against the .home-act base rules. */
.st-matrix th{padding:6px 6px;font-size:10.5px;white-space:normal;line-height:1.2}
.st-matrix td{padding:4px 6px;font-size:11.5px}
.st-matrix tfoot td{padding:5px 6px}
.st-matrix .st-cust-row td{padding-left:26px}
.home-act td.st-sub-label{font-size:11px}
.st-matrix-wrap{overflow-x:auto}
.inv-heat-head{display:flex;align-items:baseline;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-bottom:8px}
.inv-heat-head h3{margin-bottom:0}
/* Heatmap basemap is DARK and THEME-INDEPENDENT (2026-07-17, per the user: "better contrast when
   viewing in light mode"). The yellow->red heat dots were near-invisible on the old light-mode
   basemap (light card fill); a fixed dark "space/ocean" basemap makes them pop identically in both
   themes — same reasoning as the theme-independent --heat-* ramp. The land/border/label tones are
   also fixed light-on-dark so nothing depends on the active theme. */
.inv-heat{width:100%;height:100%;display:block}
/* Google-Earth palette (2026-07-17, per the user: "add the blue for the ocean and show the land
   as green, similar to how Google Earth would show"). Still theme-INDEPENDENT fixed colors (same
   reasoning as the --heat-* ramp): deep atlantic-blue ocean, muted terrain green land — muted so
   the yellow->red heat ramp stays the loudest thing on the map. Labels get a soft dark halo
   (paint-order stroke) so they hold up over both land and ocean. */
.inv-heat-bg{fill:#0b3455}
.inv-heat .border-state{fill:#2e5c40;fill-opacity:1;stroke:rgba(215,240,220,.28);stroke-width:.5}
.inv-heat .border-country{stroke:rgba(230,245,235,.55);stroke-width:1.1;opacity:1;fill:none}
.inv-heat .heat-lbl-country{font-size:16px;font-weight:700;letter-spacing:3px;fill:rgba(255,255,255,.55);text-anchor:middle;pointer-events:none;paint-order:stroke;stroke:rgba(10,40,30,.45);stroke-width:2}
.inv-heat .heat-lbl-state{font-size:7.5px;font-weight:600;fill:rgba(255,255,255,.62);letter-spacing:.5px;text-anchor:middle;pointer-events:none;paint-order:stroke;stroke:rgba(10,40,30,.4);stroke-width:1.4}
/* city labels, revealed progressively on zoom (2026-07-17, per the user) */
.inv-heat .heat-city-dot{fill:#fff;stroke:rgba(10,40,30,.55);stroke-width:.4;pointer-events:none}
.inv-heat .heat-lbl-city{fill:#fff;font-weight:600;pointer-events:none;paint-order:stroke;stroke:rgba(10,40,30,.6);stroke-width:1.1}
.inv-heat-legend{display:flex;align-items:center;gap:6px;font-size:10.5px;color:var(--text2);white-space:nowrap}
.inv-heat-legend .bar{width:70px;height:8px;border-radius:5px;background:linear-gradient(90deg,var(--heat-1),var(--heat-2),var(--heat-3),var(--heat-4),var(--heat-5))}
/* heatmap pan/zoom (2026-07-17): viewBox-driven (see js/inventory.js invHeat*), so the viewport just
   clips — no native scroll. Dark bg matches the basemap so the letterboxed margins around the wide
   map blend in rather than showing empty card. grab/grabbing cursor signals drag-to-pan. */
.inv-heat-viewport{width:100%;overflow:hidden;border-radius:10px;background:#0b3455;cursor:grab;touch-action:none}
.inv-heat-viewport.dragging{cursor:grabbing}
.inv-heat-zoom{display:flex;align-items:center;gap:4px}
.inv-heat-zoom .btn{padding:4px 9px;font-size:12px;line-height:1}
.inv-heat-zoom-label{min-width:46px;justify-content:center;font-variant-numeric:tabular-nums}
/* Incorrect Fulfillments map (js/incorrect-fulfillments.js ifFulfillmentMap) — reuses the heatmap
   basemap/borders; static (no pan/zoom). Legend swatches mirror the on-map pin/building markers. */
.if-map-viewport{height:520px;cursor:default;margin-top:6px}
@media(max-width:1400px){.if-map-viewport{height:420px}}
.if-map-legend{display:flex;flex-wrap:wrap;gap:8px 18px;align-items:center;font-size:11.5px;color:var(--text2)}
.if-map-legend span{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.if-map-legend .if-lg-pin{width:11px;height:11px;border-radius:50% 50% 50% 0;transform:rotate(-45deg);display:inline-block}
.if-map-legend .if-lg-bldg{width:12px;height:12px;border-radius:2px;background:rgba(150,168,184,.9);display:inline-block}
.if-map-legend .if-lg-bldg.lit{background:#ffd24d;box-shadow:0 0 6px 2px rgba(255,210,77,.6)}
/* clicked/selected order row on Incorrect Fulfillments. NOT `outline` on the <tr> (that was the
   2026-07-18 visual bug the user screenshotted) — Chromium draws a table row's outline as a
   separate box around EACH <td> rather than one box around the whole row, so it appeared as a
   broken/doubled line cutting through the SKU Class columns. Box-shadow on the cells themselves
   (top+bottom on every td, left only on the first, right only on the last) draws one continuous
   rectangle instead. */
.inv-table tbody tr.if-row-sel td{background:color-mix(in srgb, var(--accent) 14%, transparent);box-shadow:inset 0 2px 0 0 var(--accent),inset 0 -2px 0 0 var(--accent)}
.inv-table tbody tr.if-row-sel td:first-child{box-shadow:inset 2px 2px 0 0 var(--accent),inset 0 -2px 0 0 var(--accent)}
.inv-table tbody tr.if-row-sel td:last-child{box-shadow:inset -2px 2px 0 0 var(--accent),inset 0 -2px 0 0 var(--accent)}
/* Sales by Fiscal Year (2026-07-18, per the user): grouped CAN/USA column headers with a flag drawn
   above each label (reuses the existing .flag/.flag-can/.flag-usa asset — no new art), tightened
   below the base .home-act sizing so all 7 columns fit one frame with no horizontal scroll. */
.if-fy-table th{padding:6px 8px;font-size:10.5px}
.if-fy-table td{padding:5px 8px;font-size:11.5px}
.if-fy-flag{display:block;margin:0 auto 4px}
/* Graph sizing (2026-07-17, design-ux-ui, per the user: make the report's two graphs "the same
   size" and easy to distribute through). The heatmap and the monthly bar chart now STACK as two
   equal, full-width cards (.inv-viz-row is a single-column grid), so they share the exact same left
   and right edges and read as one deliberately-sized system instead of a half-width map next to a
   full-width chart. Equal WIDTH — not equal height — is the achievable "same size": the bar chart's
   month/value labels are drawn in SVG viewBox units and go illegible if the chart is narrowed, so it
   has to keep full width; and a full-continent map (tall) vs a 12-month column strip (short/wide)
   have reciprocal aspect ratios, so matching width naturally leaves the map taller — that height
   difference is content-driven, not arbitrary. Bonus: the heatmap now gets full width natively,
   complementing its zoom control. The four summary mini-tables (HTML, legible at any width) flow
   full-width below on their own row via the same auto-fit pattern as .calc-body. Trade-off: this is
   a bit taller than the 2026-07-16 single-viewport pass — sizing consistency was the newer, explicit
   ask. Scoped to .inv-* so no other report changes. */
.inv-page{gap:12px}
.inv-filters,.inv-table-card,.inv-heatmap-card,.inv-bar-card,.inv-summary-grid .card{padding:14px}
/* Item table column widths (2026-08-14, per the user: "ensure all columns are equal in size and
   spacing") — table-layout:fixed + an explicit px colgroup (js/inventory.js invColgroup), same
   convention as Item Catalogue's .ic-table (~27 columns, also scoped so it doesn't disturb every
   other page reusing the shared .inv-table look). table-layout:fixed WITHOUT width:100% — the
   table's width is left auto so it sizes to the SUM of the colgroup's px columns rather than being
   squeezed to fit the card (this table has 21 columns at "both" region; forcing width:100% into a
   ~580px card, as a first attempt here did, crammed every column down to ~24px, unreadable). The
   wrap's existing overflow:auto (line ~746) scrolls it sideways, same "page scrolls vertically,
   table scrolls horizontally" treatment as Item Catalogue/ABC Deep Dive. The colgroup gives every
   column an identical px width except Item, which keeps the same 150px every other report's Item
   column uses (js/inventory.js leaves that <col> matching .inv-key's own width rather than
   duplicating the number) — max-width:none on th/td clears the shared .inv-table base rule's 82px
   cap, which would otherwise override the colgroup's wider, equal px widths. */
.inv-page .inv-table{table-layout:fixed}
.inv-page .inv-table th,.inv-page .inv-table td{max-width:none}
.inv-page .inv-table td.inv-key{white-space:nowrap}
/* Dashboard section REDESIGNED 2026-07-17 (user: "I will let you style this page... If you have
   to use more space to move some visuals down and the viewer has to scroll down, so be it...
   make this look extremely professional"). The cramped 3-panel side-by-side band is gone: the
   page now stacks three full-width rows — Sales Heatmap, the four summary tables (2x2, each card
   half-page wide so warehouse/customer names NEVER truncate), and the monthly chart. Every panel
   is content-sized; nothing shares a fixed band height anymore, so nothing squishes or scrolls
   internally. Vertical page scroll is the accepted trade — the user said so explicitly. */
.inv-dashboard{display:grid;grid-template-columns:1fr;gap:14px}
.inv-heatmap-card,.inv-bar-card{display:flex;flex-direction:column}
.inv-heatmap-card .inv-heat-viewport{height:560px}
@media(max-width:1400px){.inv-heatmap-card .inv-heat-viewport{height:430px}}
.inv-bar-card .inv-mbars{width:100%;height:auto}
/* four summary tables, 2x2, half-page-wide cards — generous type and row rhythm now that width
   isn't rationed; row counts still capped in JS (invCapRows "Other (N)" fold) so the cards stay
   visually in step and no panel ever needs an internal scrollbar (standing rule). Uppercase
   letter-spaced card titles echo the app's table-header treatment for a more composed look. */
.inv-summary-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.inv-summary-grid .card{display:flex;flex-direction:column;min-width:0;padding:16px 18px 12px}
.inv-summary-grid .card h3{font-size:12px;margin-bottom:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-transform:uppercase;letter-spacing:.8px;color:var(--text2)}
@media(max-width:1000px){.inv-summary-grid{grid-template-columns:1fr}}
.inv-mini-wrap{overflow:hidden}
.inv-mini{table-layout:fixed;width:100%}
.inv-summary-grid .inv-mini th,.inv-summary-grid .inv-mini td{padding:6px 8px;font-size:11.5px}
.inv-mini th:first-child,.inv-mini td:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:34%}
.inv-mini td.bar-c{padding-top:8px;padding-bottom:8px}
.inv-mini td.bar-c .bar-track{width:100%;height:14px}
.inv-mini .bar-fill{max-width:100%}
.inv-mini tr.inv-mini-other td{color:var(--text2);font-style:italic}
/* mini-table value column (2026-07-17, "numbers are squished" fix): the value lives in its own
   fixed-width right-aligned cell now instead of inside the bar track */
.inv-mini td.bar-num{width:72px;white-space:nowrap;font-weight:600;font-variant-numeric:tabular-nums}
/* mini-table rows double as cross-filter clicks (Power BI-style visuals sync, 2026-07-17) */
.inv-mini tr.inv-mini-click{cursor:pointer}
.inv-mini tr.inv-mini-click:hover td{background:var(--card2)}
.inv-mini tr.inv-mini-sel td{background:rgba(124,108,240,.16)}
.inv-mini tr.inv-mini-sel td:first-child{color:var(--accent2);font-weight:700}
/* data labels on the Actual Sales by Month columns — horizontal now that the chart is a
   full-width row with real space per month (2026-07-17 redesign) */
.inv-mbars .bar-lbl-h{fill:var(--text2);font-size:11px;text-anchor:middle;font-variant-numeric:tabular-nums}
.inv-mini th,.inv-mini td{vertical-align:middle}

/* Discontinued Inventory Sales manual date slicer */
.disc-date{width:auto;min-width:160px}

/* ================= Company Strategy (js/company-strategy.js) ================= */
.cs-page{display:flex;flex-direction:column;gap:18px}
/* CEO message card */
.cs-ceo{padding:20px 22px;border-left:3px solid var(--accent2);background:linear-gradient(120deg,rgba(124,108,240,.08),transparent 70%)}
.cs-ceo-badge{display:inline-block;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--accent2);margin-bottom:8px}
.cs-ceo p{font-size:15px;line-height:1.6;color:var(--text);max-width:none}
.cs-ceo b{color:var(--text)}
/* classification-logic explainer card */
.cs-logic{padding:18px 22px}
.cs-logic h3{font-size:15px;margin-bottom:6px}
.cs-logic h4.cs-logic-sub{font-size:13.5px;margin:16px 0 6px}
.cs-logic-intro{font-size:13px;line-height:1.55;color:var(--text2);margin-bottom:12px}
.cs-logic-intro b{color:var(--text)}
.cs-logic-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.cs-logic-card{border:1px solid var(--border);border-radius:10px;padding:12px 14px;background:var(--card2);font-size:12.5px;line-height:1.5;color:var(--text2)}
.cs-logic-card div{margin-top:4px}
.cs-logic-card b{color:var(--text)}
.cs-logic-h{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:700;color:var(--text);margin-bottom:6px!important}
.cs-a{border-left:3px solid var(--green)}
.cs-b{border-left:3px solid var(--amber)}
.cs-c{border-left:3px solid var(--red)}
.cs-foot-list{margin:0;padding-left:20px;font-size:12.5px;line-height:1.7;color:var(--text2)}
.cs-foot-list b{color:var(--text)}
@media(max-width:900px){.cs-logic-grid{grid-template-columns:1fr}}
/* strategy table — fixed layout so all 9 columns fit the frame (no horizontal scroll, per the
   user); the colgroup in company-strategy.js sets the per-column widths. Taller than the default
   300px inv-table-wrap so more SKUs show at once; the page itself scrolls, the table doesn't
   scroll across. */
.cs-page .inv-table-wrap{max-height:74vh;overflow-x:hidden;overflow-y:auto}
/* ABC Deep Dive: same "taller wrap, page scrolls instead" treatment as Company Strategy above —
   this page has no other cards below the table to fill the frame, so the default 300px wrap left a
   large empty gap under a barely-populated viewport. */
.abc-page .inv-table-wrap{max-height:74vh;overflow-y:auto}
/* High Stock Inventory: same taller-wrap treatment (2026-08-06, per the user) — the report now
   shows every in-scope SKU (not just overstocked ones), so the default 300px wrap left most rows
   scrolled out of view immediately. */
.hs-page .inv-table-wrap{max-height:74vh;overflow-y:auto}
/* Gross Sales by Warehouse (2026-09-15, per the user: "all squished... spread it down"): same
   taller-wrap treatment as the three reports above — the default 300px cap left this report's
   table cramped into a short frame regardless of row count. Also resets table-layout back to
   auto (same fix as .hgj-page below, same root cause): the shared `.inv-page .inv-table{
   table-layout:fixed}` rule was written for Inventory Report's modest, colgroup-driven column
   count, but this table can run to ~48 warehouse-month columns with no colgroup, so `fixed` +
   the inherited width:100% (.home-act) squeezed every column into an equal, illegibly narrow
   sliver instead of letting the table grow past the frame and scroll sideways.*/
.gsw-page .inv-table-wrap{max-height:74vh;overflow-y:auto}
.gsw-page .inv-table{table-layout:auto}
.cs-table{table-layout:fixed;width:100%}
.cs-table th,.cs-table td{overflow-wrap:anywhere;word-break:break-word}
.cs-table td.it{font-size:11.5px;line-height:1.45;max-width:none;white-space:normal}
.cs-table .cs-sku{font-weight:600;color:var(--text)}
.cs-table .cs-desc{font-size:10.5px;color:var(--text2);margin-top:2px}
.cs-table td.inv-usa,.cs-table td.inv-can{white-space:normal}
.cs-arrow{color:var(--text2);font-weight:700;margin:0 1px}
.cs-table tr.cs-flag td.inv-key{box-shadow:inset 3px 0 0 var(--amber)}
.cs-insight{color:var(--text);font-weight:500}
.cs-aligned{color:var(--green);font-size:11px;font-weight:600;white-space:nowrap}
/* sell-rate window slicer + live MOI formula */
.cs-slicer-row{align-items:center}
.cs-slicer-lbl{font-size:12px;font-weight:700;color:var(--text);margin-right:2px}
.cs-slicer-hint{font-size:11.5px;color:var(--text2)}
.cs-moi-formula{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;padding:10px 12px;border:1px solid var(--border);border-left:3px solid var(--accent2);border-radius:8px;background:var(--card2)}
.cs-formula-lbl{font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--accent2)}
.cs-moi-formula code{font-family:ui-monospace,"Cascadia Code",Consolas,monospace;font-size:12px;color:var(--text);line-height:1.5;word-break:break-word}
/* Item Catalogue (2026-08-13, per the user: "add everything that is in the Excel sheet"): every Dim
   Item column is now shown, ~27 columns wide — too many to fit the fixed 100%-width layout .cs-table
   normally uses, unlike Company Strategy's 9 columns. Switched to table-layout:fixed with an explicit
   per-column colgroup (item-catalogue.js) so every column (including the conditional USA/CAN ones) gets
   a deterministic px width instead of being content-sized. Table width is left auto so it sizes to the
   sum of the columns and scrolls sideways inside its frame, same "page scrolls vertically, table
   scrolls horizontally" treatment as ABC Deep Dive above.
   ROOT CAUSE of the first two attempts both rendering every column at an identical, much-too-wide
   220px: the new cells reused the existing `.it` class, and .home-act td.it (line ~584) sets
   min-width:220px — sized for a different report's long-description column, it silently overrides
   table-layout:fixed's own per-column width for EVERY cell sharing that class, no matter how the
   colgroup or table-layout is set. Fixed by giving these cells their own `.icv` class below instead of
   reusing `.it`, so that unrelated rule never touches them. */
.ic-page .inv-table-wrap{max-height:74vh;overflow-y:auto}
.cs-table.ic-table{table-layout:fixed}
.ic-table td.icv{font-size:11.5px;line-height:1.45;white-space:normal;color:var(--text2)}

/* Class USA/CAN editable dropdown — colored like the .tag badges it replaces (grn/amb/red), except
   .fcp-edited (manual override) always wins per that class's own convention. */
.ic-class-select{width:100%;background:var(--card2);border:1px solid var(--border);color:var(--text);
  padding:3px 4px;border-radius:6px;font-size:11px;font-weight:600;outline:none;font-family:inherit;cursor:pointer}
.ic-class-select.ic-cls-a{color:var(--green)}
.ic-class-select.ic-cls-b{color:var(--amber)}
.ic-class-select.ic-cls-c{color:var(--red)}
.ic-class-select.ic-cls-req{color:var(--text2);font-weight:500}

/* ---------- Master Receiving Schedule: Excel-style grid duplicate of PO_DATA ----------
   Full cell borders + row banding on top of the normal .inv-table look, so it reads like a
   spreadsheet rather than a report table. The frozen "Issue" column reuses .inv-key (sticky
   left, already layered correctly against the sticky header — see the z-index note above) but
   needs to be wider and wrap text instead of ellipsis-truncating like a normal key column. */
.mrs-table-wrap{max-height:85vh}
.mrs-table th,.mrs-table td{border:1px solid var(--border)}
.mrs-table th.inv-key,.mrs-table td.inv-key{width:260px;max-width:260px;white-space:normal;overflow:visible;text-overflow:clip;vertical-align:top}
.mrs-issue-cell{font-size:11px;line-height:1.45}
.mrs-clean{color:var(--text2)}
.mrs-table tbody tr:nth-child(even) td{background:var(--card2)}
.mrs-table tbody tr:hover td{background:color-mix(in srgb, var(--accent) 10%, var(--card2))}
.mrs-table tr.mrs-issue-row td{background:color-mix(in srgb, var(--red) 10%, transparent)!important}
.mrs-table tr.mrs-issue-row td.inv-key{color:var(--red);font-weight:600;box-shadow:inset 3px 0 0 var(--red)}
.mrs-table tr.mrs-issue-row:hover td{background:color-mix(in srgb, var(--red) 18%, transparent)!important}

/* a manually added line (see "+ Add Line") — accent tint until/unless it also has Issues, in
   which case mrs-issue-row's red takes over via !important above. */
.mrs-table tr.mrs-new-row td{background:color-mix(in srgb, var(--accent2) 8%, transparent)}
.mrs-table tr.mrs-new-row td.inv-key{box-shadow:inset 3px 0 0 var(--accent2)}
.mrs-new-row-del{display:none;color:var(--red);cursor:pointer;font-weight:700;margin-right:6px}
.mrs-new-row:hover .mrs-new-row-del{display:inline}

/* Forecast Planner: same Excel-style grid as .mrs-table, plus inline-editable month cells.
   .fcp-cell is a contenteditable <td> (same interaction as the Developer grid: click to edit,
   Enter to commit, Escape to cancel) — .fcp-edited marks a cell that currently holds a manual
   override instead of the computed baseline forecast. */
.fcp-table-wrap{max-height:85vh}
.fcp-table th,.fcp-table td{border:1px solid var(--border)}
.fcp-table th.inv-key,.fcp-table td.inv-key{width:170px;max-width:170px}
.fcp-table tbody tr:nth-child(even) td{background:var(--card2)}
.fcp-table tbody tr:hover td{background:color-mix(in srgb, var(--accent) 10%, var(--card2))}
.fcp-cell{cursor:text}
.fcp-cell:focus{outline:2px solid var(--accent);outline-offset:-2px;background:var(--card2)}
.fcp-edited{color:var(--red);font-weight:700;background:color-mix(in srgb, var(--red) 12%, transparent)!important}
.fcp-total{font-weight:700}
.fcp-table tr.fcp-forecast-row td{background:color-mix(in srgb, var(--amber) 16%, transparent)!important}
.fcp-table tr.fcp-forecast-row td.inv-key{box-shadow:inset 3px 0 0 var(--amber)}
.fcp-table tr.fcp-forecast-row:hover td{background:color-mix(in srgb, var(--amber) 26%, transparent)!important}
.fcp-hist-wrap{overflow:auto;flex:1;margin:-2px 0 4px}
.fcp-hist-table th,.fcp-hist-table td{padding:6px 9px;font-size:12px}
.fcp-vba-code{overflow:auto;flex:1;margin:6px 0 4px;background:var(--card2);border:1px solid var(--border);border-radius:8px;padding:12px;font-family:ui-monospace,Consolas,monospace;font-size:11.5px;line-height:1.5;white-space:pre}
.fcp-vba-steps{font-size:13px;color:var(--text2);line-height:1.6;margin:0 0 10px 18px}
/* .fcp-capped = a month scaled down to fit the stock left on a discontinued SKU. Italic amber
   rather than red so it never reads as a manual override (.fcp-edited), which stays red and wins. */
.fcp-capped{color:var(--amber);font-style:italic}
.fcp-avail-live{font-weight:700}
/* Per-family per-year subtotals, then the grand totals — both use the accent tint (not the amber
   the editable forecast rows own) and !important to beat the zebra/forecast-row backgrounds. */
.fcp-table tr.fcp-sub-row td{background:color-mix(in srgb, var(--accent) 14%, var(--card2))!important;font-weight:600;border-top:2px solid var(--border)}
.fcp-table tr.fcp-sub-row td.inv-key{box-shadow:inset 3px 0 0 var(--accent);font-size:11px;opacity:.9}
.fcp-table tr.fcp-grand-row td{background:color-mix(in srgb, var(--accent) 30%, var(--card2))!important;font-weight:800;border-top:2px solid var(--accent)}
.fcp-table tr.fcp-grand-row td.inv-key{box-shadow:inset 3px 0 0 var(--accent)}

/* Inventory Management Tool: one continuous table, SKUs one after another (riskiest first),
   grouped by family, each SKU's 4 warehouse groups stacked underneath it. Reworked 2026-07-27
   (2nd pass): the separate Fiscal-Year column was folded into the Metric label (a small FYxx
   chip — .imt-fytag) so "Gross Sales" no longer repeats beside a bare year and one column is
   saved; month columns are fixed-narrow + tight-padded so all 12 fit without a horizontal scroll.
   SKU (rowspanned across its whole block, sticky-left, clickable to load the transfer map) and
   Warehouse (rowspanned per group) are real HTML rowspan cells. Each SKU is its own <tbody>
   (.imt-sku-block) with a strong divider (.imt-sku-start) and a family band (.imt-fam-band) above
   each family. Row-type classes tint each metric: .imt-avail-row / .imt-end-row bookend a group
   (bold ending balance), .imt-sales-row current-year sales, .imt-hist-row muted prior years,
   .imt-fc-row forecast, .imt-po-row purchases. */
.imt-detail-wrap{max-height:82vh}
/* "Jump to SKU" dropdown/Prev-Next — filter-bar row + the inline bar repeated above the table
   itself when a single SKU is being viewed (added per the user's ask 2026-09-18). */
.imt-skunav-dd{min-width:220px}
.imt-skunav-pos{font-size:12px;color:var(--text2);white-space:nowrap}
.imt-skunav-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:10px 14px;margin-bottom:12px;
  background:color-mix(in srgb, var(--accent2) 8%, var(--card2));border:1px solid var(--border);border-radius:10px}
.imt-skunav-bar .imt-skunav-pos{color:var(--text);font-size:13px}
/* Per-SKU KPI cards (added per the user's ask 2026-09-22) — reuses .home-kpi's card look, but a few
   need more than one number, so they get their own grid row sized for that (rather than squeezing
   into the plain 6-across .home-kpis grid above them). */
.imt-sku-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}
.imt-kpi-wh-rows{display:flex;flex-direction:column;gap:6px;margin-top:8px}
.imt-kpi-wh-row{display:flex;align-items:center;gap:6px;font-size:12.5px}
.imt-kpi-wh-row .flag{flex:none}
.imt-kpi-wh-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.imt-kpi-wh-row .r{margin-left:auto;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.imt-kpi-wh-row.imt-kpi-hl .imt-kpi-wh-name,.imt-kpi-wh-row.imt-kpi-hl .r{color:var(--accent2)}
/* Excel-style grid (reworked 2026-09-23, per the user's ask): table-layout:auto so columns size to
   their content rather than splitting a fixed card width evenly — needed once a second FY's 12
   columns can join the first (imt-dual-fy) and once individual columns can be hidden (▤ Columns),
   both of which make a fixed-percentage colgroup meaningless. The wrapper (.imt-detail-wrap, via the
   shared .inv-table-wrap) already scrolls both axes, so a wide dual-FY grid scrolls horizontally
   rather than squeezing unreadably. Every cell — including SKU/Warehouse/Metric labels and numeric
   month/Total cells — is CENTER aligned per the user's ask (2026-09-23); only long text that
   genuinely needs to wrap (the Metric label, comments) stays left so it reads naturally. */
.imt-detail-table{font-size:11.5px;table-layout:auto;width:auto;max-width:none}
.imt-detail-table th,.imt-detail-table td{white-space:nowrap;padding:3px 6px;text-align:center;overflow:hidden;text-overflow:ellipsis}
.imt-detail-table thead th{font-size:9.5px;padding:5px 6px}
.imt-detail-table th.r,.imt-detail-table td.r{text-align:center;font-variant-numeric:tabular-nums;min-width:56px}
.imt-detail-table td.inv-key,.imt-detail-table th.inv-key{text-align:center;white-space:normal;overflow:visible;min-width:110px}
.imt-detail-table td.imt-metric-cell{text-align:left;white-space:normal;line-height:1.2;color:var(--text);overflow:visible;min-width:200px}
.imt-detail-table td.imt-po-cell{white-space:normal;overflow:visible;line-height:1.5;min-width:70px}
.imt-detail-table td[rowspan]{vertical-align:middle}
/* Two-row grouped header when both FY26 and FY27 are checked — a spanning band above the month
   abbreviations, same idea as the shared .inv-table CAN/USA grouped headers. */
.imt-detail-table th.imt-fy-group-head{background:color-mix(in srgb, var(--accent2) 14%, var(--card2));font-weight:800;font-size:11px;letter-spacing:.3px;border-bottom:1px solid var(--border)}
.imt-detail-table.imt-dual-fy td.r.imt-total,.imt-detail-table.imt-dual-fy th.r.imt-total{border-right:2px solid var(--border)}
/* SKU sticky cell: name + a little "map" affordance, clickable */
.imt-sku-cell{cursor:pointer;line-height:1.25}
.imt-sku-name{display:block;font-weight:600;white-space:normal;word-break:break-word}
.imt-sku-map-hint{display:block;font-size:9px;color:var(--text2);opacity:0;transition:opacity .12s}
.imt-sku-cell:hover .imt-sku-map-hint{opacity:1}
.imt-wh-cell{white-space:nowrap;font-size:10.5px}
.imt-wh-cell>span{cursor:pointer}
.imt-wh-cell>span:hover{color:var(--accent2)}
/* 💬 Comments button beside the warehouse name (added 2026-09-23, per the user's ask for per-SKU x
   warehouse comments) — a dated, append-only note log, opened via imtOpenComments(). Sits on its own
   line under the warehouse name so it doesn't crowd the click target that highlights the group. */
.imt-comment-btn{display:block;margin:4px auto 0;padding:3px 9px;border:1px solid var(--border);border-radius:9px;background:var(--card);color:var(--text2);font-size:13px;cursor:pointer;line-height:1.5}
.imt-comment-btn:hover{border-color:var(--accent2);color:var(--accent2)}
.imt-comment-btn.imt-has-comments{background:color-mix(in srgb, var(--accent2) 16%, var(--card));color:var(--accent2);border-color:var(--accent2);font-weight:700}
/* SKU Classification (USA/CAN, added 2026-09-24, per the user's ask) — sits under the SKU name in
   the sticky SKU cell's own generous empty space; reuses imtClsTag()'s badge styling (A green/B
   amber/C red/Unclassified grey) so it reads the same as the Stockout List's own classification
   column. */
.imt-sku-cls{display:flex;flex-direction:column;gap:3px;margin-top:6px}
.imt-sku-cls-item{display:flex;align-items:center;gap:4px;font-size:9.5px}
.imt-sku-cls-item .tag{font-size:9px;padding:0 5px}
/* Permanent per-warehouse tint (Yusen-ON light green, STG GA + M and M NY sky blue, STG CAL navy
   blue — STG CAL reverted 2026-09-24 back to navy per the user's ask, after a same-day tan/gold
   experiment didn't read right on the Available Inventory row) — every row always carries its
   warehouse's own color, not just on hover/select, so the 3 stacked groups within a SKU's block
   (Yusen-ON / East Coast combined / STG CAL — see "East Coast combined block" above) are
   identifiable at a glance without clicking anything. A LOW mix percentage onto var(--card) (not a
   solid fill) keeps this readable in both themes. Replaces the old plain row-zebra striping in this
   table (a per-warehouse tint already gives every row visual context, so an unrelated alternating
   stripe on top would just be noise). Clicking a Warehouse cell (.imt-wh-hl below) still layers a
   stronger, saturated version of the SAME color on top via !important — same color mapping in both
   places. */
/* Bumped from 10% to ~20% (2026-09-25, per the user's ask — the original 10% mix read as barely-
   there in light mode, where var(--card) starts near-white). */
.imt-detail-table tbody tr[data-wh="STG CAL"] td{background:color-mix(in srgb, #1e3a8a 20%, var(--card))}
.imt-detail-table tbody tr[data-wh="STG GA"] td,
.imt-detail-table tbody tr[data-wh="M and M NY"] td{background:color-mix(in srgb, #38bdf8 22%, var(--card))}
.imt-detail-table tbody tr[data-wh="Yusen-ON"] td{background:color-mix(in srgb, #4ade80 22%, var(--card))}
.imt-detail-table tr.imt-wh-hl[data-wh="STG CAL"] td{background:color-mix(in srgb, #1e3a8a 36%, var(--card))!important}
.imt-detail-table tr.imt-wh-hl[data-wh="STG GA"] td,
.imt-detail-table tr.imt-wh-hl[data-wh="M and M NY"] td{background:color-mix(in srgb, #38bdf8 36%, var(--card))!important}
.imt-detail-table tr.imt-wh-hl[data-wh="Yusen-ON"] td{background:color-mix(in srgb, #4ade80 36%, var(--card))!important}
/* SKU cell (rowspanned across the WHOLE block, sticky-left) always stays neutral/white — it isn't
   any one warehouse's row, but a plain `td` selector on the warehouse-tint rules above would
   otherwise paint it with whichever warehouse's row it happens to physically sit in (Yusen-ON,
   first in row order), since that rule's selector also matches it. Same fix needed for the SKU's
   OWN highlighted/selected states elsewhere (.imt-sku-sel only tints the name text, not this cell,
   so no conflict there). !important because the warehouse-tint rules above are otherwise a hair
   more specific once `tbody`/`[data-wh]` are counted. */
.imt-detail-table tbody tr td.imt-sku-cell{background:var(--card)!important}
.imt-detail-table td.imt-wh-cell-sel{font-weight:700}
.imt-detail-table tr[data-wh="STG CAL"] td.imt-wh-cell-sel{box-shadow:inset 3px 0 0 #1e3a8a;color:#1e3a8a}
.imt-detail-table tr[data-wh="STG GA"] td.imt-wh-cell-sel,
.imt-detail-table tr[data-wh="M and M NY"] td.imt-wh-cell-sel{box-shadow:inset 3px 0 0 #38bdf8;color:#38bdf8}
.imt-detail-table tr[data-wh="Yusen-ON"] td.imt-wh-cell-sel{box-shadow:inset 3px 0 0 #4ade80;color:#4ade80}
/* data-theme is always set explicitly on <html> in this app (js/app.js's toggleTheme(), default
   "dark" — see index.html) — never left to system preference. Navy as a plain text/box-shadow color
   reads fine in light mode but is too close to the dark theme's own near-black card background, so
   it gets a lighter blue there instead. */
:root[data-theme="dark"] .imt-detail-table tr[data-wh="STG CAL"] td.imt-wh-cell-sel{color:#7fa4f0}
.imt-detail-table tbody tr:hover td{background:color-mix(in srgb, var(--accent) 10%, var(--card2))}
/* Combined East Coast warehouse cell (imt-wh-cell-combo) — two stacked sub-blocks, one per
   warehouse, each with its own name/flag/click-target and 💬 Comments button (see the "East Coast
   combined block" note above imtEastCoastRowCells). */
/* Deliberately NOT display:flex here (fixed 2026-09-24) — a flex display on a <td> that also
   carries a rowspan breaks the table's row-height calculation in some browser engines (the whole
   grid visibly balloons/misaligns below it); plain block stacking with margin instead of a flex gap
   avoids the table+flex interaction entirely. */
.imt-wh-cell-combo{padding-top:6px;padding-bottom:6px}
.imt-wh-subcell{padding:2px 0;margin-top:10px}
.imt-wh-subcell:first-child{margin-top:0}
.imt-wh-subcell+.imt-wh-subcell{border-top:1px solid var(--border);padding-top:8px}
.imt-wh-subcell.imt-wh-cell-sel{box-shadow:inset 3px 0 0 #38bdf8;color:#38bdf8;font-weight:700}
/* Metric-row-type accents (added 2026-09-24, matching the user's reference Excel sheet screenshot):
   Forecast = red, Gross Sales = green, Purchases = gold — universal across every warehouse, winning
   over that warehouse's own background tint above (same specificity, later in the file) except on
   the current-month column (.imt-now, !important, defined earlier in the file — still wins) and the
   click-to-highlight state (.imt-wh-hl, !important above — still wins). Available Inventory keeps
   just the plain per-warehouse tint above (reads as a continuation of the warehouse's own header
   color, like the reference sheet); Month-End On-Hand drops the fill entirely and instead colors its
   row LABEL (not the numeric cells, so the existing negative-value red still applies there) with the
   warehouse's own accent — a blank, bold-colored final row, matching the reference sheet. */
.imt-detail-table tbody tr.imt-fc-row td{background:color-mix(in srgb, var(--red) 14%, var(--card))}
.imt-detail-table tbody tr.imt-sales-row td{background:color-mix(in srgb, var(--green) 14%, var(--card))}
.imt-detail-table tbody tr.imt-po-row td{background:color-mix(in srgb, var(--amber) 12%, var(--card))}
.imt-detail-table tbody tr.imt-end-row td{background:var(--card)}
.imt-detail-table tbody tr[data-wh="Yusen-ON"].imt-end-row td.imt-metric-cell{color:#16a34a}
.imt-detail-table tbody tr[data-wh="STG CAL"].imt-end-row td.imt-metric-cell{color:#1e3a8a}
:root[data-theme="dark"] .imt-detail-table tbody tr[data-wh="STG CAL"].imt-end-row td.imt-metric-cell{color:#7fa4f0}
/* Combined East Coast Month-End On-Hand row (imt-end-row-combo, see imtEastCoastRowCells) — no
   data-wh (it's a sum of both warehouses, not either alone), so it gets its own label color rule
   instead of piggybacking on the per-warehouse selectors above. */
.imt-detail-table tbody tr.imt-end-row-combo td.imt-metric-cell{color:#0284c7}
/* extra top/bottom padding around each warehouse group's first/last row (rather than a real margin,
   which table rows can't have) reads as a visual gap between the 4 stacked warehouse groups within
   one SKU's block, without splitting the block into separate tables/rowspans (the SKU/family
   grouping stays exactly as it was). */
.imt-detail-table tr.imt-wh-start td{border-top:1px solid var(--border);padding-top:12px}
/* strong divider + accent where each new SKU block starts */
.imt-detail-table tr.imt-sku-start td{border-top:3px solid var(--accent2)}
.imt-detail-table tr.imt-current-fy td.imt-metric-cell{box-shadow:inset 3px 0 0 var(--accent2)}
.imt-detail-table tr.imt-hist-row td{color:var(--text2)}
.imt-detail-table tr.imt-hist-row td.imt-metric-cell{color:var(--text2);font-style:italic}
.imt-detail-table tr.imt-sales-row td.imt-metric-cell,.imt-detail-table tr.imt-end-row td{font-weight:700}
.imt-detail-table tr.imt-avail-row td.imt-metric-cell,.imt-detail-table tr.imt-end-row td.imt-metric-cell{font-weight:700}
.imt-detail-table tr.imt-end-row td{border-bottom:1px solid var(--border);padding-bottom:12px}
/* Selected-SKU name accent (drives the outlook chart/transfer map below) — used to also tint the
   WHOLE block's background, but since the page moved to always-single-SKU view (2026-09-22) the
   viewed SKU and the "selected" SKU are the same thing on every render, which made that tint a
   permanent flat wash across every row — stomping on the per-warehouse background colors below
   (the very thing the user asked to be able to see at a glance). Kept as just a name-color accent. */
.imt-sku-block.imt-sku-sel .imt-sku-name{color:var(--accent2)}
/* FY chip inside the metric label */
.imt-fytag{display:inline-block;margin-left:5px;padding:0 5px;border-radius:8px;font-size:8.5px;font-weight:700;letter-spacing:.3px;background:var(--card2);color:var(--text2);border:1px solid var(--border);vertical-align:middle}
.imt-fytag-cur{background:color-mix(in srgb, var(--accent2) 20%, transparent);color:var(--accent2);border-color:transparent}
/* family band */
.imt-fam-band td.imt-fam-cell{text-align:left;padding:7px 10px;background:color-mix(in srgb, var(--accent) 7%, var(--card2));border-top:3px solid var(--accent);border-bottom:1px solid var(--border)}
.imt-fam-key{font-weight:800;font-size:12.5px;letter-spacing:.2px}
.imt-fam-count{margin-left:10px;font-size:10.5px;color:var(--text2)}
.imt-fam-risk{margin-left:10px;font-size:10.5px;font-weight:700;color:var(--red)}
.imt-total{font-weight:700}
.imt-unsched-cell{color:var(--text2);font-size:10.5px;white-space:normal;padding:5px 8px;text-align:left}
.imt-now{background:color-mix(in srgb, var(--accent) 10%, transparent)!important}
.imt-chip{margin:1px 3px 1px 0}
.imt-po-cell .imt-chip{margin:1px;padding:1px 4px;font-size:9.5px}
.imt-chip-editable{cursor:pointer}
.imt-chip-editable:hover{background:color-mix(in srgb, var(--accent2) 22%, transparent)}
/* Theoretical purchase order chip (added 2026-09-23) — dashed border so it's never mistaken for a
   real, already-placed PO; clicking opens the edit/remove/commit modal (imtOpenTheoModal). The small
   "+" control beside it (and beside every Purchases cell, even an empty one) adds a new one. */
.imt-chip-theo{cursor:pointer;border:1px dashed var(--accent2)!important;background:color-mix(in srgb, var(--accent2) 10%, transparent)!important;color:var(--accent2)!important;font-style:italic}
.imt-chip-theo:hover{background:color-mix(in srgb, var(--accent2) 22%, transparent)!important}
.imt-add-theo-btn{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;margin-left:2px;padding:0;border:1px dashed var(--border);border-radius:50%;background:transparent;color:var(--text2);font-size:11px;line-height:1;cursor:pointer;vertical-align:middle;opacity:.5;transition:opacity .12s,border-color .12s,color .12s}
.imt-detail-table td.imt-po-cell:hover .imt-add-theo-btn,.imt-add-theo-btn:hover{opacity:1;border-color:var(--accent2);color:var(--accent2)}
.imt-theo-hint{font-size:11.5px;color:var(--text2);margin:0 0 12px}

.imt-country-seg .flag{margin-right:4px}
/* "▤ Columns" show/hide picker button + badge, next to the SKU nav bar's Prev/Next */
.imt-cols-btn{margin-left:auto}
.imt-cols-badge{display:inline-block;margin-left:4px;padding:0 6px;border-radius:8px;background:color-mix(in srgb, var(--accent2) 26%, transparent);color:var(--accent2);font-size:10px;font-weight:800}
/* Column picker modal (imtOpenColumnPicker) */
.imt-colpick-year{margin-bottom:14px}
.imt-colpick-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(72px,1fr));gap:6px 10px;margin-top:6px}
.imt-colpick-item{display:flex;align-items:center;gap:6px;font-size:12.5px}
/* Comments modal (imtOpenComments) — dated, append-only log */
.imt-comment-list{max-height:260px;overflow-y:auto;margin:10px 0;display:flex;flex-direction:column;gap:8px}
.imt-comment-row{padding:8px 10px;border:1px solid var(--border);border-radius:8px;background:var(--card2)}
.imt-comment-date{font-size:10.5px;font-weight:700;color:var(--text2);margin-bottom:3px}
.imt-comment-text{font-size:12.5px;line-height:1.4;white-space:pre-wrap;word-break:break-word}
.imt-comment-input{width:100%;box-sizing:border-box;resize:vertical;font-family:inherit;margin-top:4px}

/* ---- Warehouse Transfer Lanes (below the table) — reworked 2026-09-24 from a draggable map into
   a plain side-by-side list of every ordered warehouse pair, per the user's ask. ---- */
.imt-map-card{display:flex;flex-direction:column;gap:10px}
.imt-map-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
.imt-map-head h3{font-size:15px;font-weight:700;margin:0}
.imt-map-subttl{font-size:11.5px;color:var(--text2)}
.imt-map-empty{padding:26px 18px;text-align:center;color:var(--text2);border:1px dashed var(--border);border-radius:10px;font-size:13px}
.imt-map-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:2px}
.imt-map-sel{font-size:12.5px;color:var(--text2)}
.imt-map-sel b{color:var(--text)}
.imt-map-actions{display:flex;gap:8px;flex-wrap:wrap}
/* one card per lane, placed side by side */
.imt-lane-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px}
.imt-lane-card{display:flex;flex-direction:column;gap:8px;padding:12px;border:1px solid var(--border);border-radius:10px;background:var(--card2)}
.imt-lane-card.imt-lane-tariff{border-color:var(--amber)}
.imt-lane-row{display:flex;align-items:center;gap:8px}
.imt-lane-side{flex:1;min-width:0;text-align:center}
.imt-lane-side.imt-lane-risk{color:var(--red)}
.imt-lane-wh{font-size:11px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.imt-lane-units{font-size:19px;font-weight:800;margin:2px 0}
.imt-lane-sub{font-size:10px;color:var(--text2)}
.imt-lane-side.imt-lane-risk .imt-lane-sub{color:var(--red)}
.imt-lane-arrow{flex:none;font-size:15px;color:var(--text2)}
.imt-lane-tariff-note{font-size:10.5px;color:var(--amber);text-align:center}
.imt-lane-btn{width:100%;font-size:11.5px;padding:7px 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Lane visibility checklist (added 2026-09-23, per the user's ask — "create a list to the side to
   check which lanes I can view") — sits beside the lane grid; unchecking a lane hides its card
   immediately (imtToggleLane). A per-browser view preference (localStorage), defaults to every lane
   shown (today's behavior). */
.imt-lane-layout{display:grid;grid-template-columns:1fr 190px;gap:14px;align-items:start}
.imt-lane-picker{position:sticky;top:8px;padding:12px;border:1px solid var(--border);border-radius:10px;background:var(--card2)}
.imt-lane-picker-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}
.imt-lane-picker-head h4{margin:0;font-size:12.5px;font-weight:700}
.imt-lane-showall{padding:2px 8px;font-size:10.5px}
.imt-lane-picker-list{display:flex;flex-direction:column;gap:6px;max-height:340px;overflow-y:auto}
.imt-lane-picker-item{display:flex;align-items:center;gap:6px;font-size:11px;white-space:nowrap}
@media (max-width:900px){.imt-lane-layout{grid-template-columns:1fr}.imt-lane-picker{position:static}}

/* ---- Transfer prompt (devModal) + unified History ---- */
.imt-tf-sku{font-weight:700;font-size:14px;margin:2px 0 10px}
.imt-tf-grid{display:flex;align-items:flex-end;gap:12px}
.imt-tf-lbl{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--text2);flex:1}
.imt-tf-arrow{font-size:20px;color:var(--accent2);padding-bottom:6px}
.imt-tf-units{margin-top:12px;max-width:220px}
.imt-tf-reason{margin-top:12px}
.imt-tf-opt{font-weight:400;color:var(--text2);font-size:10.5px}
.imt-move-reason-lbl{display:block;margin:12px 0 4px;font-size:11.5px;color:var(--text2)}
.imt-move-reason{width:100%}
.imt-tf-msg{margin:12px 0;font-size:12px;line-height:1.5}
.imt-tf-bal,.imt-tf-after{padding:6px 9px;border-radius:7px;background:var(--card2)}
.imt-tf-after{margin-top:6px;font-weight:600}
.imt-tf-hint{margin-top:6px;color:var(--text2)}
.imt-tf-err{margin-top:8px;padding:7px 10px;border-radius:7px;background:color-mix(in srgb,var(--red) 14%,transparent);color:var(--red);font-weight:600}
.imt-tf-warn{margin-top:8px;padding:7px 10px;border-radius:7px;background:color-mix(in srgb,var(--amber) 16%,transparent);color:var(--amber);font-weight:600}
.imt-tf-flag{color:var(--amber);font-weight:700}
.imt-hist-sub{font-size:13px;font-weight:700;margin:14px 0 6px}
.imt-undo-btn{padding:2px 9px;font-size:11px}
.imt-hist-type{display:inline-block;padding:1px 7px;border-radius:8px;font-size:10px;font-weight:700}
.imt-hist-tf{background:color-mix(in srgb,var(--accent2) 20%,transparent);color:var(--accent2)}
.imt-hist-mv{background:var(--card2);color:var(--text2)}

/* ---- Transfer List (devModal) ---- */
.imt-tl-sec-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px}
.imt-tl-sec-head .imt-hist-sub{margin:0}
.imt-tl-count{margin-left:8px;font-size:10.5px;font-weight:600;color:var(--text2);text-transform:uppercase;letter-spacing:.4px}
.imt-tl-copy{padding:4px 11px;font-size:11.5px}
.imt-tl-table td.imt-tl-reason{white-space:normal;text-align:left;min-width:160px;color:var(--text)}
.imt-tl-noreason{color:var(--text2);font-style:italic}
.imt-tl-empty{padding:14px 16px;color:var(--text2);border:1px dashed var(--border);border-radius:9px;font-size:12.5px}
.imt-tl-tariff{color:var(--amber);font-weight:600;font-size:11px;white-space:nowrap}

/* ---- Low & Out of Stock Report (js/low-out-of-stock.js) ----
   Reuses .inv-table / .card / .tag styling wholesale; only the coast-count strip, the two
   section headers, the "nothing here" empty state, and the inline comment input are new. */
.los-counts{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.los-count-card{flex:1;min-width:150px;display:flex;flex-direction:column;gap:4px;align-items:flex-start;padding:11px 14px;border:1px solid var(--border);border-radius:11px;background:var(--card);cursor:pointer;font-family:inherit;text-align:left;transition:border-color .12s,background .12s}
.los-count-card:hover{border-color:var(--accent)}
.los-count-card.on{border-color:var(--accent);background:rgba(124,108,240,.10)}
.los-count-lbl{font-size:12px;font-weight:700;color:var(--text2);text-transform:uppercase;letter-spacing:.6px}
.los-count-nums{font-size:13px;color:var(--text2)}
.los-count-out{color:var(--red);font-size:16px}
.los-count-low{color:var(--amber);font-size:16px}
.los-table-card h3{font-size:15px;font-weight:700;margin-bottom:4px;display:flex;align-items:center;gap:8px}
.los-h-count{color:var(--text2);font-weight:600;font-size:13px}
.los-dot{width:9px;height:9px;border-radius:50%;flex:none}
.los-dot-out{background:var(--red)}
.los-dot-low{background:var(--amber)}
.los-table-card .vis-note{margin:0 0 10px}
.los-table td{cursor:default}
.los-none{color:var(--text2)}
.los-sub{color:var(--text2);font-size:10.5px}
.los-empty{padding:16px;color:var(--text2);border:1px dashed var(--border);border-radius:9px;font-size:12.5px;display:flex;align-items:center;gap:8px}
.los-comment-col{min-width:200px}
.los-comment{width:100%;box-sizing:border-box;background:var(--card2);border:1px solid var(--border);color:var(--text);padding:5px 8px;border-radius:6px;font-size:11.5px;font-family:inherit;outline:none}
.los-comment:focus{border-color:var(--accent)}
.los-comment::placeholder{color:var(--text2)}

/* ================= Hengjin Analysis (js/hengjin-analysis.js) =================
   Reworked 2026-08-31 (twice the same day): first combined into one country-agnostic total,
   then TRANSPOSED into a year-over-year grid — one row per SKU × fiscal year, months going
   across — mirroring Forecast Planner's own SKU × Fiscal Year layout. Ideas:
     1. Tall (not wide) now: ~34 SKUs × ~5 fiscal years is a TALL table, not a wide one, so the
        wrapper keeps the same 74vh vertical-scroll treatment as Company Strategy / ABC Deep Dive
        but no longer needs genuine horizontal scrolling.
     2. .hgj-cur-row tints each SKU's current-fiscal-year row amber, the same visual language as
        Forecast Planner's own .fcp-forecast-row, so the "still in progress" row reads as distinct
        from the closed historical years above it. Forecast-projected month cells inside that row
        reuse Forecast Planner's own unscoped .fcp-capped (italic amber) — no new color needed.
     3. The "All Hengjin SKUs" aggregate rows at the top of the body reuse the same fiscal-year-row
        markup as an individual SKU, just with a stronger card2 ground and bold text, so the
        vendor-wide trend and the per-SKU drill-down share one visual grammar.
     4. The wrapper div also carries the shared .inv-page class (for the filter bar/KPI styling
        every Reports page reuses), which brings along `.inv-page .inv-table{table-layout:fixed}`
        — a rule meant for Inventory Report's small fixed column count with an explicit px
        colgroup. This table's own column count is fixed and modest (SKU + Fiscal Year + 12 months
        + Total + MOI) but still reset to table-layout:auto below (same specificity, later in the
        file so it wins) so columns size to their content rather than splitting width evenly. */
.hgj-page .inv-table-wrap{max-height:74vh}
.hgj-page .inv-table{table-layout:auto}
.hgj-table .inv-key{width:170px;max-width:190px;white-space:normal;overflow-wrap:anywhere}
.hgj-table .hgj-sku{font-weight:600;color:var(--text)}
.hgj-table .hgj-desc{font-size:10.5px;color:var(--text2);margin-top:2px;line-height:1.35}
.hgj-table tr.hgj-cur-row td{background:color-mix(in srgb, var(--amber) 12%, transparent)}
.hgj-table tr.hgj-cur-row td.inv-key{box-shadow:inset 3px 0 0 var(--amber)}
.hgj-table tr.hgj-cur-row:hover td{background:color-mix(in srgb, var(--amber) 20%, transparent)}
.hgj-table tr.hgj-agg-row td{background:var(--card2);font-weight:700}
.hgj-table tr.hgj-agg-row.hgj-cur-row td{background:color-mix(in srgb, var(--amber) 18%, var(--card2))}
.hgj-table tr.hgj-agg-end td{border-bottom:2px solid var(--border)}
.hgj-null{color:var(--text2)}
.hgj-vendor-tag{font-size:11.5px;color:var(--text2)}
.hgj-vendor-tag b{color:var(--text)}

/* ================= Purchase Planner (js/hengjin-purchase-plan.js) =================
   The one table on this page that's genuinely editable (not just displayed), so its edit columns
   (Vendor/Month/Qty/Destination) use real inputs/selects rather than .fcp-cell contenteditable
   spans — fewer columns than Master Receiving Schedule/Forecast Planner, so native controls read
   more clearly than a spreadsheet-cell feel would here. */
.hpp-table input[type=month],.hpp-table input[type=number],.hpp-table input[type=text],.hpp-table select{
  width:100%;background:var(--card);border:1px solid var(--border);color:var(--text);
  padding:5px 7px;border-radius:6px;font-size:12px;outline:none;font-family:inherit}
.hpp-table input[type=month]{min-width:118px}
.hpp-table input[type=number]{width:64px}
.hpp-table select{min-width:150px}
.hpp-table input:focus,.hpp-table select:focus{outline:2px solid var(--accent);outline-offset:-2px}
.hpp-table input:disabled,.hpp-table select:disabled{opacity:.4;cursor:not-allowed}
.hpp-sku-input,.hpp-vendor-input{min-width:130px}
.hpp-notfound{color:var(--amber)}
.hpp-remove-btn{background:none;border:0;color:var(--text2);cursor:pointer;font-size:15px;line-height:1;padding:2px 6px;flex:none}
.hpp-remove-btn:hover{color:var(--red)}
/* "Commit as PO" + ✕/↺ sit side by side without wrapping oddly at the table's default column width */
.hpp-action-cell{display:flex;align-items:center;justify-content:flex-end;gap:6px;white-space:nowrap}
/* row selection ("insert below" anchor, js/hengjin-purchase-plan.js hppRowClick) reuses .inv-sel
   (same highlight as Inbound Shipments' clickable month rows) — every non-input cell shows a
   pointer to invite the click; the inputs/select/buttons keep their own native cursor. */
.hpp-table tbody tr td{cursor:pointer}
.hpp-table tbody tr td:has(input),.hpp-table tbody tr td:has(select),.hpp-table tbody tr td:has(button){cursor:default}

/* ================= Messages (js/messages.js) =================
   A drafting surface: one tall column where the body textarea and the captured image are the two
   things that matter, and everything else is small. Reuses .card / .btn / .slicer-q / .tag — the
   only genuinely new elements are the monospace body box and the image preview frame.
   The image gets a checkered-free solid ground and a border because it is captured ON the theme
   background; without a frame a dark-theme PNG would bleed into the dark card behind it and the
   user couldn't tell where the picture ends. */
.msg-page{width:100%}
.msg-compose{display:flex;flex-direction:column;gap:13px}
.msg-field{display:flex;flex-direction:column;gap:5px}
.msg-field>label{font-size:10.5px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;color:var(--text2)}
.msg-src-row{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding-bottom:11px;border-bottom:1px solid var(--border)}
.msg-src-new{margin-left:auto}
/* The body is deliberately monospace: the drafted report is aligned columns of SKUs and numbers,
   and a proportional font makes those columns look ragged and untrustworthy. */
.msg-body{width:100%;box-sizing:border-box;background:var(--card2);border:1px solid var(--border);color:var(--text);
  padding:11px 13px;border-radius:9px;font-size:12px;line-height:1.55;outline:none;resize:vertical;
  font-family:'Cascadia Mono',Consolas,'Courier New',monospace;white-space:pre;overflow-wrap:normal;overflow-x:auto}
.msg-body:focus{border-color:var(--accent)}
.msg-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding-top:11px;border-top:1px solid var(--border)}
.msg-counter{font-size:11px;color:var(--text2);margin-left:auto}
.msg-status{font-size:11.5px;color:var(--green);min-height:15px}
.msg-dim{color:var(--text2);font-size:11.5px}
.msg-err{border-left:2px solid var(--red)}
.msg-img-card h3{font-size:15px;font-weight:700;margin-bottom:4px}
.msg-img-card .vis-note{margin:0 0 10px}
.msg-img-actions{display:flex;gap:9px;flex-wrap:wrap;margin-bottom:11px}
.msg-img-wrap{max-height:560px;overflow:auto;border:1px solid var(--border);border-radius:9px;background:var(--bg)}
.msg-img{display:block;width:100%;height:auto}
.msg-drafts h3{font-size:15px;font-weight:700;margin-bottom:4px}
.msg-drafts .vis-note{margin:0 0 10px}
.msg-drafts-wrap{max-height:260px}
.msg-drafts .inv-table th{text-align:left;max-width:none}
.msg-drafts .inv-table tbody tr{cursor:default}
.msg-d-title{max-width:280px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.msg-d-act{white-space:nowrap;text-align:right}

/* ================= Planner (js/planner.js) =================
   A worklist you pick the shape of. Two ideas do the work:
     1. The focus picker is the loudest control on the page — it changes WHICH dataset you're
        looking at, not just how it's filtered, so it gets its own row above the ordinary filters
        with a caption underneath naming the source report.
     2. Rows carry only two editable things (a tick and a note), so .pln-input strips the note box
        back to plain text that only reveals a border on hover/focus. The row reads as data until
        you reach for it. Handled rows fade rather than vanish, so setting one aside is visibly
        reversible instead of feeling like a delete. */
.pln-page{max-width:1500px}
.pln-filters{display:flex;flex-direction:column;gap:11px}
.pln-filter-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.pln-focus-sub{font-size:11.5px;color:var(--text2);margin-top:-4px}
.pln-select{flex:0 0 auto;min-width:160px}
.pln-sel-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding-top:9px;border-top:1px solid var(--border)}
.pln-sel-count{font-size:11.5px;color:var(--text2)}
.pln-table-card h3{font-size:15px;font-weight:700;margin-bottom:4px}
.pln-table-card .vis-note{margin:0 0 10px}
.pln-table-wrap{max-height:70vh;overflow-y:auto}
.pln-table tbody tr{cursor:default}
.pln-table th{text-align:left;max-width:none;vertical-align:bottom}
.pln-table td{vertical-align:top;padding:7px}
.pln-table .pln-pick-col{width:44px;text-align:center}
.pln-table .pln-sku-col{font-weight:600;min-width:130px}
.pln-table .r{text-align:right}
.pln-table .pln-short{font-weight:700;color:var(--red)}
.pln-table .pln-po-col{min-width:150px}
.pln-table .pln-donor-col{min-width:150px}
.pln-table .pln-ms-col{min-width:280px}
.pln-table .pln-notes-col{min-width:160px}
.pln-table .pln-act-col{width:48px;white-space:nowrap;text-align:right}
.pln-check{width:15px;height:15px;accent-color:var(--accent);cursor:pointer}
.pln-ms{font-size:11px;line-height:1.5;white-space:normal}
.pln-ms+.pln-ms{margin-top:3px}
.pln-sub{color:var(--text2);font-size:10.5px}
.pln-none{color:var(--text2);font-size:11px;font-style:italic}
/* borderless until you reach for it — see note 2 above */
.pln-input{width:100%;box-sizing:border-box;background:transparent;border:1px solid transparent;color:var(--text);
  padding:4px 6px;border-radius:6px;font-size:11.5px;font-family:inherit;outline:none}
.pln-input:hover{border-color:var(--border);background:var(--card2)}
.pln-input:focus{border-color:var(--accent);background:var(--card2)}
.pln-input::placeholder{color:var(--text2)}
.pln-mini{padding:3px 7px;font-size:11px;line-height:1.2}
.pln-r-handled td{opacity:.45}

/* Sandbox (js/sandbox.js) — amber accent border echoes the app's existing warning tone (see the
   Homepage's "Fulfilled From" mismatch styling) to keep "you're in a private replica" visible at
   a glance while a sandboxed Tools page renders its own normal UI beneath this strip. */
.sbx-bar{display:flex;align-items:center;flex-wrap:wrap;gap:10px;background:var(--card);
  border:1px solid var(--border);border-left:3px solid var(--amber);border-radius:10px;
  padding:10px 14px;margin-bottom:14px}
.sbx-bar-label{font-size:12.5px;color:var(--text2);flex:1 1 260px}
.sbx-bar-label b{color:var(--text)}
.sbx-bar select.slicer-dd{margin:0}
.sbx-picker{max-width:520px}
.sbx-picker h2{margin:0 0 6px}
.sbx-picker-row{display:flex;gap:10px;margin-top:12px}
.sbx-picker-row select.slicer-dd{flex:1}

/* ---------- roles (js/auth.js): view-only users + admin-only areas ---------- */
body.ua-viewonly .ua-edit{display:none!important}
body.ua-viewonly .ub-btn[data-sec="developer"],body.ua-viewonly .ub-btn[data-sec="savedTemplates"]{display:none!important}
body:not(.ua-admin) .ua-admin-only{display:none!important}
body.ua-viewonly [data-ua-locked^="ce"]{cursor:default}
.ua-role-badge{display:inline-block;margin-left:6px;padding:1px 7px;border-radius:999px;font-size:10.5px;font-weight:700;letter-spacing:.02em;background:var(--card2);color:var(--text2);border:1px solid var(--border);vertical-align:1px;text-transform:none}
/* ---------- Users page (js/users-admin.js) ---------- */
.usr-table td{vertical-align:middle}
.usr-actions{white-space:nowrap;text-align:right}
.usr-actions .btn{padding:5px 10px;font-size:12px}
.usr-role{display:inline-block;padding:2px 9px;border-radius:999px;font-size:11.5px;font-weight:700}
.usr-role-admin{background:rgba(var(--accent-rgb),.15);color:var(--accent)}
.usr-role-viewer{background:var(--card2);color:var(--text2)}
.usr-label{display:block;font-size:12px;font-weight:600;color:var(--text2);margin:12px 0 5px}
.usr-hint{font-weight:400}
.usr-select{width:100%;background:var(--card2);border:1px solid var(--border);color:var(--text);padding:9px 12px;border-radius:9px;font-size:13px;font-family:inherit}
.modal #usrErr{min-height:16px}
