/* eabcx — public/app/kit/grid.css
   Styles for kit/grid.js (dataGrid) and kit/editgrid.js (editGrid).
   Every colour is a token from tokens.css. Dark mode comes free through the tokens.
   z-index ladder (load-bearing): th.rn 8 > thead th.frz 7 > td.frz / td.rn / .fillh 5
   > .selbox / marching ants 4 > focused .celled 3 > td.gc.active 2. */

/* ============================ shared chrome ============================ */
.dg, .eg{
  --dg-py:7px; --dg-px:12px;              /* default density 10 x 14 */
  --dg-headh:30px;
  display:flex; flex-direction:column; min-width:0; width:100%;
  font:13px/1.35 var(--font); color:var(--txt);
}
.dg.dg-dense, .eg.eg-dense{ --dg-py:var(--cell-y); --dg-px:var(--cell-x); --dg-headh:27px; }  /* 9 x 12 */

.dg-tools{
  display:flex; align-items:center; gap:6px; justify-content:space-between;
  padding:6px 4px 8px; min-height:34px;
}
.dg-tools-l, .dg-tools-r{ display:flex; align-items:center; gap:4px; }
.dg-tsep{ width:1px; height:18px; background:var(--line); margin:0 4px; }

.dg-iconbtn{
  display:inline-flex; align-items:center; justify-content:center;
  width:30px; height:30px; padding:0; border:1px solid transparent; border-radius:var(--radius-ctl);
  background:transparent; color:var(--muted); cursor:pointer;
  transition:background var(--t) var(--ease), color var(--t) var(--ease), border-color var(--t) var(--ease);
}
.dg-iconbtn:hover{ background:var(--bg2); color:var(--txt); border-color:var(--line); }
.dg-iconbtn:active{ background:var(--accent-soft); color:var(--accent); }
.dg-iconbtn:focus-visible{ outline:none; box-shadow:0 0 0 3px var(--accent-soft); }
.dg-iconbtn svg{ width:16px; height:16px; display:block; }

.dg-search{ position:relative; display:flex; align-items:center; }
.dg-search-ic{ position:absolute; left:9px; display:flex; color:var(--faint); pointer-events:none; }
.dg-search-ic svg{ width:14px; height:14px; display:block; }
/* chrome.css's `input[type=search]` (0,1,1) outranks a bare class (0,1,0) and was
   taking back the height, the pill radius and — visibly — the 28px left padding
   that keeps the placeholder out from under the magnifier (Rule 04b §6). */
.dg-search input.dg-search-i{
  height:30px; width:220px; padding:0 10px 0 28px; font:13px var(--font); color:var(--txt);
  background:var(--panel); border:1px solid var(--line); border-radius:var(--pill); outline:none;
}
.dg-search input.dg-search-i:focus{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft); }
.dg-search-i::placeholder{ color:var(--faint); }

/* ============================ dataGrid table ============================ */
.dg-scroll{
  position:relative; overflow:auto; background:var(--panel);
  border:1px solid var(--line); border-radius:var(--radius-card);
  max-height:var(--dg-maxh, none); outline:none; scrollbar-gutter:stable;
}
.dg-scroll:focus-visible{ box-shadow:0 0 0 3px var(--accent-soft); }
.dg-t{ width:100%; border-collapse:separate; border-spacing:0; table-layout:fixed; }

.dg-t thead th{
  position:sticky; top:0; z-index:6;
  height:var(--dg-headh); box-sizing:border-box;
  padding:0 var(--dg-px); text-align:left; white-space:nowrap; overflow:visible;
  background:var(--panel); color:var(--muted);
  font:600 11px/1 var(--font); letter-spacing:.06em; text-transform:uppercase;
  border-bottom:1px solid var(--line); user-select:none;
}
.dg-t thead th.dg-sortable{ cursor:pointer; }
.dg-t thead th.dg-sortable:hover{ color:var(--txt); background:var(--bg2); }
.dg-t thead th.dg-sorted{ color:var(--accent); }
.dg-hlab{ display:inline-block; vertical-align:middle; }
.dg-sortic{ display:inline-flex; vertical-align:middle; margin-left:4px; color:var(--accent); }
.dg-sortic svg{ width:12px; height:12px; display:block; }
.dg-rz{ position:absolute; top:0; right:-3px; width:7px; height:100%; cursor:col-resize; z-index:2; }
.dg-rz:hover{ background:var(--accent-soft); }

.dg-t td{
  padding:var(--dg-py) var(--dg-px); border-bottom:1px solid var(--line);
  background:var(--panel); vertical-align:middle; overflow:hidden;
}
.dg-cv{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.dg-t td.a-right, .dg-t th.a-right{ text-align:right; }
.dg-t td.a-center, .dg-t th.a-center{ text-align:center; }
.dg-numc{ font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1; }

.dg-t tbody tr.dg-r:hover td{ background:var(--bg2); }
.dg-t tbody tr.dg-selected td{ background:var(--accent-soft); }
.dg-t tbody tr.dg-selected td:first-child{ box-shadow:inset 2px 0 0 var(--accent); }
.dg-t tbody tr.dg-r{ cursor:default; }
.dg tbody td.dg-act{ box-shadow:inset 0 0 0 2px var(--accent); border-radius:2px; }
.dg-t tbody tr.dg-spacer td{ border:0; background:var(--panel); }
.dg-t tfoot td{
  position:sticky; bottom:0; z-index:6;
  background:var(--bg2); border-top:1px solid var(--line); border-bottom:0;
  font-weight:600; font-variant-numeric:tabular-nums;
}

/* frozen columns — sticky cells must be opaque or the scrolled content shows through */
.dg-t th.dg-frz, .dg-t td.dg-frz{ position:sticky; left:0; }
.dg-t td.dg-frz{ z-index:5; background:var(--panel); }
.dg-t thead th.dg-frz{ z-index:7; background:var(--panel); }
.dg-t tbody tr.dg-r:hover td.dg-frz{ background:linear-gradient(var(--bg2),var(--bg2)), var(--panel); }
.dg-t tbody tr.dg-selected td.dg-frz{ background:linear-gradient(var(--accent-soft),var(--accent-soft)), var(--panel); }
/* the edge shadow is a box-shadow, not a pseudo-element hanging 10px outside the
   cell: that strip made every frozen cell report scrollWidth = clientWidth + 10,
   which reads as truncation to anything that measures overflow */
.dg-t .dg-frz-last{ box-shadow:10px 0 8px -8px rgba(0,0,0,.09); }
html[data-theme="dark"] .dg-t .dg-frz-last{ box-shadow:10px 0 8px -8px rgba(0,0,0,.55); }
.dg-t th.dg-sel, .dg-t td.dg-sel{ width:34px; padding-left:10px; padding-right:0; text-align:center; }

.dg-cb{ width:14px; height:14px; accent-color:var(--accent); cursor:pointer; vertical-align:middle; }

/* cell value types */
.dg-link{ color:var(--accent); text-decoration:none; cursor:pointer; display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.dg-link:hover{ text-decoration:underline; }
.dg-check{ display:inline-flex; color:var(--green); }
.dg-check svg{ width:15px; height:15px; display:block; }
.dg-acts{ display:inline-flex; gap:2px; justify-content:flex-end; }
/* action cells use the kit's 36px .iconbtn (ui.js) — sized down here so a row with actions keeps
   the 9×12 density instead of growing to 51px (every grid with Edit/Delete had fat rows) */
.dg-acts .dg-iconbtn, .dg-acts .iconbtn{ width:26px; height:26px; border-color:transparent; background:transparent; }
.dg-acts .iconbtn:hover{ background:var(--bg2); border-color:var(--line); transform:none; }
.dg-t td:has(> .dg-acts){ padding-top:2px; padding-bottom:2px; }
.dg-badge{
  display:inline-flex; align-items:center; height:20px; padding:0 9px; border-radius:var(--pill);
  background:var(--bg2); color:var(--muted); border:1px solid var(--line);
  font:600 11px/1 var(--font); letter-spacing:.02em; white-space:nowrap;
}
.dg-badge.t-green{ background:var(--green-soft); color:var(--green); border-color:transparent; }
.dg-badge.t-red{ background:var(--red-soft); color:var(--red); border-color:transparent; }
.dg-badge.t-amber{ background:var(--amber-soft); color:var(--amber); border-color:transparent; }
.dg-badge.t-accent{ background:var(--accent-soft); color:var(--accent); border-color:transparent; }

.dg-pct{ display:flex; align-items:center; gap:8px; justify-content:flex-end; }
.dg-pctbar{ flex:1 1 auto; min-width:34px; max-width:120px; height:6px; border-radius:3px; background:var(--bg2); overflow:hidden; }
.dg-pctfill{ display:block; height:100%; border-radius:3px; background:var(--accent); }
.dg-pctn{ font-variant-numeric:tabular-nums; color:var(--muted); min-width:34px; text-align:right; }

/* empty state */
.dg-empty, .eg .dg-empty{
  display:flex; flex-direction:column; align-items:center; gap:6px;
  padding:44px 20px; color:var(--muted); text-align:center;
}
.dg-empty-ic{ color:var(--faint); }
.dg-empty-ic svg{ width:28px; height:28px; display:block; }
.dg-empty-t{ color:var(--txt); font-size:14px; }
.dg-empty-h{ color:var(--faint); font-size:12px; }

/* pager */
.dg-pager{ display:flex; align-items:center; justify-content:space-between; gap:10px; padding:10px 2px 2px; flex-wrap:wrap; }
.dg-pg-m{ display:flex; align-items:center; gap:4px; }
.dg-pg-r{ display:flex; align-items:center; gap:4px; }
.dg-pg-count{ color:var(--muted); font-variant-numeric:tabular-nums; }
.dg-pg-lab{ color:var(--faint); font:600 11px var(--font); letter-spacing:.06em; text-transform:uppercase; margin-right:2px; }
.dg-pg-gap{ color:var(--faint); padding:0 2px; }
.dg-pill{
  min-width:28px; height:26px; padding:0 10px; border-radius:var(--pill);
  border:1px solid var(--line); background:var(--panel); color:var(--muted);
  font:13px var(--font); cursor:pointer; transition:all var(--t) var(--ease);
}
.dg-pill:hover:not(.dis){ color:var(--txt); background:var(--bg2); }
.dg-pill.on{ background:var(--accent); border-color:var(--accent); color:#fff; }
.dg-pill.dis, .dg-pill:disabled{ opacity:.4; cursor:default; }

/* loading veil */
.dg-loading .dg-scroll{ opacity:.55; pointer-events:none; }

/* fallback modal / button / toast (only used until kit/ui.js lands) */
.dg-modal-back{ position:fixed; inset:0; z-index:120; background:var(--backdrop,rgba(0,0,0,.35)); display:flex; align-items:center; justify-content:center; }
.dg-modal{ width:420px; max-width:92vw; max-height:82vh; overflow:auto; background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-card); box-shadow:var(--shadow-lg); }
.dg-modal.wide{ width:720px; }
.dg-modal-head{ padding:16px 18px 8px; font-size:15px; font-weight:600; }
.dg-modal-body{ padding:4px 18px 8px; color:var(--muted); }
.dg-modal-acts{ display:flex; justify-content:flex-end; gap:8px; padding:12px 18px 16px; }
.dg-btn{ height:32px; padding:0 14px; border-radius:var(--radius-ctl); border:1px solid var(--line); background:var(--panel); color:var(--txt); font:13px var(--font); cursor:pointer; }
.dg-btn:hover{ background:var(--bg2); }
.dg-btn.primary{ background:var(--accent); border-color:var(--accent); color:#fff; }
.dg-btn.primary:hover{ background:var(--accent-hover); }
.dg-btn.danger{ background:var(--red); border-color:var(--red); color:#fff; }
.dg-toast{ position:fixed; left:50%; bottom:26px; transform:translateX(-50%); z-index:200; padding:9px 16px; border-radius:var(--pill); background:var(--panel); border:1px solid var(--line); box-shadow:var(--shadow-lg); }
.dg-toast.t-red{ border-color:var(--red); color:var(--red); }

/* column setup modal list */
.dg-colsetup{ margin-top:8px; border:1px solid var(--line); border-radius:var(--radius-ctl); overflow:hidden; }
.dg-cs-hint{ font-size:12px; color:var(--faint); }
.dg-cs-row{ display:flex; align-items:center; gap:10px; padding:7px 10px; background:var(--panel); border-bottom:1px solid var(--line); cursor:grab; }
.dg-cs-row:last-child{ border-bottom:0; }
.dg-cs-row:hover{ background:var(--bg2); }
.dg-cs-row.dragging{ opacity:.45; }
.dg-cs-row.over{ box-shadow:inset 0 2px 0 var(--accent); }
.dg-cs-drag{ display:flex; color:var(--faint); }
.dg-cs-drag svg{ width:14px; height:14px; display:block; }
.dg-cs-lab{ display:flex; align-items:center; gap:8px; color:var(--txt); cursor:pointer; flex:1; }

/* ============================ editGrid (Excel-grade) ============================ */
.eg-wrap{ position:relative; }
.eg .gridscroll{
  position:relative; overflow:auto; outline:none;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-card);
  max-height:var(--eg-maxh, 62vh);
}
.eg .gridscroll:focus-visible{ box-shadow:0 0 0 3px var(--accent-soft); }
.eg table.grid{ width:100%; border-collapse:separate; border-spacing:0; }

.eg table.grid thead th{
  position:sticky; top:0; z-index:6; box-sizing:border-box; height:var(--dg-headh);
  padding:0 var(--dg-px); text-align:left; white-space:nowrap;
  background:var(--panel); color:var(--muted);
  font:600 11px/1 var(--font); letter-spacing:.06em; text-transform:uppercase;
  border-bottom:1px solid var(--line); user-select:none;
}
.eg table.grid thead th.rn{ left:0; z-index:8; width:46px; padding:0; background:var(--panel); }
.eg table.grid thead th.colsel{ color:var(--txt); background:var(--bg2); }
.eg table.grid thead th.colact{ color:var(--accent); }
.eg .hlab{ display:inline-block; vertical-align:middle; }
.eg .colsort{
  margin-left:5px; width:16px; height:16px; padding:0; vertical-align:middle;
  border:0; background:transparent; color:var(--faint); cursor:pointer; opacity:0;
  display:inline-flex; align-items:center; justify-content:center;
}
.eg table.grid thead th:hover .colsort{ opacity:1; }
.eg .colsort.on{ opacity:1; color:var(--accent); }
.eg .colsort svg{ width:11px; height:11px; display:block; }
.eg .colrz{ position:absolute; top:0; right:-3px; width:7px; height:100%; cursor:col-resize; z-index:2; }
.eg .colrz:hover{ background:var(--accent-soft); }

.eg td.rn{
  position:sticky; left:0; z-index:5; width:46px; text-align:center;
  padding:var(--dg-py) 4px; background:var(--bg2); color:var(--faint);
  font:11px/1 var(--font); font-variant-numeric:tabular-nums;
  border-right:1px solid var(--line); border-bottom:1px solid var(--line);
  cursor:pointer; user-select:none;
}
.eg td.rn:hover{ color:var(--txt); }
.eg td.rn.rnsel{ background:linear-gradient(var(--accent-soft),var(--accent-soft)), var(--bg2); color:var(--txt); }
.eg td.rn.rnact{ color:var(--accent); font-weight:700; }

.eg td.gc{
  position:relative; padding:var(--dg-py) var(--dg-px);
  background:var(--panel); border-bottom:1px solid var(--line); border-right:1px solid var(--line);
  cursor:cell; user-select:none; vertical-align:middle; overflow:hidden;
}
.eg td.gc .cv{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-height:16px; }
.eg td.gc.a-right{ text-align:right; font-variant-numeric:tabular-nums; }
.eg td.gc.a-center{ text-align:center; }
.eg td.gc.ro{ background:var(--bg2); color:var(--muted); cursor:default; }
.eg td.gc .cv.lab{ color:var(--muted); font-weight:600; }
.eg td.gc .cv.sig{ color:var(--txt); font-style:italic; }
.eg tr.inact td.gc, .eg tr.inact td.rn{ opacity:.55; }
.eg tr.inact td.gc .cv{ text-decoration:line-through; text-decoration-color:var(--faint); }
.eg tr.inact td.gc .cv:not(:empty) ~ * { text-decoration:none }
.eg tr.eg-dirty td.rn{ box-shadow:inset 3px 0 0 var(--amber); }

/* selection — the td owns the tint, the .cv never does */
.eg td.gc.sel{ background:linear-gradient(var(--accent-soft),var(--accent-soft)), var(--panel); }
.eg td.gc.active{ z-index:2; box-shadow:inset 0 0 0 2px var(--accent); }
.eg td.gc.fillprev{ background:linear-gradient(var(--accent-soft),var(--accent-soft)), var(--bg2); }

/* frozen columns */
.eg td.gc.frz, .eg thead th.frz{ position:sticky !important; }
.eg td.gc.frz{ z-index:5; background:var(--panel); }
.eg thead th.frz{ z-index:7; }
.eg td.gc.frz.sel{ background:linear-gradient(var(--accent-soft),var(--accent-soft)), var(--panel) !important; }
.eg td.gc.frz.ro{ background:linear-gradient(var(--bg2),var(--bg2)), var(--panel); }
.eg .frz-last{ box-shadow:10px 0 8px -8px rgba(0,0,0,.09); }   /* see .dg-frz-last */
html[data-theme="dark"] .eg .frz-last{ box-shadow:10px 0 8px -8px rgba(0,0,0,.55); }

/* group rows */
.eg tr.grprow td{
  position:sticky; top:var(--dg-headh); z-index:4;
  padding:5px var(--dg-px); background:var(--bg2);
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
}
.eg tr.grprow td.grprn{ left:0; z-index:6; }
.eg .grpname{ font:600 11px/1 var(--font); letter-spacing:.06em; text-transform:uppercase; color:var(--txt); }
.eg .grpn{
  display:inline-flex; align-items:center; height:16px; padding:0 7px; margin-left:8px;
  border-radius:var(--pill); background:var(--panel); border:1px solid var(--line);
  color:var(--muted); font:600 10px/1 var(--font); font-variant-numeric:tabular-nums;
}

/* the single in-cell editor */
.eg .celled{
  position:relative; z-index:3; box-sizing:border-box;
  width:100%; height:100%; min-height:20px; margin:0; padding:0;
  border:0; outline:none; background:var(--panel); color:var(--txt);
  font:13px var(--font);
}
.eg td.gc:has(> .celled){ box-shadow:inset 0 0 0 2px var(--accent); }

/* boolean segmented control */
.eg .seg{ display:inline-flex; gap:3px; }
.eg .segb{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:44px; height:20px; padding:0 9px; border-radius:var(--pill);
  background:var(--bg2); color:var(--muted); border:1px solid transparent;
  font:600 11px/1 var(--font); letter-spacing:.02em; cursor:pointer; white-space:nowrap;
  transition:background var(--t) var(--ease), color var(--t) var(--ease);
}
.eg .segb:hover{ color:var(--txt); }
.eg .segb.on.t-pass{ background:var(--green-soft); color:var(--green); }
.eg .segb.on.t-fail{ background:var(--red-soft); color:var(--red); }
.eg .segb.on.t-na{ background:var(--panel); color:var(--muted); border-color:var(--line); }
.eg td.gc.ro .segb{ cursor:default; opacity:.7; }

/* signature stamp + images */
.eg .egsign{
  display:inline-flex; align-items:center; height:20px; padding:0 10px; border-radius:var(--pill);
  border:1px dashed var(--line); color:var(--faint); font:600 11px/1 var(--font); cursor:pointer;
}
.eg .egsign:hover{ border-color:var(--accent); color:var(--accent); }
.eg .egimg{
  position:relative; display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:22px; border:0; border-radius:var(--radius-ctl);
  background:transparent; color:var(--muted); cursor:pointer;
}
.eg .egimg:hover{ background:var(--bg2); color:var(--accent); }
.eg .egimg svg{ width:15px; height:15px; display:block; }
.eg .egcount{
  position:absolute; top:-3px; right:-4px; min-width:14px; height:14px; padding:0 3px;
  border-radius:var(--pill); background:var(--accent); color:#fff;
  font:700 9px/14px var(--font); text-align:center;
}

/* selection frame, fill handle */
.eg .selbox{ position:absolute; z-index:4; pointer-events:none; border:2px solid var(--accent); border-radius:2px; }
.eg .fillh{
  position:absolute; right:-3px; bottom:-3px; width:6px; height:6px; z-index:5;
  background:var(--accent); border:1px solid var(--panel); border-radius:1px; cursor:crosshair;
}

/* marching ants — per-cell edge borders so the marquee clips inside the scroller
   and tucks UNDER the frozen pane (z 4 < frozen 5), exactly like Excel. */
.eg td.clip{
  background-image:
    linear-gradient(90deg, var(--accent) 50%, transparent 0),
    linear-gradient(90deg, var(--accent) 50%, transparent 0),
    linear-gradient(180deg, var(--accent) 50%, transparent 0),
    linear-gradient(180deg, var(--accent) 50%, transparent 0);
  background-repeat:repeat-x, repeat-x, repeat-y, repeat-y;
  background-size:var(--caT,0 0), var(--caB,0 0), var(--caL,0 0), var(--caR,0 0);
  background-position:0 0, 0 100%, 0 0, 100% 0;
  animation:eg-ants .6s linear infinite;
}
.eg td.clip-t{ --caT:8px 2px; }
.eg td.clip-b{ --caB:8px 2px; }
.eg td.clip-l{ --caL:2px 8px; }
.eg td.clip-r{ --caR:2px 8px; }
@keyframes eg-ants{ to{ background-position:16px 0, -16px 100%, 0 -16px, 100% 16px; } }
@media (prefers-reduced-motion: reduce){ .eg td.clip{ animation:none; } }

/* status strip + row cap banner */
.eg-status{ display:flex; align-items:center; gap:12px; padding:8px 4px 2px; color:var(--muted); font-size:12px; }
.eg-st-dirty{ color:var(--amber); font-weight:600; }
.eg-st-clean{ color:var(--faint); }
.eg-cap{
  margin:0 0 8px; padding:8px 12px; border-radius:var(--radius-ctl);
  background:var(--amber-soft); color:var(--amber); font-size:12px;
}

/* row hover must never compete with the selection tint */
.eg tbody tr:hover td.rn{ background:linear-gradient(var(--bg2),var(--bg2)), var(--bg2); color:var(--txt); }
.eg tbody tr:hover td.gc:not(.sel):not(.ro){ background:var(--bg2); }

/* dataGrid inline editor (editable columns) — one .celled at a time, like the edit grid */
.dg .celled{
  position:relative; z-index:3; box-sizing:border-box; width:100%;
  margin:0; padding:0; border:0; outline:none;
  background:var(--panel); color:var(--txt); font:13px var(--font);
}
.dg td.dg-c:has(> .celled){ box-shadow:inset 0 0 0 2px var(--accent); }
