/* ===========================================================================
   Sun Garner IBP — design system
   ---------------------------------------------------------------------------
   Extracted from the customer-supplied prototype:
       uitheme/SunGarner_ERP_v4.html

   Token values, spacing and component styles are preserved verbatim so the
   built application matches what the customer signed off on. Changes made
   during extraction are limited to:

     - self-hosted icon font (the prototype used a jsDelivr CDN, which does
       not resolve on a LAN-only shop floor — see bin/fetch-assets.sh)
     - a real Inter @font-face (the prototype named Inter but never loaded it,
       so it silently rendered in system-ui everywhere)
     - print rules promoted out of the job-card popup into a shared block
     - focus-visible outlines added for keyboard navigation

   Do not restyle components here to suit one screen. If a screen needs
   something new, add a component — consistency across 45 screens is the
   whole point of a design system.
   =========================================================================== */

*{box-sizing:border-box;margin:0;padding:0}

:root{
  /* Brand — Sun Garner navy and gold */
  --navy:#0f2744;--navy2:#1a3a60;--navy3:#0a1e36;
  --gold:#f5a623;--gold2:#e8951a;--gold3:#fbbf4a;
  --accent:#1d6fa5;--accent2:#155d8a;

  /* Semantic status colours — each has text / background / border */
  --green:#2d7d46;--green-bg:#e8f5ed;--green-b:#a8d5b5;
  --amber:#b36b00;--amber-bg:#fff3e0;--amber-b:#ffcc80;
  --red:#c0392b;--red-bg:#fdecea;--red-b:#f5c6c3;
  --purple:#6d4fa5;--purple-bg:#f0ebfa;--purple-b:#c9b8ef;
  --blue-bg:#e8f2fb;--blue-b:#90c5f0;

  /* Neutrals */
  --border:#e2e8f0;--bg:#f8fafc;--white:#fff;
  --text:#1e293b;--text2:#475569;--text3:#94a3b8;
  --radius:8px;
}

body{font-family:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;font-size:14px;background:var(--bg);color:var(--text);min-height:100vh}
button{cursor:pointer;font-family:inherit;font-size:13px}
input,select,textarea{font-family:inherit;font-size:13px}
a{text-decoration:none;color:inherit}

/* Keyboard accessibility. Store and Production enter high volume and work
   keyboard-first (09 §5) — an invisible focus ring makes that unusable. */
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ── Shell ── */
.shell{display:flex;height:100vh;overflow:hidden}
.sidebar{width:230px;background:var(--navy3);color:#fff;display:flex;flex-direction:column;flex-shrink:0;overflow-y:auto}
.main{flex:1;overflow-y:auto;display:flex;flex-direction:column;min-width:0}
.topbar{background:var(--white);border-bottom:1px solid var(--border);padding:0 24px;height:56px;display:flex;align-items:center;gap:12px;flex-shrink:0;position:sticky;top:0;z-index:10}
.content{flex:1;padding:20px 24px;max-width:1300px;width:100%}

/* ── Sidebar ── */
.sb-logo{padding:18px 16px 14px;border-bottom:1px solid rgba(255,255,255,.08)}
.sb-logo-main{font-weight:700;font-size:15px;color:var(--gold)}
.sb-logo-sub{font-size:10px;color:rgba(255,255,255,.58);margin-top:2px}
.sb-user{padding:10px 16px;border-bottom:1px solid rgba(255,255,255,.08);display:flex;align-items:center;gap:8px}
.sb-avatar{width:30px;height:30px;border-radius:50%;background:var(--gold);color:var(--navy);font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.sb-user-info{min-width:0}
.sb-uid{font-size:12px;font-weight:600;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sb-dept{font-size:10px;color:rgba(255,255,255,.58)}
/* ── Sidebar legibility ─────────────────────────────────────────────────
   Contrast measured against --navy3 #0a1e36, the sidebar ground.
   The section labels were the actual fault at 2.67:1 — below AA, at the
   smallest size in the product. Menu text already passed at 6.74:1 and
   read as faded for a different reason: 13px at weight 400 under a low
   alpha has thin strokes, so it gains weight as well as opacity.

   The ceiling is the gold active state at 8.28:1. Resting text sits at
   8.29:1 — level with it, never above it, because unselected text
   brighter than selected text makes the selected row look disabled.
   Hover stays pure white at 16.77:1, so the hierarchy still reads
   resting < hover, and active is carried by hue and the left bar. */
.nav-section{padding:6px 0}
.nav-label{font-size:10px;color:rgba(255,255,255,.55);text-transform:uppercase;letter-spacing:.08em;
  font-weight:700;padding:9px 16px 3px}
.nav-item{display:flex;align-items:center;gap:9px;padding:7px 16px;cursor:pointer;color:rgba(255,255,255,.68);
  font-weight:500;transition:all .15s;border-left:3px solid transparent;font-size:13px}
.nav-item:hover{background:rgba(255,255,255,.06);color:#fff}
.nav-item.active{background:rgba(245,166,35,.12);color:var(--gold);border-left-color:var(--gold)}
.nav-item i{font-size:15px;width:16px;text-align:center;flex-shrink:0}
.nav-badge{background:var(--red);color:#fff;font-size:9px;font-weight:700;padding:1px 5px;border-radius:10px;margin-left:auto}
.nav-badge-gold{background:var(--gold);color:var(--navy);font-size:9px;font-weight:700;padding:1px 5px;border-radius:10px;margin-left:auto}

/* ── Topbar ── */
.tb-title{font-weight:600;font-size:15px;flex:1}
.tb-right{display:flex;align-items:center;gap:10px}
.tb-icon-btn{width:34px;height:34px;border-radius:var(--radius);border:1px solid var(--border);background:var(--white);display:flex;align-items:center;justify-content:center;cursor:pointer;position:relative;color:var(--text2)}
.tb-icon-btn:hover{background:var(--bg)}
.tb-notif{position:absolute;top:-3px;right:-3px;width:8px;height:8px;background:var(--red);border-radius:50%;border:1.5px solid var(--white)}
.search-box{display:flex;align-items:center;gap:8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);padding:6px 10px;flex:1;max-width:280px}
.search-box i{color:var(--text3);font-size:15px}
.search-box input{border:none;background:none;outline:none;font-size:13px;width:100%;color:var(--text)}

/* ── Cards ── */
.card{background:var(--white);border:1px solid var(--border);border-radius:12px;padding:20px;margin-bottom:16px}
.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}
.card-title{font-weight:600;font-size:15px;display:flex;align-items:center;gap:8px}
.card-title i{color:var(--accent)}

/* ── Stats ── */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin-bottom:20px}
.stat{background:var(--white);border:1px solid var(--border);border-radius:10px;padding:14px 16px}
.stat-label{font-size:11px;color:var(--text3);text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px}
.stat-val{font-size:22px;font-weight:700}
.stat-sub{font-size:11px;color:var(--text3);margin-top:2px}
.stat-trend-up{color:var(--green);font-size:11px}
.stat-trend-down{color:var(--red);font-size:11px}

/* ── Forms ── */
.fg2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.fg3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px}
.fg4{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:12px}
.full{grid-column:1/-1}
.field{display:flex;flex-direction:column;gap:4px}
.field label{font-size:12px;font-weight:500;color:var(--text2)}
.field input,.field select,.field textarea{border:1px solid var(--border);border-radius:var(--radius);padding:8px 10px;color:var(--text);background:var(--white);transition:border .15s;width:100%}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(29,111,165,.1)}
.field textarea{resize:vertical;min-height:70px}
.field-note{font-size:11px;color:var(--text3);margin-top:2px}
.field .error{font-size:11px;color:var(--red);margin-top:2px}
.field input[aria-invalid="true"],.field select[aria-invalid="true"]{border-color:var(--red-b)}

/* ── Buttons ── */
.btn{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border-radius:var(--radius);border:1px solid var(--border);background:var(--white);color:var(--text);font-weight:500;transition:all .15s;font-size:13px;cursor:pointer}
.btn:hover{background:var(--bg)}
.btn:disabled{opacity:.5;cursor:not-allowed}
.btn-primary{background:var(--navy);color:#fff;border-color:var(--navy)}
.btn-primary:hover{background:var(--navy2)}
.btn-gold{background:var(--gold);color:var(--navy);border-color:var(--gold);font-weight:600}
.btn-gold:hover{background:var(--gold2)}
.btn-danger{background:var(--red-bg);color:var(--red);border-color:var(--red-b)}
.btn-success{background:var(--green-bg);color:var(--green);border-color:var(--green-b)}
.btn-sm{padding:5px 10px;font-size:12px;border-radius:6px}
.btn-xs{padding:3px 8px;font-size:11px;border-radius:5px}
.btn-row{display:flex;gap:8px;flex-wrap:wrap;margin-top:16px;align-items:center}

/* ── Status badges ── */
.badge{display:inline-flex;align-items:center;gap:3px;font-size:11px;font-weight:600;padding:2px 8px;border-radius:20px}
.badge-pending{background:var(--amber-bg);color:var(--amber);border:1px solid var(--amber-b)}
.badge-approved{background:var(--green-bg);color:var(--green);border:1px solid var(--green-b)}
.badge-rejected{background:var(--red-bg);color:var(--red);border:1px solid var(--red-b)}
.badge-inprog{background:var(--blue-bg);color:var(--accent);border:1px solid var(--blue-b)}
.badge-new{background:var(--purple-bg);color:var(--purple);border:1px solid var(--purple-b)}
.badge-done{background:#f0fdf4;color:#166534;border:1px solid #bbf7d0}
.badge-navy{background:var(--navy);color:#fff}
.badge-gold{background:var(--gold);color:var(--navy)}
/* Semantic set, alongside the workflow-named badges above.
   The names above describe a STATE (approved, in progress); these describe
   a SEVERITY, which is what an enum spanning eleven states needs — there is
   no badge-partially-received worth having. Added after finding the
   purchasing enums already referenced these five while the CSS defined none
   of them, so every PO status rendered with no colour at all. */
.badge-ok{background:var(--green-bg);color:var(--green);border:1px solid var(--green-b)}
.badge-warn{background:var(--amber-bg);color:var(--amber);border:1px solid var(--amber-b)}
.badge-danger{background:var(--red-bg);color:var(--red);border:1px solid var(--red-b)}
.badge-info{background:var(--blue-bg);color:var(--accent);border:1px solid var(--blue-b)}
.badge-muted{background:var(--bg);color:var(--text2);border:1px solid var(--border)}

/* Semantic text colours, sharing the badge palette so a red number and a red
   badge on the same row are the same red.

   These were already in use — the purchase register's overdue count and the
   stock register's negative quantities both ask for .text-danger — but had
   never been defined, so every one of them rendered in ordinary body colour.
   A count that is supposed to shout was whispering. */
.text-danger{color:var(--red)}
.text-warn{color:var(--amber)}
.text-ok{color:var(--green)}

/* ── Tables ── */
.tbl-wrap{overflow-x:auto;border-radius:10px;border:1px solid var(--border)}
.tbl{width:100%;border-collapse:collapse;min-width:600px}
.tbl th{font-size:11px;font-weight:600;color:var(--text3);text-transform:uppercase;letter-spacing:.04em;padding:9px 12px;text-align:left;border-bottom:1px solid var(--border);background:var(--bg);white-space:nowrap}
.tbl td{padding:10px 12px;border-bottom:1px solid #f1f5f9;font-size:13px;vertical-align:middle}
.tbl tr:last-child td{border-bottom:none}
.tbl tr:hover td{background:#fafbfc}
.tbl-link{color:var(--accent);font-weight:600;cursor:pointer}
.tbl-link:hover{text-decoration:underline}
/* Quantities and money read as columns, not prose. */
.tbl .num{text-align:right;font-variant-numeric:tabular-nums}

/* Row-action icon buttons — compact, native title tooltip carries the label. */
.tbl-actions{display:flex;gap:4px;align-items:center;justify-content:flex-end;white-space:nowrap}
.tbl-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;
  border-radius:6px;border:1px solid transparent;background:transparent;color:var(--text2);
  cursor:pointer;transition:all .15s;font-size:15px;line-height:1}
.tbl-icon-btn:hover{background:var(--blue-bg);color:var(--accent);border-color:var(--blue-b)}
.tbl-icon-btn.danger:hover{background:var(--red-bg);color:var(--red);border-color:var(--red-b)}

/* An action that needs a word of context before it fires — Finance recording
   a payment with a remark. The input sits in the row rather than behind a
   modal: this is a queue, and a round trip per row is how a queue stops
   being worked. */
.inline-form{display:flex;gap:4px;align-items:center}
.inp-sm{border:1px solid var(--border);border-radius:var(--radius);padding:5px 8px;
  font-size:12px;color:var(--text);background:var(--white);width:150px;transition:border .15s}
.inp-sm:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(29,111,165,.1)}
@media (max-width:760px){.inp-sm{width:110px}}

/* ── Permission picker (Roles create/edit) ── */
.perm-group{border:1px solid var(--border);border-radius:10px;margin-bottom:12px;overflow:hidden}
.perm-group-header{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:9px 14px;background:var(--bg);border-bottom:1px solid var(--border)}
.perm-group-heading{display:flex;align-items:center;gap:8px}
.perm-group-title{font-weight:600;font-size:13px;color:var(--text)}
.perm-group-count{font-size:11px;color:var(--text3);font-weight:600;font-variant-numeric:tabular-nums}
.perm-group-actions{display:flex;gap:10px}
.perm-group-toggle{font-size:11px;color:var(--accent);font-weight:600;cursor:pointer;background:none;border:none;padding:0}
.perm-group-toggle:hover{text-decoration:underline}
.perm-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:1px;background:var(--border)}
.perm-item{display:flex;align-items:flex-start;gap:9px;padding:8px 14px;background:var(--white);cursor:pointer;transition:background .15s}
.perm-item:hover{background:var(--bg)}
.perm-item:has(input:checked){background:var(--blue-bg)}
.perm-item input[type=checkbox]{margin-top:2px;flex-shrink:0;width:15px;height:15px;accent-color:var(--accent);cursor:pointer}
.perm-item-text{display:flex;flex-direction:column;gap:1px;min-width:0}
.perm-item-label{font-size:12.5px;font-weight:500;color:var(--text)}
.perm-item-code{font-size:10.5px;color:var(--text3);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
@media (max-width:600px){.perm-list{grid-template-columns:1fr}}

/* ── Tabs ── */
.tabs{display:flex;border-bottom:2px solid var(--border);margin-bottom:18px;gap:0;overflow-x:auto}
.tab{padding:9px 18px;font-size:13px;font-weight:500;color:var(--text2);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px;white-space:nowrap;transition:all .15s}
.tab:hover{color:var(--text)}
.tab.active{color:var(--navy);border-bottom-color:var(--navy);font-weight:600}

/* ── Section headers ── */
.sec-title{font-size:11px;font-weight:700;color:var(--text3);text-transform:uppercase;letter-spacing:.07em;margin-bottom:10px;padding-bottom:7px;border-bottom:1px solid var(--border)}
.divider{height:1px;background:var(--border);margin:16px 0}

/* ── Pipeline (document stage indicator) ── */
.pipeline{display:flex;align-items:center;overflow-x:auto;gap:0;margin:12px 0;padding:4px 0}
.pipe-step{display:flex;align-items:center}
.pipe-node{padding:6px 12px;border-radius:6px;font-size:11px;font-weight:600;white-space:nowrap;border:1.5px solid var(--border);background:var(--bg);color:var(--text3)}
.pipe-node.done{background:var(--green-bg);border-color:var(--green-b);color:var(--green)}
.pipe-node.active{background:var(--blue-bg);border-color:var(--accent);color:var(--accent)}
.pipe-node.rejected{background:var(--red-bg);border-color:var(--red-b);color:var(--red)}
.pipe-arr{color:var(--text3);padding:0 3px;font-size:14px}

/* ── Alerts ── */
.alert{padding:10px 14px;border-radius:var(--radius);font-size:13px;margin-bottom:12px;display:flex;align-items:flex-start;gap:8px}
.alert-success{background:var(--green-bg);border:1px solid var(--green-b);color:var(--green)}
.alert-warn{background:var(--amber-bg);border:1px solid var(--amber-b);color:var(--amber)}
.alert-info{background:var(--blue-bg);border:1px solid var(--blue-b);color:var(--accent)}
.alert-danger{background:var(--red-bg);border:1px solid var(--red-b);color:var(--red)}

/* ── Tags ── */
.tag{display:inline-block;font-size:11px;font-weight:600;padding:2px 7px;border-radius:4px}
.tag-grid{background:#dbeafe;color:#1e40af}
.tag-offgrid{background:#fef3c7;color:#92400e}
.tag-bess{background:#ede9fe;color:#5b21b6}
.tag-pm{background:#d1fae5;color:#065f46}
.tag-inv{background:#ffe4e6;color:#9f1239}
.tag-product{background:#e0f2fe;color:#0369a1}
.tag-project{background:#fce7f3;color:#9d174d}
/* Lead channel — how the work arrived. Deliberately outside the order-type
   hues above, because the two sit in adjacent columns on the lead register
   and must not read as the same family of thing. */
.tag-tender{background:#e2e8f0;color:#334155}
.tag-ci{background:#ccfbf1;color:#115e59}
.tag-partner{background:#e0e7ff;color:#3730a3}

/* ── Timeline (contextual chat / audit trail) ── */
.timeline{padding-left:18px;border-left:2px solid var(--border)}
.tl-item{position:relative;padding:0 0 14px 14px}
.tl-dot{position:absolute;left:-7px;top:4px;width:12px;height:12px;border-radius:50%;background:var(--accent);border:2px solid var(--white)}
.tl-who{font-size:12px;font-weight:600}
.tl-when{font-size:11px;color:var(--text3)}
.tl-note{font-size:12px;color:var(--text2);margin-top:2px}

/* ── Messages ── */
.msg-bubble{background:var(--bg);border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin-bottom:8px;font-size:13px}
.msg-bubble.mine{background:var(--blue-bg);border-color:var(--blue-b);margin-left:40px}
.msg-bubble.theirs{margin-right:40px}
.msg-meta{font-size:11px;color:var(--text3);margin-bottom:3px}
.msg-linked{font-size:11px;color:var(--accent);font-weight:500}

/* ── Modal ── */
.modal-bg{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:200;display:flex;align-items:center;justify-content:center;padding:20px}
.modal{background:var(--white);border-radius:14px;padding:24px;width:100%;max-width:620px;max-height:90vh;overflow-y:auto;position:relative}
.modal-close{position:absolute;top:14px;right:14px;background:none;border:none;font-size:20px;cursor:pointer;color:var(--text3);line-height:1}

/* ── Misc ── */
.empty{text-align:center;padding:40px 20px;color:var(--text3)}
.empty i{font-size:36px;margin-bottom:8px;display:block;opacity:.5}
.empty p{font-size:13px}
.avatar-circle{border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:600;flex-shrink:0}
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.info-pair{font-size:13px;padding:5px 0;border-bottom:1px solid #f1f5f9;display:flex;justify-content:space-between;gap:12px}
.info-pair:last-child{border-bottom:none}
.info-pair .lbl{color:var(--text3);font-size:12px;font-weight:500;white-space:nowrap}
.info-pair .val{font-weight:500;text-align:right}
.photo-upload{width:80px;height:80px;border-radius:50%;border:2px dashed var(--border);display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer;overflow:hidden;position:relative;background:var(--bg);flex-shrink:0}
.photo-upload img{width:100%;height:100%;object-fit:cover}
.photo-upload input{position:absolute;inset:0;opacity:0;cursor:pointer}
.prog-bar-wrap{height:6px;background:var(--border);border-radius:3px;overflow:hidden;margin-top:4px}
.prog-bar{height:100%;border-radius:3px;transition:width .4s}
.prog-green{background:var(--green)}
.prog-amber{background:var(--gold)}
.prog-red{background:var(--red)}
.progress-fill{height:100%;border-radius:3px;background:var(--accent)}

/* ── Utilities ── */
.flex{display:flex;align-items:center;gap:8px}
.flex-between{display:flex;align-items:center;justify-content:space-between}
.flex-wrap{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.hidden{display:none!important}
.text-muted{color:var(--text3)}
.text-accent{color:var(--accent)}
.text-gold{color:var(--gold2)}
.fw600{font-weight:600}
.fs12{font-size:12px}
.fs11{font-size:11px}
.mt8{margin-top:8px}
.mt12{margin-top:12px}
.mt16{margin-top:16px}
.mb8{margin-bottom:8px}
.mb12{margin-bottom:12px}

/* ── Print ──
   Job cards, POs, indents and invoices are paper documents on a shop floor.
   Print is a first-class output (02 §3), not an afterthought. */
@media print{
  .sidebar,.topbar,.btn,.btn-row,.tabs,.modal-bg{display:none!important}
  .shell{display:block;height:auto;overflow:visible}
  .main{overflow:visible}
  .content{padding:0;max-width:none}
  .card{border:none;box-shadow:none;padding:0;margin-bottom:12px;break-inside:avoid}
  .tbl-wrap{overflow:visible;border:none}
  .tbl th{background:var(--navy)!important;color:#fff!important;-webkit-print-color-adjust:exact;print-color-adjust:exact}
  body{background:#fff;font-size:12px}
}

/* Shop-floor terminals are often 1366x768 on older hardware (09 §5). */
@media (max-width:1100px){
  .fg4{grid-template-columns:1fr 1fr}
  .fg3{grid-template-columns:1fr 1fr}
  .two-col{grid-template-columns:1fr}
}
@media (max-width:760px){
  .sidebar{position:fixed;left:-230px;top:0;bottom:0;z-index:150;transition:left .2s}
  .sidebar.open{left:0}
  .fg2,.fg3,.fg4{grid-template-columns:1fr}
  .content{padding:14px}
}

/* ── Dashboard: punch button, trend graphs ──────────────────────────────
   Charts are plain markup — a bar is a div with a height. No charting
   library is vendored and an intranet box has no CDN, so the alternative
   was a dependency to carry and patch for two graphs. The numbers stay
   legible if this stylesheet never loads. */
.mt4{margin-top:4px}
.punch-box{text-align:right}

/* Small dot on the topbar icon, so "you are on shift" is visible without
   reading a tooltip. */
.tb-icon-btn{position:relative}
.tb-punch-dot{position:absolute;top:6px;right:6px;width:7px;height:7px;border-radius:50%;
  background:var(--green);border:1.5px solid var(--white)}

.chart-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px}

/* Vertical bars: attendance per day. align-items:flex-end so bars grow up
   from a shared baseline. */
.bars{display:flex;align-items:flex-end;gap:2px;height:120px;padding:8px 0;
  border-bottom:1px solid var(--border)}
.bar-col{flex:1;height:100%;display:flex;align-items:flex-end;min-width:3px}
.bar-fill{width:100%;background:var(--gold);border-radius:2px 2px 0 0;min-height:1px;
  transition:opacity .12s}
.bar-col:hover .bar-fill{opacity:.7}
.bar-axis{display:flex;justify-content:space-between;font-size:11px;color:var(--text3);margin-top:6px}

/* Horizontal bars: open tasks per person. */
.hbar{display:flex;align-items:center;gap:10px;padding:6px 0;text-decoration:none;color:inherit}
.hbar:hover .hbar-fill{opacity:.75}
.hbar-name{flex:0 0 130px;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hbar-track{flex:1;background:var(--bg);border-radius:4px;height:14px;overflow:hidden}
.hbar-fill{display:block;height:100%;background:var(--gold);border-radius:4px;min-width:2px}
.hbar-val{flex:0 0 32px;text-align:right;font-size:12px;font-weight:600}

/* ── List tables: sortable headings, footer controls, filter chips ───────
   Sorting and paging are server-side, so a heading is a link and the page
   size is a form — no table library involved. See partials/sortable-th and
   partials/table-controls. */
.th-sort{display:inline-flex;align-items:center;gap:4px;color:inherit;text-decoration:none;
  font:inherit;letter-spacing:inherit;text-transform:inherit;white-space:nowrap}
.th-sort:hover{color:var(--gold)}
/* The neutral double-arrow sits back until hovered, so a sorted column is the
   only one drawing the eye. */
.th-sort .ti{font-size:13px;opacity:.35;transition:opacity .12s}
.th-sort:hover .ti{opacity:.8}
.th-sort.is-active{color:var(--gold)}
.th-sort.is-active .ti{opacity:1}

.tbl-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;padding:10px 2px 0}
.tbl-perpage{display:flex;align-items:center;gap:6px}
.tbl-perpage select{padding:3px 6px;border:1px solid var(--border);border-radius:6px;
  background:var(--white);color:inherit}

/* Filters that arrived from a link rather than from the filter bar, so they
   can announce themselves and be dismissed. */
.chip{display:inline-flex;align-items:center;gap:6px;font-size:11px;padding:4px 8px;
  border:1px solid var(--amber-b);background:var(--amber-bg);color:var(--amber);border-radius:999px}
.chip-x{color:inherit;text-decoration:none;font-size:14px;line-height:1;opacity:.7;padding:0 2px}
.chip-x:hover{opacity:1}

/* ── Segmented control ───────────────────────────────
   Two or three exclusive choices, shown side by side rather than in a
   dropdown. Used where the choice changes what the rest of the form means
   and hiding it behind a click would bury it — project vs product on a
   sales order decides what a line item even is.

   Real radios underneath: keyboard and screen readers get a radiogroup, and
   the form still posts with no JavaScript. */
.seg{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius);
  overflow:hidden;background:var(--white);
  /* Shrink to the buttons. .field is flex-direction:column, so the cross
     axis is horizontal and the default align-items:stretch pulled this box
     out to the field width — leaving a wide empty area inside the border to
     the right of the last option. inline-flex does not save you from that;
     the stretch is applied by the PARENT. */
  align-self:flex-start}
.seg-opt{position:relative;cursor:pointer;margin:0}
.seg-opt + .seg-opt{border-left:1px solid var(--border)}
.seg-opt input{position:absolute;opacity:0;width:100%;height:100%;left:0;top:0;
  margin:0;cursor:pointer}
.seg-opt span{display:block;padding:7px 18px;font-size:13px;font-weight:500;
  color:var(--text2);transition:background .12s,color .12s;user-select:none}
.seg-opt.is-on span{background:var(--navy);color:#fff;font-weight:600}
/* Focus lands on the hidden radio, so the ring has to be drawn on the label. */
.seg-opt input:focus-visible + span{outline:2px solid var(--accent);outline-offset:-2px}
.seg-opt:hover span{background:var(--bg)}
.seg-opt.is-on:hover span{background:var(--navy2)}

/* ── Read-only fields ───────────────────────────────────────────────────
   A disabled input must not look like an empty one somebody forgot to
   fill. Dashed border plus a grey ground says "this is shown to you, not
   asked of you" — used for the derived category code. */
.field input:disabled,.field select:disabled,.field textarea:disabled{
  background:var(--bg);color:var(--text3);border-style:dashed;cursor:not-allowed;
  box-shadow:none}
.field input:disabled:focus,.field select:disabled:focus{outline:none;box-shadow:none;
  border-color:var(--border)}
/* Marks the label of a derived field, so the reason is next to the name. */
.label-derived{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;
  color:var(--text3);background:var(--bg);border:1px solid var(--border);
  border-radius:4px;padding:1px 5px;margin-left:6px;vertical-align:middle}

/* ── Field explanations ─────────────────────────────────────────────────
   The little (i) beside a label. Pure hover/focus — see
   partials/field-info.blade.php for why there is no JS here. */
.field-info{position:relative;display:inline-flex;align-items:center;margin-left:5px;
  color:var(--text3);cursor:help;vertical-align:middle}
.field-info:hover,.field-info:focus{color:var(--accent);outline:none}
.field-info .ti{font-size:14px}
.field-info-bubble{position:absolute;bottom:calc(100% + 7px);left:-8px;z-index:60;
  width:250px;padding:8px 10px;border-radius:8px;
  background:var(--navy);color:#fff;font-size:11px;font-weight:400;line-height:1.5;
  text-transform:none;letter-spacing:normal;
  box-shadow:0 6px 20px rgba(0,0,0,.28);
  opacity:0;visibility:hidden;transition:opacity .12s,visibility .12s}
.field-info.is-wide .field-info-bubble{width:330px}
.field-info:hover .field-info-bubble,
.field-info:focus .field-info-bubble{opacity:1;visibility:visible}
/* Little arrow, so the bubble reads as belonging to the icon. */
.field-info-bubble::after{content:'';position:absolute;top:100%;left:11px;
  border:5px solid transparent;border-top-color:var(--navy)}
.field-info-bubble b{font-weight:600}
/* Near the right edge the bubble would overflow; flip it. */
.field-info.flip-left .field-info-bubble{left:auto;right:-8px}
.field-info.flip-left .field-info-bubble::after{left:auto;right:11px}

/* ── Searchable dropdown (Tom Select) ───────────────────────────────────
   The list is parented to <body> (see sgibp-select.js) to escape the
   overflow-x:auto on .tbl-wrap, which was clipping it. Body-parented means
   it now needs to out-stack everything: 300 clears the modal backdrop (200)
   and the mobile sidebar (150), which is right — a dropdown opened inside a
   modal must still be readable. */
.ts-dropdown{z-index:300;border:1px solid var(--border);border-radius:8px;
  box-shadow:0 10px 30px rgba(0,0,0,.16);font-size:13px}
.ts-wrapper.single .ts-control{border:1px solid var(--border);border-radius:var(--radius);
  padding:7px 10px;background:var(--white);min-height:0}
.ts-wrapper.single.focus .ts-control{border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(29,111,165,.1)}
.ts-wrapper.disabled .ts-control{background:var(--bg);cursor:not-allowed}
.ts-dropdown .active{background:rgba(29,111,165,.10);color:inherit}

/* Code first and monospaced so the eye can run down the column, then the
   description — the same shape the old <option> text had. */
.ts-row{display:flex;gap:8px;align-items:baseline}
.ts-code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:11px;
  font-weight:600;color:var(--accent);flex:0 0 auto}
.ts-name{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ts-dropdown .ts-loading,.ts-dropdown .no-results{padding:8px 10px;color:var(--text3);font-size:12px}

/* ── Layout guard: the shell owns the viewport ──────────────────────────
   .shell is height:100vh with .main scrolling inside it, so the DOCUMENT
   should never scroll on desktop. When it does, the shell slides up and
   leaves a blank strip below it — which is what a body-parented dropdown
   caused: .ts-dropdown is position:absolute; top:100%, and with <body>
   unpositioned its containing block is the viewport, so "100%" placed it at
   exactly 100vh and extended the page.

   Fixed at the source — a dropdown attached to <body> starts at the origin,
   and positionDropdown() sets an explicit inline top when it opens, which
   wins over this. */
body > .ts-dropdown{top:0;left:0}

/* And made structurally impossible, so no future body-level element can
   reintroduce it. */
html,body{height:100%}
body{overflow:hidden}

/* Mobile is the opposite: there .main is overflow:visible and the sidebar is
   off-canvas, so the document itself is the scroller and must stay one. */
@media (max-width:760px){
  html,body{height:auto;overflow:visible}
}
