:root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#171717;background:#f5f6f8;font-synthesis:none}*{box-sizing:border-box}body{margin:0}.shell{display:grid;grid-template-columns:230px minmax(0,1fr);min-height:100vh}aside{background:#121418;color:white;padding:24px 16px;display:flex;flex-direction:column;gap:8px}.brand{font-weight:800;font-size:18px;padding:6px 10px 20px}.nav{appearance:none;border:0;background:transparent;color:#aeb4bf;text-align:left;border-radius:10px;padding:11px 12px;font-size:15px;cursor:pointer}.nav:hover,.nav.active{background:#22262d;color:white}.side-note{margin-top:auto;color:#7e8795;font-size:12px;line-height:1.4;padding:10px}main{padding:32px;overflow:auto}header{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px}h1,h2,h3,p{margin-top:0}h1{margin-bottom:5px;font-size:28px}header p{color:#707782;margin-bottom:0}.secondary,.primary,button{font:inherit}.secondary{border:1px solid #d7dbe0;background:white;border-radius:9px;padding:9px 13px;cursor:pointer}.primary,button[type="submit"],#saveAuth{border:0;background:#181b20;color:#fff;border-radius:9px;padding:10px 14px;cursor:pointer}.banner{border-radius:10px;padding:12px 14px;margin-bottom:16px;background:#fff4ce;color:#614b00;border:1px solid #f4d96b}.hidden{display:none!important}.card{background:white;border:1px solid #e2e5e9;border-radius:14px;box-shadow:0 1px 2px rgba(0,0,0,.025)}.toolbar{padding:14px 16px;display:flex;justify-content:space-between;gap:12px;align-items:center}.muted{color:#7b828d;font-size:13px}.table-wrap{overflow:auto}table{border-collapse:collapse;width:100%;min-width:900px}th,td{text-align:left;padding:12px 14px;border-top:1px solid #eceef1;font-size:14px;vertical-align:middle}th{font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:#747b86;background:#fafbfc}.chip{display:inline-flex;align-items:center;border-radius:999px;padding:5px 9px;font-size:12px;font-weight:700}.green{background:#e9f8ee;color:#157238}.amber{background:#fff4d6;color:#8c5c00}.red{background:#fdeaea;color:#a82929}.gray{background:#eef0f3;color:#59616d}.row-actions{display:flex;gap:7px}.small-btn{border:1px solid #d9dde3;background:white;color:#262a30;border-radius:8px;padding:6px 9px;cursor:pointer}.field-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.field{display:flex;flex-direction:column;gap:6px}.field label{font-size:12px;font-weight:700;color:#59616d}.field input,.field select{border:1px solid #d6dbe1;border-radius:9px;padding:10px 11px;background:white;font:inherit}.settings-grid{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(300px,.8fr);gap:18px}.panel{padding:20px}.panel h3{margin-bottom:14px}.status-list{display:grid;gap:10px}.status-line{display:flex;justify-content:space-between;border-bottom:1px solid #eceef1;padding-bottom:9px}.dialog-card{border:0;padding:0;min-width:min(760px,92vw);max-width:760px}.dialog-card>div,.dialog-card>section{padding:0 24px}dialog{border:0;border-radius:15px;padding:0;box-shadow:0 30px 80px rgba(0,0,0,.25)}dialog::backdrop{background:rgba(0,0,0,.45)}.dialog-head{display:flex;justify-content:space-between;align-items:flex-start;padding-top:22px!important;padding-bottom:12px!important}.dialog-head h2{margin-bottom:4px}.dialog-head p{color:#727985}.icon-btn{background:transparent;color:#606774;padding:6px 8px}.detail-sections{padding:0 24px 24px}.comparison{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:20px}.subcard{border:1px solid #e0e4e8;border-radius:12px;padding:14px}.subcard h3{font-size:14px}.dimension-row{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;padding-top:18px}.auth-card{padding:24px;min-width:min(420px,90vw)}.auth-card input{width:100%;margin:4px 0 14px;border:1px solid #d6dbe1;border-radius:9px;padding:11px}.candidate-list{display:grid;gap:6px;margin-top:8px}.candidate{display:flex;justify-content:space-between;align-items:center;border:1px solid #e1e4e8;border-radius:9px;padding:8px 10px}.error-text{color:#aa2929;font-size:13px}.success-text{color:#157238;font-size:13px}@media(max-width:800px){.shell{grid-template-columns:1fr}aside{position:sticky;top:0;z-index:2;flex-direction:row;padding:10px;align-items:center}.brand{padding:8px;margin-right:auto}.side-note{display:none}.nav{padding:8px 10px}main{padding:18px}.settings-grid,.comparison{grid-template-columns:1fr}.field-grid{grid-template-columns:1fr 1fr}.dimension-row{grid-template-columns:1fr 1fr}}
.bulk-toolbar{flex-wrap:wrap}.bulk-actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}.bulk-note{padding:11px 16px;background:#fff8e5;border-top:1px solid #f0dfaa;border-bottom:1px solid #f0dfaa;color:#6d5200;font-size:13px}.secondary:disabled,.primary:disabled,.small-btn:disabled{opacity:.45;cursor:not-allowed}.banner.success{background:#e9f8ee;color:#157238;border-color:#bfe8cd}.banner.error{background:#fdeaea;color:#a82929;border-color:#f3c4c4}@media(max-width:800px){.bulk-actions{width:100%;justify-content:stretch}.bulk-actions button{flex:1 1 auto}}
.select-cell{width:68px;text-align:center}.row-select{width:18px;height:18px;cursor:pointer;accent-color:#181b20}.excluded-row{opacity:.48;background:#fafafa}.selection-note{padding:10px 16px;background:#f7f8fa;border-top:1px solid #eceef1;border-bottom:1px solid #eceef1;color:#59616d;font-size:13px}
.workflow-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin-bottom:16px}.workflow-card{padding:18px}.workflow-card h3{margin-bottom:7px}.step-label{display:inline-flex;border-radius:999px;background:#17191c;color:#fff;font-size:11px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:5px 9px;margin-bottom:10px}.metric-row{display:flex;gap:16px;flex-wrap:wrap;font-size:13px;margin:14px 0;color:#59616d}.metric-row strong{color:#17191c}.left-actions{justify-content:flex-start}.queue-card{overflow:hidden}.platform-links{display:flex;gap:5px;flex-wrap:wrap;margin-top:7px}.link-btn{border:0;background:#f0f2f5;color:#49515d;border-radius:6px;padding:4px 7px;font-size:11px;cursor:pointer}.link-btn:hover{background:#e4e8ed}.platform-bar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}.platform-anchor{text-decoration:none;display:inline-flex;align-items:center}.step-state{border-radius:10px;padding:10px 12px;margin-bottom:16px;font-size:13px}.state-ok{background:#e9f8ee;color:#157238;border:1px solid #bfe8cd}.state-blocked{background:#fff4d6;color:#7b5700;border:1px solid #f0d88a}.confirm-btn{border-color:#a9d5b7;background:#effaf3}.field input:disabled{background:#f1f3f5;color:#7b828d}.workflow-card.step-one{border-top:3px solid #343a40}.workflow-card.step-two{border-top:3px solid #157238}.workflow-card.step-three{border-top:3px solid #315a9b}@media(max-width:1000px){.workflow-grid{grid-template-columns:1fr}}

.danger-outline { border-color: #b42318 !important; color: #b42318 !important; }
.danger-outline:hover { background: #fff1f0 !important; }
.add-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;align-items:start}.manual-add-panel{grid-column:1/-1}.field textarea{border:1px solid #d6dbe1;border-radius:9px;padding:10px 11px;background:white;font:inherit;resize:vertical}.compact-table table{min-width:0}.compact-table th,.compact-table td{padding:9px 10px}.add-candidate{gap:12px}.selected-add-btn{background:#e9f8ee;border-color:#a9d5b7;color:#157238}@media(max-width:900px){.add-grid{grid-template-columns:1fr}.manual-add-panel{grid-column:auto}}

#pinError{min-height:18px;margin:-6px 0 12px}.auth-card button:disabled{opacity:.6;cursor:wait}

.add-sheet-card{padding:20px}.add-sheet-table table{min-width:1040px}.add-sheet-table th,.add-sheet-table td{padding:8px}.add-sheet-table input{width:100%;min-width:110px;border:1px solid #d6dbe1;border-radius:8px;padding:9px;background:#fff;font:inherit}.add-sheet-table td:first-child input{min-width:240px}.add-sheet-table td:nth-child(2) input{min-width:180px}.add-sheet-actions{display:flex;justify-content:space-between;gap:10px;align-items:center;padding-top:16px}.add-sheet-note{margin-top:12px;margin-bottom:0}@media(max-width:800px){.add-sheet-actions{align-items:stretch;flex-direction:column}.add-sheet-actions button{width:100%}}

.match-chip-btn{font:inherit;border:0;cursor:pointer}.match-chip-btn:hover{filter:brightness(.97);text-decoration:underline}.manual-match-source{display:flex;flex-direction:column;gap:3px;border:1px solid #e1e4e8;background:#fafbfc;border-radius:10px;padding:11px 12px;margin-bottom:12px}.candidate-heading{display:flex;align-items:center;justify-content:space-between;margin-top:16px;margin-bottom:6px}.candidate-main{min-width:0;display:flex;flex-direction:column;gap:4px}.candidate-meta{display:flex;gap:8px;align-items:center;flex-wrap:wrap;color:#646c77;font-size:12px}.candidate-score{padding:3px 7px;font-size:10px}.candidate{gap:14px}.candidate .small-btn{flex:0 0 auto}

.best-match-card{display:inline-flex;flex-direction:column;align-items:flex-start;gap:2px;max-width:360px;border:0;border-radius:12px;padding:8px 11px;text-align:left;color:#8c5c00}.best-match-top{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px}.best-match-name{font-size:11px;line-height:1.25;color:#765a18;max-width:330px;white-space:normal}.best-match-action{font-size:10px;font-weight:700;color:#8c5c00;opacity:.82}.best-match-card:hover{filter:brightness(.97);box-shadow:inset 0 0 0 1px rgba(140,92,0,.18)}

.product-thumb,.candidate-thumb,.match-thumb{display:block;object-fit:contain;background:#fff;border:1px solid #e1e4e8;border-radius:8px}.candidate-thumb{width:58px;height:58px;flex:0 0 58px}.match-thumb{width:46px;height:46px;flex:0 0 46px}.product-thumb-placeholder{background:linear-gradient(135deg,#f5f6f8,#eceff2)}.best-match-card{display:inline-grid;grid-template-columns:46px minmax(0,1fr);align-items:center;column-gap:9px}.best-match-copy{min-width:0;display:flex;flex-direction:column;gap:2px}.match-confirmed-wrap{display:inline-flex;align-items:center;gap:8px}.cache-stats{display:flex;gap:14px;flex-wrap:wrap;margin:10px 0 14px;font-size:13px;color:#59616d}.cache-stats strong{color:#17191c}.product-cache-card{margin-bottom:14px}.progress-track{background:#eceef1;border-radius:999px;height:8px;overflow:hidden;margin:8px 0}.progress-fill{background:#181b20;height:100%;border-radius:999px;transition:width .3s ease}.pipeline-area{border-top:1px solid #eceef1;margin-top:16px;padding-top:16px}.pipeline-area:first-of-type{border-top:0;margin-top:0;padding-top:0}.pipeline-area h4{font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:#59616d;margin-bottom:8px}.candidate{justify-content:flex-start}.candidate-main{flex:1 1 auto}@media(max-width:800px){.candidate-thumb{width:48px;height:48px;flex-basis:48px}.match-thumb{width:40px;height:40px;flex-basis:40px}.best-match-card{grid-template-columns:40px minmax(0,1fr)}}

.workload-control{overflow:hidden;margin-bottom:20px}.workload-control-head{display:flex;justify-content:space-between;align-items:flex-start;gap:20px;padding:20px 22px;border-bottom:1px solid #e8eaed}.workload-control-head h2{font-size:20px;margin:4px 0}.workload-control-head p{font-size:13px;color:#707782;margin:0}.workload-refreshed{text-align:right;color:#777f8a;font-size:11px}.workload-refreshed span,.workload-refreshed strong{display:block}.workload-refreshed strong{margin-top:4px;color:#2d333b;font-size:12px}.workload-overview{display:grid;grid-template-columns:210px 260px minmax(420px,1fr);min-height:270px}.workload-grand-total{padding:28px 24px;border-right:1px solid #eceef1;display:flex;flex-direction:column;justify-content:center}.workload-grand-total>span{color:#747b86;font-size:13px}.workload-grand-total>strong{font-size:58px;line-height:1;margin:12px 0 7px;color:#12202b}.workload-grand-total>small{color:#7b828d}.workload-signal{display:flex;align-items:center;gap:7px;margin-top:28px;font-size:12px;font-weight:700;color:#6d5200}.workload-signal i{width:8px;height:8px;border-radius:50%;background:#e7a21a;box-shadow:0 0 0 4px #fff4d6}.workload-mix{padding:24px;border-right:1px solid #eceef1;display:flex;flex-direction:column;align-items:center;justify-content:center}.workload-donut{width:156px;height:156px;border-radius:50%;display:grid;place-items:center;background:conic-gradient(#19b99a 0 var(--first-end),#f3ad23 var(--first-end) var(--second-end),#315a9b var(--second-end) 100%);position:relative}.workload-donut:after{content:"";position:absolute;inset:30px;border-radius:50%;background:#fff}.workload-donut>div{position:relative;z-index:1;text-align:center}.workload-donut strong,.workload-donut span{display:block}.workload-donut strong{font-size:31px}.workload-donut span{font-size:11px;color:#7b828d}.workload-legend{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-top:15px;font-size:11px;color:#59616d}.workload-legend span{display:flex;align-items:center;gap:5px}.workload-legend i{width:8px;height:8px;border-radius:50%}.ready-dot{background:#19b99a}.held-dot{background:#f3ad23}.b2b-dot{background:#315a9b}.department-grid{padding:18px;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-content:center;background:#fafbfc}.department-card{appearance:none;text-align:left;background:#fff;color:#171717;border:1px solid #e1e4e8;border-top:4px solid #19b99a;border-radius:12px;padding:16px;min-height:190px;box-shadow:0 1px 2px rgba(0,0,0,.03);transition:transform .15s ease,box-shadow .15s ease,border-color .15s ease}.department-card.held{border-top-color:#f3ad23}.department-card.b2b{border-top-color:#315a9b}.department-card:hover,.department-card.selected{transform:translateY(-2px);box-shadow:0 8px 22px rgba(27,37,49,.1)}.department-card.selected{outline:2px solid #1b2936;outline-offset:1px}.department-card-top{display:flex;align-items:center;justify-content:space-between;gap:8px}.department-name{font-weight:800;font-size:13px}.department-arrow{color:#89919b}.department-card>strong{display:block;font-size:38px;line-height:1;margin:24px 0 6px}.department-status{display:block;font-size:11px;color:#6f7782}.department-order-value{display:block;margin-top:4px;color:#315a9b;font-size:12px;font-weight:800}.department-track{display:block;height:5px;border-radius:99px;background:#edf0f2;margin:18px 0 8px;overflow:hidden}.department-track span{display:block;height:100%;border-radius:inherit;background:#19b99a}.department-card.held .department-track span{background:#f3ad23}.department-card.b2b .department-track span{background:#315a9b}.department-card small{color:#7a828d;font-size:10px;line-height:1.3}.workload-detail-label{display:flex;align-items:baseline;gap:8px;margin:0 2px 10px;color:#7b828d;font-size:12px;scroll-margin-top:18px}.workload-detail-label strong{color:#20252b;font-size:14px}.workload-stack{display:grid;gap:18px}.workload-section{overflow:hidden}.workload-section.ready{border-left:4px solid #19b99a}.workload-section.held{border-left:4px solid #f3ad23}.workload-section.b2b{border-left:4px solid #315a9b}.workload-section-head{display:flex;align-items:center;justify-content:space-between;padding:20px}.workload-section-head h2{margin:5px 0 0;font-size:20px}.eyebrow{text-transform:uppercase;letter-spacing:.05em;font-size:11px;font-weight:800;color:#707782}.workload-count{display:grid;place-items:center;min-width:58px;height:58px;border-radius:14px;background:#f2f4f7;font-size:25px;font-weight:800}.workload-table table{min-width:720px}.workload-table a{color:#1d4f91;text-decoration:none}.workload-table a:hover{text-decoration:underline}.workload-footer{padding:14px 20px;border-top:1px solid #eceef1;background:#fafbfc}.workload-error .platform-bar{margin:16px 0 0}@media(max-width:1180px){.workload-overview{grid-template-columns:190px 230px 1fr}.department-grid{grid-template-columns:1fr}.department-card{min-height:0}.department-card>strong{margin:10px 0 4px}.department-track{margin:10px 0 6px}}@media(max-width:850px){.workload-overview{grid-template-columns:1fr 1fr}.department-grid{grid-column:1/-1;grid-template-columns:repeat(2,1fr);border-top:1px solid #eceef1}.workload-grand-total{border-right:1px solid #eceef1}.workload-mix{border-right:0}}@media(max-width:650px){.workload-control-head{display:block}.workload-refreshed{text-align:left;margin-top:12px}.workload-overview{grid-template-columns:1fr}.workload-grand-total,.workload-mix{border-right:0;border-bottom:1px solid #eceef1}.department-grid{grid-column:auto;grid-template-columns:1fr}.workload-section-head{padding:16px}.workload-count{min-width:50px;height:50px}}

.workload-donut{background:conic-gradient(#19b99a 0 var(--first-end),#f3ad23 var(--first-end) var(--second-end),#315a9b var(--second-end) 100%)}.mix-1{background:#19b99a}.mix-2{background:#f3ad23}.mix-3{background:#315a9b}.workload-insights{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin:0 0 18px}.insight-card{padding:18px 20px}.insight-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:16px}.insight-head h3{font-size:16px;margin:4px 0 0}.insight-head>strong{font-size:26px}.insight-row{display:grid;grid-template-columns:minmax(90px,150px) minmax(100px,1fr) 34px;align-items:center;gap:10px;margin:9px 0;font-size:12px}.insight-row>span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#59616d}.insight-row>div{height:8px;background:#eef0f3;border-radius:99px;overflow:hidden}.insight-row i{display:block;height:100%;min-width:2px;border-radius:inherit}.status-bar{background:#315a9b}.age-bar{background:#19b99a}.insight-row strong{text-align:right}.age-summary{display:flex;gap:14px;color:#777f8a;font-size:11px}.age-summary span,.age-summary strong{display:block}.age-summary strong{font-size:18px;color:#20252b;margin-top:2px}.order-age{display:inline-flex;background:#eaf8f3;color:#15745f;border-radius:999px;padding:4px 8px;font-size:11px;font-weight:800}.order-age.aging{background:#fff4d6;color:#8c5c00}.order-age.overdue{background:#fdeaea;color:#a82929}@media(max-width:800px){.workload-insights{grid-template-columns:1fr}}@media(max-width:520px){.insight-row{grid-template-columns:90px 1fr 28px}.age-summary{display:none}}
/* v0.7.6: rotate/flip interaction removed site-wide. Both faces now render as static,
   non-interactive cards side by side, so there is nothing left to animate or click. */
.insight-pair{display:flex;gap:14px;min-width:0}.insight-pair .insight-card{flex:1;min-width:0;min-height:230px}.window-bar{background:#f3ad23}
@media(max-width:640px){.insight-pair{flex-direction:column}}
.workload-footer{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap}.api-limit{color:#737b86;font-size:11px;max-width:560px;line-height:1.4}
.activity-summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin-bottom:16px}.activity-summary .card{padding:18px;display:flex;flex-direction:column;gap:7px}.activity-summary span{color:#7b828d;font-size:13px}.activity-summary strong{font-size:28px}.activity-toolbar{display:flex;gap:14px;align-items:end;padding:16px;margin-bottom:16px;flex-wrap:wrap}.activity-toolbar label{display:flex;flex-direction:column;gap:6px;font-size:12px;font-weight:700}.activity-toolbar select{min-width:150px}.activity-toolbar p{margin:0 0 9px auto;color:#7b828d;font-size:12px}.activity-table td{vertical-align:top}.activity-table td:first-child{white-space:nowrap}.activity-table td:first-child small,.activity-run{display:block;color:#7b828d;font-size:11px;margin-top:4px}.activity-subsystem{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12px}.activity-details{margin-top:7px}.activity-details summary{cursor:pointer;color:#7b828d;font-size:12px}.activity-details pre{white-space:pre-wrap;word-break:break-word;background:#f6f7f8;border-radius:8px;padding:10px;max-width:520px;max-height:280px;overflow:auto;font-size:11px}.activity-error{background:rgba(180,35,24,.025)}
@media(max-width:800px){.activity-summary{grid-template-columns:repeat(2,minmax(0,1fr))}.activity-toolbar p{width:100%;margin:0}.activity-table{font-size:12px}}
.workload-readiness{display:grid;gap:6px;margin-top:18px;font-size:11px;color:#5e6670}.workload-readiness span{display:flex;align-items:center;gap:6px}.workload-readiness i{width:8px;height:8px;border-radius:50%;flex:0 0 auto}.workload-readiness strong{color:#20252b}.window-dot{background:#f3ad23}.workload-signal{margin-top:16px}.workload-signal i{background:#315a9b;box-shadow:0 0 0 4px #edf3fb}.workload-section.window{border-left:4px solid #f3ad23}.availability-cell{white-space:nowrap}.availability-chip{display:inline-flex;align-items:center;gap:4px;padding:5px 8px;border-radius:999px;font-size:11px;font-weight:700}.availability-chip.ready{color:#08745f;background:#dcf8f1}.availability-chip.window{color:#775400;background:#fff2c9}.ready-at-time{display:block;margin-top:4px;color:#7b828d;font-size:10px}
.workload-table-toolbar{display:grid;grid-template-columns:minmax(250px,1.5fr) repeat(5,minmax(130px,1fr)) auto auto;align-items:end;gap:10px;padding:14px 16px;border-top:1px solid #eceef1;background:#fafbfc}.workload-table-toolbar label{display:grid;gap:5px;min-width:0}.workload-table-toolbar label>span{font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#707782}.workload-table-toolbar input,.workload-table-toolbar select{width:100%;min-width:0;height:38px;padding:7px 10px;border:1px solid #d8dce1;border-radius:8px;background:#fff;color:#20252b;font:inherit}.workload-table-toolbar input:focus,.workload-table-toolbar select:focus{outline:2px solid rgba(25,185,154,.22);border-color:#19a98d}.workload-filter-clear{height:38px;padding:0 13px}.workload-filter-count{align-self:center;white-space:nowrap;color:#707782;font-size:11px}.workload-filter-count strong{color:#20252b}.workload-sort-button{appearance:none;display:inline-flex;align-items:center;gap:6px;padding:0;border:0;background:transparent;color:inherit;font:inherit;font-weight:inherit;text-transform:inherit;letter-spacing:inherit;cursor:pointer}.workload-sort-button span{color:#9aa1aa;font-size:12px}.workload-sort-button.active span{color:#08745f}@media(max-width:1450px){.workload-table-toolbar{grid-template-columns:minmax(250px,2fr) repeat(3,minmax(150px,1fr));}.workload-table-toolbar label:nth-of-type(5),.workload-table-toolbar label:nth-of-type(6),.workload-filter-clear,.workload-filter-count{grid-row:2}}@media(max-width:850px){.workload-table-toolbar{grid-template-columns:1fr 1fr}.workload-search{grid-column:1/-1}.workload-table-toolbar label:nth-of-type(5),.workload-table-toolbar label:nth-of-type(6),.workload-filter-clear,.workload-filter-count{grid-row:auto}}@media(max-width:520px){.workload-table-toolbar{grid-template-columns:1fr}.workload-search{grid-column:auto}}

/* Elite ShipHero All-in-One navigation and held-order workload */
.brand{line-height:1.15}.brand span{display:block;color:#8fd8c8;font-size:12px;letter-spacing:.08em;text-transform:uppercase;margin-top:5px}.sidebar-nav{display:grid;gap:20px}.nav-group{display:grid;gap:4px}.nav-group-label{padding:0 12px 5px;color:#697382;font-size:10px;font-weight:800;letter-spacing:.12em;text-transform:uppercase}.nav{width:100%}.sidebar-actions{display:grid;gap:4px;margin-top:auto}.side-note{margin-top:0}.department-grid{grid-template-columns:repeat(3,minmax(0,1fr))}.workload-signal{margin-top:12px;color:#315a9b}.workload-signal i{background:#315a9b;box-shadow:0 0 0 4px #edf3fb}.workload-signal.held-signal{color:#7b5700;margin-top:20px}.workload-signal.held-signal i{background:#e7a21a;box-shadow:0 0 0 4px #fff4d6}.workload-section.held .workload-table table{min-width:1080px}.picker-note{min-width:260px;max-width:520px;white-space:pre-wrap;line-height:1.45;color:#3f4650}
@media(max-width:1180px){.department-grid{grid-template-columns:1fr}}
@media(max-width:850px){.department-grid{grid-template-columns:repeat(3,minmax(180px,1fr));overflow-x:auto}}
@media(max-width:800px){aside{overflow-x:auto}.brand span{display:none}.sidebar-nav{display:flex;gap:8px;align-items:center}.nav-group{display:flex;gap:4px}.nav-group-label{display:none}.sidebar-actions{display:flex;gap:4px;margin:0 0 0 auto}.nav{white-space:nowrap}}
@media(max-width:650px){.department-grid{grid-template-columns:1fr;overflow:visible}}
.b2b-order-table table{min-width:980px}.b2b-order-table td:nth-child(4),.b2b-order-table td:nth-child(5){font-variant-numeric:tabular-nums}.b2b-order-table .money-cell{white-space:nowrap;font-variant-numeric:tabular-nums;font-weight:700}.b2b-type{background:#edf3fb;color:#315a9b}
.b2b-order-number{display:flex;align-items:center;gap:10px;white-space:nowrap}.b2b-pdf-button{appearance:none;border:1px solid #b9c9dd;border-radius:7px;background:#f4f7fb;color:#244e84;padding:5px 8px;font:inherit;font-size:10px;font-weight:800;cursor:pointer}.b2b-pdf-button:hover{background:#e8f0fa;border-color:#8da9c9}.b2b-pdf-button:focus-visible{outline:3px solid rgba(49,90,155,.25);outline-offset:2px}.b2b-pdf-button:disabled{cursor:wait;opacity:.65}

/* v0.7.0 B2B dashboard: sortable headers, created column, packer selector */
.sort-header {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.sort-header:hover { text-decoration: underline; }
.sort-header.active { font-weight: 700; }
.sort-arrow { font-size: 9px; opacity: .75; }
.b2b-created { display: flex; flex-direction: column; gap: 2px; white-space: nowrap; }
.b2b-created small { font-size: 11px; }
.b2b-slip-actions { display: flex; align-items: center; gap: 6px; margin-top: 6px; flex-wrap: wrap; }
.b2b-packer { font-size: 12px; padding: 3px 6px; max-width: 150px; }

/* v0.7.12: the B2B table's store-type filter reuses .workload-table-toolbar's
   look but has far fewer controls than the B2C toolbar, so it gets its own
   compact flex layout instead of inheriting the wide multi-column grid. */
.b2b-store-type-toolbar { display: flex; flex-wrap: wrap; align-items: end; gap: 10px; }
.b2b-store-type-toolbar label { display: grid; gap: 5px; min-width: 200px; }
.b2b-store-type-toolbar .workload-filter-count { align-self: center; }

/* Worker directory in Settings */
.worker-list { display: flex; flex-direction: column; gap: 4px; margin: 12px 0; }
/* v0.8.34: three independent per-tracker switches per worker row. Each is
   labelled - three unlabelled checkboxes in a row cannot be told apart. */
.worker-toggle { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #59616d; white-space: nowrap; cursor: pointer; }
.worker-toggle input[type="checkbox"] { margin: 0; }
/* v0.8.18: flex rather than a fixed 4-column grid, because this same row is
   now rendered with a different number of children in two places (the Workers
   tab: checkbox + name + wage + source chip + Remove; the Time Kiosk tab's
   read-only roster preview: name + wage chip). A fixed grid stretched the
   short variant across the wrong columns. */
.worker-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: 6px;
}
.worker-row:hover { background: rgba(0, 0, 0, .04); }
.worker-row input[type="checkbox"] { margin: 0; }
.worker-name { font-weight: 600; flex: 1; min-width: 0; }
/* v0.8.69: the preferred display name and the employment type. Both sit
   between the full name and the tracker switches, so a row reads
   "full name -> what we call them -> what they are -> where they appear". */
.worker-preferred input { width: 110px; border: 1px solid #d6dbe1; border-radius: 7px; padding: 5px 6px; font: inherit; font-size: 13px; }
.worker-type select { border: 1px solid #d6dbe1; border-radius: 7px; padding: 4px 5px; font: inherit; font-size: 12px; }
.worker-wage { display: inline-flex; align-items: center; gap: 2px; font-size: 12px; color: #59616d; white-space: nowrap; }
.worker-wage input { width: 74px; border: 1px solid #d6dbe1; border-radius: 7px; padding: 5px 6px; font: inherit; font-size: 13px; }
/* .worker-add-row is still used: v0.8.23 removed the "Add a worker" field
   (names come from the roster import only), but Clockhero's "Add project" row
   reuses the same class. */
.worker-add-row { display: flex; gap: 8px; }
.worker-add-row input { flex: 1; }
/* v0.7.25: one sub-block per "Import images" sweep (Drive/Cin7/ShipHero). */
.sweep-stage { margin: 14px 0; padding: 10px 12px; background: #fafbfc; border: 1px solid #eceef1; border-radius: 10px; }
.sweep-stage h5 { margin: 0 0 6px; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: #59616d; }
.sweep-stage p.muted { margin: 6px 0 0; }
.notice.warning { border-radius: 10px; padding: 10px 12px; margin: 10px 0; background: #fff4ce; color: #614b00; border: 1px solid #f4d96b; font-size: 13px; }

/* v0.8.0 Settings: clickable section tabs + the six-step pipeline panel. */
.settings-tabs { display: flex; gap: 6px; margin-bottom: 18px; border-bottom: 1px solid #e2e5e9; }
.settings-tab { appearance: none; border: 0; background: transparent; font: inherit; font-weight: 600; color: #7b828d; padding: 10px 16px; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.settings-tab:hover { color: #262a30; }
.settings-tab.active { color: #17191c; border-bottom-color: #181b20; }
/* The imports tab is one wide column: six stacked step cards read far better
   than the two-column layout the sheet-matching tab still uses. */
.settings-grid:has(.pipeline-steps) { grid-template-columns: minmax(0, 1fr); }
.pipeline-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.pipeline-head h3 { margin-bottom: 6px; }
.pipeline-controls { justify-content: flex-start; flex-wrap: wrap; }
.pipeline-steps { display: grid; gap: 12px; margin-top: 18px; }
.pipeline-step { border: 1px solid #e2e5e9; border-radius: 12px; padding: 14px 16px; background: #fff; }
.pipeline-step.is-current { border-color: #cbb37a; background: #fffdf6; box-shadow: 0 0 0 1px #f0e2bd inset; }
.pipeline-step.is-complete { background: #fbfcfb; }
.pipeline-step-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
.pipeline-step-head h4 { margin: 0; font-size: 15px; display: flex; align-items: center; gap: 10px; flex: 1 1 auto; }
.pipeline-step-number { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 999px; background: #eceef1; color: #59616d; font-size: 12px; font-weight: 700; flex: 0 0 22px; }
.pipeline-step.is-current .pipeline-step-number { background: #181b20; color: #fff; }
.pipeline-step.is-complete .pipeline-step-number { background: #e9f8ee; color: #157238; }
.pipeline-step p.muted { margin: 4px 0 0; }
.pipeline-step .progress-track { margin: 10px 0 6px; }

/* v0.8.18: Dashboard tab - labour by project. Table left, donut right, to
   match the Clockify summary report Jim works from today. Under 900px the
   two stack, because the table already has a 900px min-width of its own. */
.dash-controls { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.dash-split { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 24px; align-items: center; }
.dash-table { min-width: 420px; }
.dash-table td.num, .dash-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.dash-table tfoot td { font-weight: 700; border-top: 2px solid #dfe3e8; background: #fafbfc; }
.dash-title { display: flex; align-items: center; gap: 9px; font-weight: 600; }
.dash-dot { width: 9px; height: 9px; border-radius: 999px; flex: 0 0 9px; }
.th-sort {
  appearance: none; border: 0; background: transparent; padding: 0; cursor: pointer;
  font: inherit; font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
  color: #747b86; display: inline-flex; align-items: center; gap: 5px;
}
.th-sort:hover { color: #171717; }
.donut-wrap { display: flex; justify-content: center; align-items: center; padding: 8px; }
.donut { width: 240px; height: 240px; max-width: 100%; }
.donut circle { stroke-linecap: butt; }
.donut-total { font-size: 22px; font-weight: 700; fill: #171717; font-variant-numeric: tabular-nums; }
@media (max-width: 900px) {
  .dash-split { grid-template-columns: 1fr; }
}

/* v0.8.29: B2C Work Assignment and Processing Tracking. */
.b2c-form { display: flex; flex-wrap: wrap; align-items: end; gap: 12px; }
.b2c-form label { display: grid; gap: 5px; font-size: 12px; color: #59616d; font-weight: 600; }
.b2c-form input, .b2c-form select { font: inherit; padding: 7px 9px; border: 1px solid #d6dbe1; border-radius: 7px; min-width: 140px; }
/* v0.8.30: the spreadsheet-style stacked assignment table (replaced the
   v0.8.29 form + open-assignment cards). Reads like Jim's Sheet: a Stack
   header band, then one row per worker under it. */
.b2c-stack-table th.mid, .b2c-stack-table td.mid { text-align: center; }
.b2c-stack-table td, .b2c-stack-table th { white-space: nowrap; }
.b2c-stack-table .b2c-stack-head th { background: #eef1f5; color: #3b434f; font-size: 12px; letter-spacing: .04em; text-transform: uppercase; text-align: left; }
.b2c-stack-table tbody th[scope="row"] { text-align: left; font-weight: 600; }
.b2c-stack-table .cell-num { font: inherit; padding-left: 5px; padding-right: 5px; border: 1px solid #d6dbe1; border-radius: 5px; }
.b2c-stack-table select { font: inherit; padding-left: 5px; padding-right: 5px; border: 1px solid #d6dbe1; border-radius: 5px; max-width: 150px; }
.b2c-stack-table input[type="checkbox"] { width: 17px; height: 17px; }
/* v0.8.49: two BASE colour schemes splitting the grid into a Picking block and
   a Processing block, so the two stages read as distinct even on a table where
   nothing is running - cool blue-grey for picking, warm sand for processing.

   These are IDLE-STATE backgrounds only. They are declared BEFORE the v0.8.40
   active-stage rules and the tone-* result rules below, which carry identical
   specificity - so CSS source order alone guarantees the live green/amber
   on-target/late signal still paints over the top of them. Do not move this
   block below those, and do not raise its specificity: either would silence
   the signal the board is actually read for.

   Kept very pale for the same reason v0.8.40's colours are: everything else
   on the row has to stay legible sitting on top.

   v0.8.50: these four are deliberately written WITHOUT an element qualifier
   (`.col-pick`, not `td.col-pick`). A result cell now carries its stage base
   class AND its tone-* class at the same time, and `td.col-pick` would score
   (0,2,1) against `.tone-under`'s (0,2,0) - silently winning on specificity
   and erasing the green/red result colour. Kept at (0,2,0), the later-declared
   tone-* and sec-* rules win as intended. Do not add `td`/`th` here. */
.b2c-stack-table .col-pick { background: #eef3f8; }
.b2c-stack-table .col-process { background: #faf5ec; }
.b2c-stack-table .col-pick-head { background: #e3ebf3; }
.b2c-stack-table .col-process-head { background: #f3e9d9; }

/* v0.8.40: the highlight follows the STAGE, not the target - green while a
   worker is picking, amber while they are processing, plain once ticked
   complete. Kept pale so the checkbox, text and the result cells' own colours
   all stay legible on top of it. */
.b2c-stack-table tr.b2c-row-picking > *, .b2c-stack-table td.sec-picking { background: #cfeddb; }
.b2c-stack-table tr.b2c-row-processing > *, .b2c-stack-table td.sec-processing { background: #fbe2a8; }
/* The name column is sticky and paints its own background, so it needs the
   row's colour restated or it floats over the row as a white gap. */
.b2c-stack-table tr.b2c-row-picking .b2c-worker-col { background: #b8e4c9; }
.b2c-stack-table tr.b2c-row-processing .b2c-worker-col { background: #f7d488; }
/* A block whose own stage differs from the row's overall state keeps its own
   colour - a worker can be picking one stack while packing another. */
.b2c-stack-table tr > td.sec-picking { background: #cfeddb; }
.b2c-stack-table tr > td.sec-processing { background: #fbe2a8; }
/* Over target is a different fact from "which stage is running", so it marks
   the elapsed cell alone rather than colouring the whole block. */
.b2c-stack-table .tone-late { background: #f7e2b0; color: #7a5407; font-weight: 600; }
.b2c-stack-table .tone-under { background: #cdefd6; color: #16663a; font-weight: 600; }
.b2c-stack-table .tone-over { background: #f8ced0; color: #8a1c22; font-weight: 600; }
.b2c-stack-table th.group-pick, .b2c-stack-table th.group-process { background: #e4e9f0; }
.b2c-stack-table th.group-process, .b2c-stack-table td.group-process { border-left: 2px solid #c3cbd6; }
.b2c-stack-table .b2c-process-start { border-left: 2px solid #c3cbd6; }
/* v0.8.33: the grid now runs sideways - Stack 1..N per worker row - so the
   worker name column is pinned and each stack block gets a divider. */
.b2c-stack-table .b2c-worker-col { position: sticky; left: 0; z-index: 2; background: #fff; box-shadow: 1px 0 0 #d6dbe1; }
.b2c-stack-table thead .b2c-worker-col { z-index: 3; background: #eef1f5; }
.b2c-stack-table .b2c-stack-group { background: #e4e9f0; }
.b2c-stack-table .stack-edge { border-left: 3px solid #aab3c0; }
.b2c-summary-table .b2c-summary-total { background: #eef1f5; font-weight: 600; }
.b2c-summary-table .b2c-summary-total td[colspan] { font-weight: 400; color: #59616d; text-align: left; }
.b2c-boards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; }
.b2c-board h4 { margin: 0 0 8px; font-size: 14px; }
.b2c-board .b2c-rank-top { background: #eaf8ee; font-weight: 600; }

/* v0.8.20: date-range picker - presets left, two months right, matching Jim's
   screenshot: flush full-width preset rows with a solid blue active bar, two
   abbreviated month titles each flanked by a paging chevron, and a blue
   rounded-square day selection. */
.dash-range { position: relative; }
.dash-rangebtn {
  display: inline-flex; align-items: center; gap: 10px;
  border: 1px solid #d6dbe1; background: white; border-radius: 9px;
  padding: 9px 13px; font: inherit; cursor: pointer; min-width: 200px;
}
.dash-rangebtn:hover { border-color: #b9c0c9; }
.dash-rangebtn-label { font-weight: 600; }
.dash-rangebtn-caret { margin-left: auto; color: #7b828d; font-size: 11px; }
.cal-popover {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 30;
  display: flex; background: white; border: 1px solid #dfe3e8; border-radius: 10px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .16); overflow: hidden;
}
/* Flush rows, no gaps and no padding, so the active row's blue bar reaches
   both edges of the column exactly as in the screenshot. */
.cal-presets {
  display: flex; flex-direction: column;
  border-right: 1px solid #eceef1; background: white; min-width: 172px; padding: 6px 0;
}
.cal-preset {
  appearance: none; border: 0; background: transparent; text-align: left;
  font: inherit; font-size: 15px; padding: 11px 20px; border-radius: 0;
  cursor: pointer; color: #2b3038; width: 100%;
}
.cal-preset:hover { background: #f2f4f6; }
.cal-preset.is-active { background: #4a86c8; color: white; }
.cal-months { padding: 14px 18px 12px; }
.cal-month-pair { display: flex; gap: 34px; }
.cal-month-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; margin-bottom: 10px; }
.cal-month-label { font-weight: 700; font-size: 16px; text-align: center; flex: 1; }
.cal-navbtn {
  appearance: none; border: 0; background: transparent; font: inherit; font-size: 22px;
  line-height: 1; width: 26px; height: 26px; border-radius: 6px; cursor: pointer; color: #4a5058;
}
.cal-navbtn:hover { background: #f2f4f6; }
.cal-navspacer { display: inline-block; width: 26px; height: 26px; }
.cal-grid { width: auto; min-width: 0; border-collapse: collapse; }
.cal-grid th, .cal-grid td { border: 0; padding: 1px; text-align: center; background: none; }
.cal-grid th {
  font-size: 13px; color: #2b3038; text-transform: none; letter-spacing: 0;
  font-weight: 700; padding-bottom: 8px;
}
.cal-day {
  appearance: none; border: 0; background: transparent; font: inherit; font-size: 14px;
  width: 38px; height: 34px; border-radius: 6px; cursor: pointer; color: #2b3038;
  font-variant-numeric: tabular-nums;
}
.cal-day:hover { background: #eef0f3; }
.cal-day.is-outside { color: #c2c8d0; }
.cal-day.is-today { box-shadow: inset 0 0 0 1px #c2c8d0; }
.cal-day.is-selected { background: #dbe7f4; color: #1b3a5f; }
.cal-day.is-edge { background: #4a86c8; color: white; font-weight: 600; }
.cal-footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 12px; }
.dash-workers-note { margin: 10px 2px 0; }
@media (max-width: 760px) {
  .cal-popover { flex-direction: column; }
  .cal-presets { flex-direction: row; flex-wrap: wrap; border-right: 0; border-bottom: 1px solid #eceef1; }
  .cal-month-pair { flex-direction: column; gap: 14px; }
}

/* v0.8.20: second line inside the donut - the distinct worker count. */
.donut-sub { font-size: 12px; font-weight: 600; fill: #7b828d; font-variant-numeric: tabular-nums; }

/* v0.8.20: "Open Kiosk" is an <a> in the sidebar, not a button - match the nav
   buttons exactly so the two are indistinguishable to look at. */
.nav-link { display: block; text-decoration: none; }

/* v0.8.20: the "Currently clocked in" widget, moved off the Time Kiosk page onto
   Clockhero. Compact chips rather than the full-width status list it used to be:
   here it is a glance-at-it companion to the cost report, not the main event. */
.clockedin-card { margin-bottom: 16px; padding: 16px 20px; }
.clockedin-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.clockedin-head h3 { margin: 0; display: flex; align-items: center; gap: 8px; }
.clockedin-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.clockedin-chip {
  display: inline-flex; align-items: baseline; gap: 7px;
  background: #f2f4f6; border: 1px solid #e4e8ec; border-radius: 999px;
  padding: 6px 13px; font-size: 13px; color: #59616d;
}
.clockedin-chip strong { color: #171717; }

/* v0.8.21: the worker roster table on Clockhero - the merged kiosk. Replaces
   the deleted device page's tile grid; a supervisor tool, so it optimises for
   seeing everyone at once rather than for one big tap target. */
.roster-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.roster-head h3 { margin-bottom: 4px; }
.roster-head p { margin-bottom: 0; }
.roster-bulk { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 4px; }
.roster-table { min-width: 620px; }
.roster-table th.roster-select, .roster-table td.roster-select { width: 62px; text-align: center; }
.roster-table td.roster-select input { margin: 0; width: 17px; height: 17px; }
.roster-worker { font-weight: 600; }
.roster-table tr.is-clocked-in { background: #f6fbf7; }
.roster-project {
  border: 1px solid #d6dbe1; border-radius: 8px; padding: 7px 9px;
  background: white; font: inherit; font-size: 13px; max-width: 220px; width: 100%;
}
.roster-project:disabled { background: #f2f4f6; color: #9aa1ab; }
.roster-table td .small-btn:disabled { opacity: .45; cursor: default; }
/* Project management and the automatic-rules/export card sit side by side
   under the report, so the operational half of the tab stays above the fold. */
.dash-admin { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; margin-top: 16px; }
@media (max-width: 900px) { .dash-admin { grid-template-columns: 1fr; } }

/* v0.8.22: the roster/late banding on the worker table, and the three new tabs
   (Roster, History, Monthly Tracker). The band tints are deliberately faint -
   the ORDER carries the meaning, and a loud row colour on a table where a third
   of the rows are unrostered every day stops reading as a signal within a week. */
.roster-table tr.is-late { background: #fffaf0; }
.roster-table tr.is-late td.roster-worker { color: #8c5c00; }
.roster-table tr.is-unrostered td.roster-worker { color: #7b828d; font-weight: 500; }
.roster-shift { white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Date/month stepper: a field plus Previous / Today / Next. Not the Clockhero
   range picker - see the comment on the Roster tab in public/app.js. */
.roster-datectl { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.roster-datectl label { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: #59616d; }
.roster-datectl input { border: 1px solid #d6dbe1; border-radius: 9px; padding: 8px 10px; background: white; font: inherit; font-size: 13px; }
.roster-import { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 12px; }
.roster-import input[type="file"] { font-size: 13px; }

.hist-table { min-width: 980px; }
.hist-actions { white-space: nowrap; }
.hist-actions .small-btn + .small-btn { margin-left: 6px; }
.small-btn.danger { border-color: #f0c4c4; color: #a82929; }
.small-btn.danger:hover { background: #fdeaea; }
/* The one row being edited is tinted so it is obvious which row's Save button
   applies - only one row is editable at a time, on purpose. */
.hist-table tr.hist-editing { background: #f4f7fd; }
.hist-table tr.hist-editing input, .hist-table tr.hist-editing select {
  border: 1px solid #c9d3e6; border-radius: 8px; padding: 6px 8px; background: white; font: inherit; font-size: 13px;
}
.hist-open { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: #59616d; margin-top: 4px; }
.monthly-detail td { background: #fffaf0; font-size: 12px; }

/* v0.8.24: the Activity Log's Export CSV button sits inline with the two
   filter selects (the toolbar is already a wrapping flex row and aligns to
   `end`, so the button lines up with the selects rather than their labels).
   The note below it takes the full row so it wraps instead of squeezing the
   controls. */
.activity-toolbar #exportActivityLogBtn { align-self: end; }
.activity-toolbar .activity-export-note { flex-basis: 100%; margin: 0; color: #7b828d; font-size: 12px; line-height: 1.5; }

/* v0.8.34, tightened again in v0.8.40: the B2C tracker's two tables run much
   denser than the rest of the app (12px -> 11.4px -> 4px of vertical cell
   padding), because this grid is read as a whole board rather than a row at a
   time. Scoped to these two selectors only - the global `th,td` rule is shared
   by every other table in the app. Density only; no column, field or behaviour
   changes. */
.b2c-stack-table th, .b2c-stack-table td,
.b2c-summary-table th, .b2c-summary-table td { padding-top: 4px; padding-bottom: 4px; padding-left: 8px; padding-right: 8px; line-height: 1.2; font-size: 13px; }
.b2c-stack-table .cell-num, .b2c-stack-table .cell-time, .b2c-stack-table select { padding-top: 2px; padding-bottom: 2px; font-size: 12px; }
.b2c-stack-table input[type="checkbox"] { margin: 0; width: 15px; height: 15px; }
.b2c-stack-table .cell-time { width: 78px; }
.b2c-stack-table .cell-num { width: 58px; }

/* v0.8.35: the running tally above the grid. (v0.8.38 removed the derived
   "Unassigned" row it used to sit beside, along with the rest of the workload
   deduction.) */
.b2c-tally { margin: 8px 0 4px; }
.loose-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px 12px; margin: 12px 0; }
.loose-cell { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 5px 8px; border: 1px solid #e6e9ed; border-radius: 8px; font-size: 13px; }
.loose-cell span { color: #3f4650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.loose-cell .cell-num { width: 68px; }
/* v0.8.41: the manage-statuses panel reuses the tally's own grid so the two
   read as one thing - the same status in the same place, with a switch
   instead of a number. */
.loose-manager { border-top: 1px solid #e6e9ed; margin-top: 12px; padding-top: 12px; }
.loose-cell input[type="checkbox"] { width: 16px; height: 16px; margin: 0; }
.b2c-stack-table .cell-time { font: inherit; border: 1px solid #d6dbe1; border-radius: 5px; background: #fff; }

/* v0.8.43: the day's summary tiles, and the rankings gradient. Red deepens
   with `--band-strength` (0 at the edge of the yellow band, 1 at 60% of
   target) so "a bit behind" and "half the target" do not look the same. */
/* The glance box is a plain label/value table (Jim's screenshot): bold labels
   on the left, right-aligned figures on the right. */
.b2c-glance { min-width: 0; max-width: 380px; border: 1px solid #d9dee4; }
.b2c-glance th[scope="row"] { font-weight: 700; background: #fff; }
.b2c-glance th, .b2c-glance td { padding: 5px 10px; border-top: 1px solid #e6e9ed; }
.b2c-glance td.num { font-weight: 700; font-variant-numeric: tabular-nums; color: #5b3fa8; }
.band-cell { font-variant-numeric: tabular-nums; }
.band-cell.band-green { background: #cdefd6; color: #16663a; font-weight: 600; }
.band-cell.band-yellow { background: #f7e2b0; color: #7a5407; font-weight: 600; }
.band-cell.band-red { background: rgba(240, 150, 155, calc(.3 + .7 * var(--band-strength, 1))); color: #6d1116; font-weight: 600; }
.b2c-board h4 small { font-weight: 400; font-size: 11px; }

/* v0.8.53: the B2B grid shades by STACK BLOCK (B2B 1, B2B 2, ...) rather than
   by column group, so the eye finds where one job ends and the next begins.
   Kept pale: the green/amber stage colours and the result cells all sit on top
   of this and have to stay legible. */
.b2c-stack-table td.stack-odd, .b2c-stack-table th.stack-odd { background: #ffffff; }
.b2c-stack-table td.stack-even, .b2c-stack-table th.stack-even { background: #f2f5f9; }
.b2c-stack-table thead th.stack-odd { background: #e8ecf2; }
.b2c-stack-table thead th.stack-even { background: #dde3ec; }
/* The stage colours must win over the base shade - they are about what is
   happening right now, which always matters more than which block it is in. */
.b2c-stack-table tr.b2c-row-picking > *, .b2c-stack-table td.sec-picking { background: #cfeddb; }
.b2c-stack-table tr.b2c-row-processing > *, .b2c-stack-table td.sec-processing { background: #fbe2a8; }
.b2c-stack-table td.tone-under { background: #cdefd6; }
.b2c-stack-table td.tone-over { background: #f8ced0; }
.b2b-ref-cell { display: grid; gap: 3px; }
.b2b-order-pick { max-width: 190px; }

/* v0.8.57 Ticket 5: Clockhero's daily hours/wages bars. Deliberately plain
   CSS bars rather than a charting library - one value per day needs no axis
   engine, and the app ships no chart dependency. */
.hours-chart-panel .hours-chart-head { display: flex; gap: 22px; align-items: baseline; flex-wrap: wrap; margin-bottom: 14px; font-size: 14px; }
.hours-chart { display: flex; align-items: flex-end; gap: 10px; overflow-x: auto; padding-bottom: 4px; }
.hours-bar-col { flex: 1 1 0; min-width: 64px; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.hours-bar-value { font-size: 12px; color: #3b434f; white-space: nowrap; }
/* Fixed-height track so every bar shares one baseline and one scale - without
   it, a column with a short label would sit lower than its neighbours. */
.hours-bar-track { width: 100%; height: 190px; display: flex; align-items: flex-end; }
.hours-bar-fill { width: 100%; background: #8bc34a; border-radius: 2px 2px 0 0; display: flex; align-items: center; justify-content: center; min-height: 2px; }
/* A day nobody worked keeps its column and its caption, drawn as a baseline
   rule - present and empty, never missing. */
.hours-bar-fill.is-empty { background: transparent; border-top: 2px solid #c3cbd6; min-height: 0; }
.hours-bar-amount { color: #fff; font-weight: 600; font-size: 15px; }
.hours-bar-caption { font-size: 12px; color: #6b7280; white-space: nowrap; }
/* v0.8.57 Ticket 3: the shared date filter's anchor - the popover positions
   against this, so every filter in the app opens the same way. */
.cal-anchor { position: relative; display: inline-block; }
.dash-rangebtn-caption { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }
.tracker-daystrip { align-items: center; gap: 10px; flex-wrap: wrap; }
.tracker-pastday { margin: 0; }

/* v0.8.57 Ticket 4: the Daily Updates forms. Two columns on a wide screen,
   stacking on a narrow one - the morning form is read on a laptop at a desk,
   not on the floor.

   v0.8.59: tightened so a whole tab fits one viewport without scrolling, which
   is how it is actually used - screenshotted and pasted into the group chat.
   The numbers are NOT new: they are the same density the B2C summary table has
   used since v0.8.40 (4px vertical / 8px horizontal cell padding, line-height
   1.2, 13px text, 12px inputs). Scoped to .du-* only - the global `th,td` rule
   is shared by every table in the app, and editing it there would restyle the
   whole product under a "make the form smaller" heading (the v0.8.34 lesson). */
.du-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: 10px; align-items: start; }
.du-span { grid-column: 1 / -1; }

/* v0.8.60: LAYOUT ONLY - no density value below this point, the sizing from
   v0.8.59 is unchanged.

   Morning: "To Do vs Target" used to sit full-width UNDER the roster and
   leader blocks, which pushed the tab past one screen on its own. It now sits
   in the right-hand column beside them, spanning both rows, so the tab is two
   columns of roughly equal height instead of one tall stack.

   Two explicit columns rather than auto-fit here: auto-fit decides column
   count from available width, which cannot express "this panel goes beside
   those two". */
@media (min-width: 900px) {
  .du-morning { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  /* The two left-hand panels fall into column 1 in source order; To Do takes
     column 2 across both of their rows. */
  .du-morning > .du-todo { grid-column: 2; grid-row: 1 / span 2; }
  /* End of Day is two equal panels side by side, same as the Morning tab. */
  .du-eod { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
/* Below that width the columns collapse and everything stacks in source
   order, which is the readable answer on a narrow screen. */
/* The global table rule sets min-width:900px, which forces a horizontal
   scrollbar the moment these sit two-to-a-row. They are label/value forms, not
   wide data grids, so they size to their column instead. */
.du-table { min-width: 0; }
.du-table th, .du-table td { padding-top: 4px; padding-bottom: 4px; padding-left: 8px; padding-right: 8px; line-height: 1.2; font-size: 13px; }
.du-table th[scope="row"] { text-align: left; font-weight: 600; width: 44%; text-transform: none; letter-spacing: 0; font-size: 13px; color: #2b3038; background: transparent; }
.du-input { font: inherit; font-size: 12px; width: 100%; max-width: 200px; padding: 2px 6px; border: 1px solid #d6dbe1; border-radius: 5px; }
.du-input.du-wide { max-width: 100%; }
/* An auto-filled field is tinted so it is obvious which numbers the app
   supplied - and typing over one clears nothing, it is a normal input. */
.du-input[data-du-auto] { background: #eef3f8; }
.du-auto-flag { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: #3b6ea5; background: #e3ebf3; border-radius: 3px; padding: 0 4px; vertical-align: middle; }
.du-textarea { font: inherit; font-size: 13px; width: 100%; padding: 6px; border: 1px solid #d6dbe1; border-radius: 6px; }
/* The panels themselves carry 20px of padding and a 14px heading gap by
   default; on this view that alone costs most of a viewport across six cards. */
.du-grid .panel, .dailyupdates-compact .panel { padding: 12px; }
.du-grid .panel h3, .dailyupdates-compact .panel h3 { margin-bottom: 8px; font-size: 15px; }
.du-grid .panel h4 { margin: 10px 0 6px; font-size: 13px; }
.dailyupdates-compact .dash-controls { margin-bottom: 8px; }
.dailyupdates-compact > .card { margin-bottom: 10px; }

/* v0.8.61: per-widget sizing, matching each block's shape in Jim's own
   templates rather than every table sharing one generic width.

   The problem this fixes: every field was a 200px input and every label column
   was 44%, so a "People" cell that holds "3" was as wide as one holding a list
   of names, and each widget wasted a third of its row on empty input. Sized
   per widget, the same content occupies far less height because labels stop
   wrapping and numeric fields stop reserving space they never use.

   Row rhythm is tightened once here for all of them - 3px vertical, 12px text,
   matching the tracker's own inline-control size (v0.8.40's 12px cells). */
.du-table th, .du-table td { padding-top: 3px; padding-bottom: 3px; padding-left: 6px; padding-right: 6px; font-size: 12px; }
.du-table th[scope="row"] { font-size: 12px; }
.du-input { font-size: 12px; padding: 1px 5px; }
/* Roster: label | value. The template's value column holds counts and short
   name lists, so the label takes the majority. */
.du-t-roster th[scope="row"] { width: 58%; }
.du-t-roster .du-input { max-width: 130px; }
.du-t-roster .du-input.du-wide { max-width: 100%; }

/* Late starters: a fixed narrow time column, names taking the rest. */
.du-t-starters th[scope="row"] { width: 74px; }
.du-t-starters .du-input { max-width: 100%; }

/* Leaders: Leader | Area | People, with People just wide enough for a count. */
.du-t-leaders th:nth-child(1), .du-t-leaders td:nth-child(1) { width: 38%; }
.du-t-leaders th:nth-child(2), .du-t-leaders td:nth-child(2) { width: 44%; }
.du-t-leaders th:nth-child(3), .du-t-leaders td:nth-child(3) { width: 18%; }
.du-t-leaders td:nth-child(3) .du-input { max-width: 58px; }
.du-t-leaders .du-input { max-width: 100%; }

/* ETA | Issue/Update | Communication - a short time against two free-text
   columns, which is how the template weights them. */
.du-t-eta th:nth-child(1), .du-t-eta td:nth-child(1) { width: 18%; }
.du-t-eta th:nth-child(2), .du-t-eta td:nth-child(2) { width: 41%; }
.du-t-eta th:nth-child(3), .du-t-eta td:nth-child(3) { width: 41%; }
.du-t-eta .du-input { max-width: 100%; }

/* To Do vs Target: the widest label column of the four, then the entry, then
   a narrow right-aligned target - the template's own proportions. */
.du-t-todo th[scope="row"] { width: 46%; }
.du-t-todo th:nth-child(2), .du-t-todo td:nth-child(2) { width: 36%; }
.du-t-todo th:nth-child(3), .du-t-todo td:nth-child(3) { width: 18%; text-align: right; }
.du-t-todo .du-input { max-width: 100%; }

/* End of Day, areas table: Area | KPI | #People | %Wages | $Wages. The three
   figure columns are narrow and right-aligned, as in the spreadsheet. */
.du-t-areas th:nth-child(1), .du-t-areas td:nth-child(1) { width: 26%; }
.du-t-areas th:nth-child(2), .du-t-areas td:nth-child(2) { width: 32%; }
.du-t-areas th:nth-child(n+3), .du-t-areas td:nth-child(n+3) { width: 14%; text-align: right; }
.du-t-areas .du-input { max-width: 100%; }
.du-t-areas td:nth-child(3) .du-input { max-width: 56px; }
/* The tfoot totals are label | value pairs spanning the same grid. */
.du-t-areas tfoot th[scope="row"] { width: 58%; }
.du-t-areas tfoot .du-input { max-width: 130px; }

/* End of Day, goals table: label | value, values being money and counts. */
.du-t-goals th[scope="row"] { width: 56%; }
.du-t-goals .du-input { max-width: 140px; }
.du-t-goals .du-input.du-wide { max-width: 100%; }


/* v0.8.62: the Daily Updates panels are hand-resizable.
   Native `resize` rather than a custom drag handle: the browser already gives
   a corner grip, keyboard/AT behaviour and pointer capture for free, and a
   hand-rolled handle here would be a lot of code to arrive back at the same
   place. `overflow: auto` is required - `resize` does nothing without it. */
.du-widget { resize: vertical; overflow: auto; }
/* A floor in CSS as well as on the server: the grip lives in the bottom-right
   corner, so a panel dragged smaller than this could not be grabbed again. */
/* v0.8.63: no min-height - it forced a floor on panels whose content is
   shorter, which is half of where the dead space came from. */
.du-widget { min-width: 220px; }
/* The grid sizes columns; a dragged width has to win over its track, or the
   drag appears to do nothing on the horizontal axis. */
.du-grid > .du-widget { max-width: 100%; }

/* v0.8.63: the Daily Updates panels sit flush in one grid, with no gaps and no
   internal scrollbars.

   Three separate causes were producing the floating-cards look, and all three
   had to go:

   1. `gap: 10px` on the grid, plus a 10px bottom margin on the toolbar card,
      drew a visible channel between and around every panel.
   2. `align-items: start` sized each panel to its own content, so two panels
      side by side ended at different heights and left dead space beside the
      shorter one. Stretch instead: a grid row is always at least as tall as
      the tallest thing in it, so stretching can only ever make a panel taller
      than its content - never shorter, which is what would reintroduce a
      scrollbar. That is why this is safe to do while ALSO removing scrollbars.
   3. `min-height: 120px` on a panel whose content is shorter forced a floor
      nothing needed, and `overflow: auto` then scrolled anything the box was
      too short for - which is where the Roster and Areas grips came from.

   `overflow: auto` has to stay: CSS `resize` (v0.8.62) does nothing without a
   non-visible overflow. It is harmless once the box is never shorter than its
   content, which is exactly what stretch guarantees. A panel the user drags
   smaller still scrolls, which is the correct answer to a deliberate choice. */
.du-grid { gap: 0; align-items: stretch; }
.du-grid > .du-widget, .du-grid > .card { height: 100%; min-height: 0; }
/* Square the shared edges and collapse the doubled 1px borders, so adjoining
   panels read as one table rather than as cards that happen to touch. */
.du-grid > .card { border-radius: 0; box-shadow: none; margin: 0 -1px -1px 0; }
/* The outermost corners keep the app's radius, so the block still reads as a
   single card from the outside. */
.du-grid > .card:first-child { border-top-left-radius: 14px; }
.du-grid > .card:last-child { border-bottom-right-radius: 14px; }
.dailyupdates-compact > .card { margin-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
/* The toolbar above the grid is part of the same block, so its bottom edge
   meets the grid's top edge rather than floating above it. */
.dailyupdates-compact > .du-grid > .card:first-child { border-top-left-radius: 0; }
.dailyupdates-compact > .du-grid > .card:nth-child(2) { border-top-right-radius: 0; }

/* v0.8.64: the Plan of Attack renders as real bullets beneath its entry box. */
.du-plan-preview { margin-top: 6px; }
.du-plan-list { margin: 0; padding-left: 18px; font-size: 12px; line-height: 1.35; }
.du-plan-list li { margin: 1px 0; }
/* The End of Day tab is one table again, so it fills the row rather than
   sitting in a half-width column with dead space beside it. */
.du-eod { grid-template-columns: minmax(0, 1fr); }

/* v0.8.65's three-column rules are deleted, not left dangling: columns are
   exactly what stopped horizontal resizing working (see the v0.8.68 block
   below), so keeping them around would only invite the layout back. */
/* v0.8.66: the End of Day table resizes horizontally too. It is a full-width
   panel of its own, so unlike v0.8.63's two-panel split there is nothing
   beside it for a dragged width to knock out of alignment. */
.du-freewidth.du-widget { resize: both; overflow: auto; }
.du-eod > .du-freewidth { max-width: 100%; }

/* v0.8.67: the Daily Rankings boards, styled to match Jim's spreadsheet -
   heavy black gridlines, bold throughout, a black title band, and the
   performance colours filling each value cell.

   ONE treatment, applied to the B2C rankings and both B2B score boards. They
   answer the same question in the same shape, so a second copy would be two
   places to change the day somebody wants the bands adjusted. The colours
   themselves still come from `rateBand`/`band-*` - this only re-skins the
   grid around them, so green/amber/red keep meaning exactly what they meant. */
.rank-title {
  background: #000; color: #fff; font-weight: 700; font-size: 15px;
  text-align: center; padding: 6px 8px; border: 2px solid #000; margin-bottom: 0;
}
.rank-boards { gap: 0; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
/* Boards butt together under the one title band rather than floating apart. */
.rank-board { border: 2px solid #000; border-left-width: 0; }
.rank-boards > .rank-board:first-child { border-left-width: 2px; }
.rank-board h4 {
  margin: 0; padding: 5px 8px; text-align: center; font-size: 13px;
  font-weight: 700; border-bottom: 2px solid #000; background: #fff;
}
.rank-board h4 small { font-weight: 400; }
.rank-table { min-width: 0; }
/* Every cell carries the full gridline, and everything is bold - the reference
   uses weight rather than colour to separate label from figure. */
.rank-table th, .rank-table td {
  border: 2px solid #000; padding: 4px 8px; font-size: 13px; font-weight: 700;
  text-transform: none; letter-spacing: 0; color: #000; background: #fff;
}
.rank-table thead th { background: #fff; font-size: 12px; }
/* The band colours fill the cell edge to edge, over the white default above. */
.rank-table .band-cell.band-green { background: #8fce9d; color: #000; }
.rank-table .band-cell.band-yellow { background: #f5c778; color: #000; }
.rank-table .band-cell.band-red { background: rgba(226, 122, 118, calc(.45 + .55 * var(--band-strength, 1))); color: #000; }
/* The top-rank tint from the old style would fight the band colours, which are
   the only thing on this table that is supposed to carry meaning. */
.rank-table .b2c-rank-top { background: transparent; }
.rank-table .b2c-rank-top th, .rank-table .b2c-rank-top td { background: #fff; }
.rank-table .b2c-rank-top .band-cell.band-green { background: #8fce9d; }
.rank-table .b2c-rank-top .band-cell.band-yellow { background: #f5c778; }

/* v0.8.68: Daily Updates panels are a flat, wrapping set - each one resizable
   on both axes and reorderable.

   Columns are gone. Grouping panels into flex columns is what made horizontal
   resizing impossible: a column with `flex: 1 1 0` has its width computed by
   flex-grow, so the inline width the resize grip writes was overridden every
   frame and the drag looked like it did nothing. `flex: 0 0 auto` with an
   explicit width means the element's own width is what counts - which is the
   whole reason resize works here and did not before. */
.du-flow { display: flex; flex-wrap: wrap; gap: 0; align-items: flex-start; }
.du-flow > .du-widget {
  flex: 0 0 auto; width: 33.33%; min-width: 280px; max-width: 100%;
  resize: both; overflow: auto;
  border-radius: 0; box-shadow: none; margin: 0 -1px -1px 0;
}
/* The End of Day tab is a single table, so it takes the full width. */
.du-flow[data-du-tab-flow="eod"] > .du-widget { width: 100%; }
.du-panel-head { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.du-panel-head h3 { margin: 0; flex: 1 1 auto; font-size: 15px; }
.du-grip { cursor: grab; color: #9aa1ac; letter-spacing: -3px; user-select: none; }
.du-move { display: inline-flex; gap: 2px; }
.du-move .small-btn { padding: 1px 6px; line-height: 1.2; }
/* Where a dragged panel would land. */
.du-drop-target { outline: 2px dashed #3b6ea5; outline-offset: -2px; }

/* v0.8.68: a summary row's Top End Result cell - its figure lives in its own
   sub-rows, so this is deliberately empty rather than an input nobody should
   fill in. */
.du-no-result { background: #f7f8fa; }

/* v0.8.69: the Daily Updates panel-visibility switch, sitting with the other
   layout controls rather than inside the panel it hides (a control inside the
   thing it removes cannot be used to bring it back). */
.du-hide-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: #59616d; white-space: nowrap; }

/* v0.8.69: the Strikes ledger and the bonus calculator. Both are wide, dense
   tables read across; the shared `th,td{padding:12px 14px}` rule is far too
   loose for them, so they are tightened here and here only - the same scoped
   approach v0.8.34/v0.8.40 took for the B2C tracker. */
.strike-table th, .strike-table td,
.bonus-table th, .bonus-table td,
.bonus-paid-table th, .bonus-paid-table td { padding: 4px 8px; font-size: 13px; line-height: 1.2; }
.strike-month { margin: 18px 0 6px; }
.strike-input, .bonus-paid-input { width: 62px; border: 1px solid #d6dbe1; border-radius: 6px; padding: 3px 5px; font: inherit; font-size: 13px; text-align: right; }
.bonus-table .is-ineligible th, .bonus-table .is-ineligible td { opacity: .72; }
.bonus-notes { max-width: 260px; font-size: 12px; }
.bonus-settings { display: flex; flex-wrap: wrap; gap: 18px; margin: 10px 0 16px; padding: 12px; border: 1px solid #e3e7ec; border-radius: 10px; background: #fafbfc; }
.bonus-settings-group { min-width: 260px; }
.bonus-settings-group h4 { margin: 0 0 6px; font-size: 13px; }
.bonus-setting { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 12px; color: #59616d; padding: 2px 0; }
.bonus-setting-input { display: inline-flex; align-items: center; gap: 2px; }
.bonus-setting input { width: 88px; border: 1px solid #d6dbe1; border-radius: 6px; padding: 4px 6px; font: inherit; font-size: 13px; text-align: right; }

/* v0.8.75 Ticket 1: the B2C and B2B tracker grids get the reference sheet's
   own weight - heavy black gridlines, bold text, high contrast throughout.

   This is BORDERS AND WEIGHT ONLY. Every background on these tables already
   carries meaning (the picking/processing base colours from v0.8.49/v0.8.50,
   the stage highlighting from v0.8.40, the green/amber/red result tones), so
   nothing here sets a background - a restyle that repainted the cells would
   have wiped out the colour scheme that says what is actually happening.

   Both trackers use `.b2c-stack-table` (the B2B tracker was built from the
   B2C one in v0.8.51 and kept the class), so one rule covers both rather than
   two copies that drift the first time either is adjusted. Scoped to the
   tracker tables and their summaries - never the global `th,td`. */
.b2c-stack-table th, .b2c-stack-table td,
.b2c-summary-table th, .b2c-summary-table td {
  border: 2px solid #000; font-weight: 700; color: #000;
}
.b2c-stack-table thead th, .b2c-summary-table thead th {
  color: #000; font-weight: 700; letter-spacing: 0;
}
/* The stack header band and the column-group headers read as headings rather
   than as another row of data. */
.b2c-stack-table .b2c-stack-group, .b2c-stack-table .b2c-stack-head th {
  text-align: center; text-transform: none; font-size: 13px;
}
/* The stack edge stays heavier than an ordinary gridline now that every line
   is 2px, or the boundary between one stack and the next disappears. */
.b2c-stack-table .stack-edge { border-left: 4px solid #000; }
.b2c-stack-table th.group-process, .b2c-stack-table td.group-process,
.b2c-stack-table .b2c-process-start { border-left: 4px solid #000; }
/* Inputs inside the grid match the cells around them instead of floating in
   them as rounded light-grey boxes. */
.b2c-stack-table .cell-num, .b2c-stack-table .cell-time, .b2c-stack-table select {
  border: 1px solid #000; border-radius: 3px; font-weight: 700; color: #000; background: transparent;
}
.b2c-stack-table input[type="checkbox"] { accent-color: #000; }
/* The sticky worker column must restate the border, or the shadow it uses to
   separate itself reads as a thin line beside 2px ones. */
.b2c-stack-table .b2c-worker-col { box-shadow: 2px 0 0 #000; }

/* v0.8.75 Ticket 6: the Monthly Tracker's tables, given the same weight and
   room to breathe. Numbers align on the decimal, headers stop shouting in
   small grey capitals, and the money columns are separated from the measured
   ones by a heavier rule so a row can be read across without counting cells. */
.bonus-table th, .bonus-table td,
.bonus-paid-table th, .bonus-paid-table td,
.strike-table th, .strike-table td,
.bonus-travis-table th, .bonus-travis-table td {
  border: 1px solid #000; padding: 6px 10px; font-size: 13px; line-height: 1.35; color: #000;
}
.bonus-table thead th, .bonus-paid-table thead th, .strike-table thead th, .bonus-travis-table thead th {
  background: #f1f3f6; font-weight: 700; text-transform: none; letter-spacing: 0; font-size: 12px; text-align: center;
}
.bonus-table tbody th[scope="row"], .bonus-paid-table tbody th[scope="row"], .bonus-travis-table tbody th[scope="row"] {
  text-align: left; font-weight: 700;
}
.bonus-table td.num, .bonus-paid-table td.num, .bonus-travis-table td.num { font-variant-numeric: tabular-nums; }
.bonus-table tfoot td, .bonus-table tfoot th, .bonus-travis-table tfoot td, .bonus-travis-table tfoot th {
  border-top: 3px solid #000; background: #f1f3f6; font-weight: 700;
}
.bonus-table tr.is-ineligible td, .bonus-table tr.is-ineligible th { background: #fbf1f1; }
.bonus-paid-table .bonus-paid-input { width: 74px; text-align: right; border: 1px solid #000; border-radius: 3px; padding: 3px 5px; font: inherit; }
.bonus-notes { white-space: normal; max-width: 320px; font-weight: 400; }

/* v0.8.75 Ticket 2: Allan's criteria list. One line per criterion with its own
   money beside it, so what a tick is worth is never a separate lookup. */
.bonus-criteria { list-style: none; margin: 10px 0 6px; padding: 0; display: grid; gap: 0; max-width: 900px; }
.bonus-criterion {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  border: 1px solid #000; border-bottom-width: 0; padding: 7px 10px; font-size: 13px;
}
.bonus-criteria > .bonus-criterion:last-child { border-bottom-width: 1px; }
.bonus-criterion label { display: flex; align-items: center; gap: 9px; font-weight: 600; cursor: pointer; }
.bonus-criterion input[type="checkbox"] { width: 17px; height: 17px; accent-color: #000; }

/* v0.8.76: the Clockify name-matching table. Set apart from the panel's prose
   so it reads as a thing to act on rather than another paragraph. */
.clockify-names { border: 1px solid #000; border-radius: 6px; padding: 10px 12px; margin: 12px 0; background: #fbfcfd; }
.clockify-names h4 { margin: 0 0 4px; font-size: 14px; }
.clockify-names select { font: inherit; padding: 3px 6px; border: 1px solid #000; border-radius: 3px; min-width: 210px; }
.clockify-names tr.is-matched td { color: #59616d; }

/* v0.8.79: this month's Travis tiers are typed in the table itself, so the
   figure and the target it is judged against stay side by side. */
.travis-tier-input { width: 84px; text-align: right; font: inherit; border: 1px solid #000; border-radius: 3px; padding: 2px 5px; }
.travis-tier-input::placeholder { color: #8b929c; font-style: italic; }
.bonus-travis-table .travis-amount-row th, .bonus-travis-table .travis-amount-row td { border-top: 3px solid #000; }

/* v0.8.80: probation and warning read as words, and carry their own colour so
   a sheet of them can be scanned - a "warning issued" is the exception, so it
   is the one that stands out. */
.bonus-yesno { font: inherit; font-weight: 700; padding: 2px 4px; border: 1px solid #000; border-radius: 3px; background: #fff; }
td .bonus-yesno { min-width: 62px; }
[data-bonus-probation].is-yes, [data-bonus-warning].is-no { color: #16663a; }
[data-bonus-probation].is-no, [data-bonus-warning].is-yes { color: #8a1c22; background: #fbeaea; }

/* v0.8.81: User Management. */
.user-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0; }
.user-add input, .user-newpass { font: inherit; padding: 6px 8px; border: 1px solid #000; border-radius: 4px; min-width: 200px; }
.user-actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.user-newpass { min-width: 170px; }
.user-table th[scope="row"] { text-align: left; font-weight: 700; }
button.secondary.danger { border-color: #8a1c22; color: #8a1c22; }

/* v0.8.83 Ticket 1: the two Last Print fields carry an order number AND a
   timestamp - the whole value is the point, and it was being cut off. */
.du-input.du-xwide { min-width: 330px; width: 100%; }
.du-t-todo td:first-of-type { min-width: 340px; }
/* Ticket 2: the target column is typed now, so it needs room for a field. */
.du-target-cell { min-width: 110px; }
.du-target-cell .du-input { width: 96px; text-align: right; font-weight: 600; }
/* Ticket 3: the oldest-order date sits under the figure it qualifies. */
.du-row-note { font-size: 11px; color: #59616d; margin-top: 2px; }
/* v0.8.84: the tints are gone (Jim). A carried-forward value says so in its
   tooltip and in the panel's own note; it does not need a colour, and the
   coloured fields read as warnings on a form where nothing is wrong. */
.du-carry-note { margin: 0 0 6px; }

/* v0.8.83 Ticket 7: blank separator columns between the Bonuses table's
   sections, matching the reference sheet. Structural only - the cells carry no
   data and no border, so the groups read apart without anything moving. */
.bonus-table .bonus-gap, .payout-table .bonus-gap {
  width: 14px; min-width: 14px; padding: 0; border-top: 0; border-bottom: 0;
  border-left: 1px solid #000; border-right: 1px solid #000; background: #fff;
}
.bonus-table thead .bonus-gap, .payout-table thead .bonus-gap { background: #fff; }

/* v0.8.83 Ticket 8: the payout sheet. */
.payout-table th, .payout-table td { border: 1px solid #000; padding: 6px 10px; font-size: 13px; color: #000; }
.payout-table thead th { background: #1f2a44; color: #fff; font-weight: 700; text-transform: none; letter-spacing: 0; }
.payout-table tbody th[scope="row"] { text-align: left; font-weight: 700; }
.payout-table tbody tr:nth-child(even) td { background: #f4f7fd; }
.payout-table .payout-total { border-left: 2px solid #000; border-right: 2px solid #000; }
.payout-table .payout-notes { white-space: normal; max-width: 420px; font-weight: 400; color: #2a3f7a; }
.payout-table tfoot th, .payout-table tfoot td { background: #1f2a44; color: #fff; font-weight: 700; border-top: 3px solid #000; }
.payout-table tfoot .payout-total { color: #fff; }
