:root {
  --bg:#f6f7f9;            /* app background */
  --card:#ffffff;          /* white surface / cards */
  --surface:#f2f4f7;       /* low container — inputs, group heads */
  --surface-2:#eceef1;     /* container — hover, chips */
  --line:#e6e8eb;          /* neutral border */
  --brand:#E73C3E;         /* PANTONE 2034 C */
  --brand-dark:#c81e25;    /* hover / active */
  --brand-tint:#ffdad7;    /* light red — chips */
  --text:#191c1e;
  --muted:#5b5f64;
  --radius-card:16px;
  --radius:10px;
  --radius-pill:9999px;
  --shadow:0 4px 12px rgba(27,31,36,.05);
  --shadow-lift:0 8px 24px rgba(27,31,36,.08);
}
* { box-sizing: border-box; }
body { margin:0; font:14px/1.5 'Inter',-apple-system,Segoe UI,Roboto,sans-serif; background:var(--bg); color:var(--text); }
.view.hidden, .app.hidden, .hidden { display:none; }
.error { color:#c0392b; min-height:1em; }
.empty { color:var(--muted); padding:16px; }
.mono { font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace; font-size:13px; }
.strong { font-weight:600; }
.center { text-align:center; }

/* ---- Login ---- */
.login-card { max-width:340px; margin:12vh auto; background:var(--card); padding:32px; border-radius:var(--radius-card); box-shadow:var(--shadow-lift); display:flex; flex-direction:column; gap:14px; }
.login-card h1 { font-size:20px; font-weight:800; margin:0; color:var(--brand); }
.login-sub { margin:-10px 0 4px; font-size:12px; color:var(--muted); }
.login-card label { display:flex; flex-direction:column; gap:4px; font-size:12px; color:var(--muted); }
.login-card input { padding:10px 12px; border:1px solid var(--line); border-radius:var(--radius); font-size:14px; background:var(--surface); }
.login-card input:focus { outline:none; border-color:var(--brand); box-shadow:0 0 0 3px rgba(231,60,62,.15); }
button, .btn { cursor:pointer; border:none; background:var(--brand); color:#fff; padding:9px 16px; border-radius:var(--radius); font:inherit; font-weight:600; text-decoration:none; display:inline-block; transition:background .15s ease, transform .1s ease; }
button:hover:not(:disabled), .btn:hover { background:var(--brand-dark); }
button:active:not(:disabled), .btn:active { transform:scale(.97); }
button.ghost { background:var(--card); color:var(--text); border:1px solid var(--line); }
button.ghost:hover { background:var(--surface); }

/* ---- App shell: left nav drawer + main column, both locked to the viewport ---- */
/* The whole app is exactly one viewport tall and never scrolls as a document — the grid owns
   its own scrolling (see .grid-scroll). That is what lets the table header stay put. */
.app { display:flex; flex-direction:row; height:100vh; overflow:hidden; }

/* ---- Left nav drawer ---- */
/* A navigation shell (Kent, 2026-08-06): brand + identity on top, page list in the middle,
   log out at the bottom. Only one page exists today; new ones slot into .nav-list.
   Collapsing it to 64px buys the grid ~190px of width, which matters at 16 columns. */
.sidebar { width:248px; flex:0 0 248px; background:var(--card); border-right:1px solid var(--line); display:flex; flex-direction:column; overflow:hidden; transition:width .18s ease, flex-basis .18s ease; }
.app.nav-collapsed .sidebar { width:64px; flex-basis:64px; }
.nav-head { display:flex; align-items:center; gap:12px; padding:14px 16px; height:64px; border-bottom:1px solid var(--line); min-width:0; }
.brand-mark { width:36px; height:36px; flex:0 0 36px; background:var(--brand); border-radius:var(--radius); display:flex; align-items:center; justify-content:center; }
.brand-text { display:flex; flex-direction:column; line-height:1.15; min-width:0; }
.brand-name { font-weight:800; font-size:16px; color:var(--brand); white-space:nowrap; }
.brand-sub { font-size:11px; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.nav-list { flex:1 1 auto; overflow-y:auto; padding:12px 10px; display:flex; flex-direction:column; gap:4px; }
.nav-item { display:flex; align-items:center; gap:12px; width:100%; padding:10px 12px; border-radius:var(--radius); background:transparent; color:var(--muted); font-weight:600; font-size:13px; text-align:left; white-space:nowrap; }
.nav-item:hover:not(:disabled) { background:var(--surface); color:var(--text); }
.nav-item.active { background:var(--brand-tint); color:var(--brand); }
.nav-item.active:hover { background:var(--brand-tint); }
.nav-item .nav-icon { flex:0 0 18px; width:18px; text-align:center; font-size:15px; line-height:1; }
.nav-item .nav-count { margin-left:auto; font-size:11px; font-weight:600; opacity:.75; }
.nav-hint { padding:10px 22px; font-size:11px; color:var(--muted); opacity:.6; font-style:italic; }
.nav-foot { border-top:1px solid var(--line); padding:12px 10px; }
.nav-foot .nav-item { color:var(--muted); }
/* Collapsed: keep only the icons, hide every text run. */
.app.nav-collapsed .brand-text,
.app.nav-collapsed .nav-item .nav-label,
.app.nav-collapsed .nav-item .nav-count,
.app.nav-collapsed .nav-hint { display:none; }
.app.nav-collapsed .nav-item { justify-content:center; padding:10px 0; }
.app.nav-collapsed .nav-head { padding:14px 0; justify-content:center; }

/* ---- Main column ---- */
/* min-width:0 is load-bearing: without it this flex child refuses to shrink below the width of
   the 2175px table and the whole page scrolls sideways instead of the grid. */
.main-col { flex:1 1 auto; min-width:0; display:flex; flex-direction:column; overflow:hidden; }
.topbar { display:flex; justify-content:space-between; align-items:center; gap:16px; padding:0 20px; height:64px; flex:0 0 64px; background:var(--card); border-bottom:1px solid var(--line); z-index:5; }
.topbar-left { display:flex; align-items:center; gap:12px; min-width:0; }
.page-title { font-weight:700; font-size:15px; white-space:nowrap; }
.page-meta { font-size:12px; color:var(--muted); white-space:nowrap; }
.nav-toggle { background:var(--card); color:var(--muted); border:1px solid var(--line); padding:7px 11px; border-radius:var(--radius); font-size:14px; line-height:1; }
.nav-toggle:hover { background:var(--surface); color:var(--text); }
.controls { display:flex; gap:8px; align-items:center; }
.controls input { padding:8px 14px; border:1px solid var(--line); border-radius:var(--radius-pill); font:inherit; font-size:13px; background:var(--surface); color:var(--text); min-width:260px; }
.controls input:focus { outline:none; border-color:var(--brand); box-shadow:0 0 0 3px rgba(231,60,62,.15); }
.controls button { border-radius:var(--radius-pill); }
main { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }

/* ---- Grid ---- */
/* 🔴 ONE table for every group, not one per group.
   Groups used to render as separate <table>s, each auto-sized and each in its own overflow
   container. At 16 columns that broke the grid three ways: every group computed different
   column widths (CLIENT NAME came out 325 / 272 / 200px), each group scrolled sideways on its
   own and by a different amount, and the sticky header never stuck because its scroll container
   had no height. A single fixed-layout table inside a single scroller fixes all three — group
   headers are now rows in that same table (see tr.group-row). */
.grid-scroll { flex:1 1 auto; min-height:0; overflow:auto; background:var(--card); border-top:1px solid var(--line); }
/* The pixel width comes from the renderer (TABLE_WIDTH = sum of the column spec); min-width
   makes it fill a wider screen instead of leaving dead space on the right. */
table.grid { border-collapse:separate; border-spacing:0; font-size:13px; table-layout:fixed; min-width:100%; }
table.grid th, table.grid td { text-align:left; padding:10px 14px; border-bottom:1px solid var(--line); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; background:var(--card); }
table.grid thead th { position:sticky; top:0; z-index:3; background:#fafbfc; color:var(--muted); font-weight:600; font-size:12px; text-transform:uppercase; letter-spacing:.02em; }
/* First column frozen: at 2175px of columns you lose track of which submission a row is
   without it. z-index tiers: header-corner 4 > header 3 > frozen body cell 2 > body 1. */
table.grid th.freeze, table.grid td.freeze { position:sticky; left:0; z-index:2; box-shadow:1px 0 0 var(--line); }
table.grid thead th.freeze { z-index:4; }
table.grid tbody tr:hover td { background:#fdecec; }
.badge { display:inline-block; max-width:100%; overflow:hidden; text-overflow:ellipsis; vertical-align:bottom; font-size:11px; padding:2px 8px; border-radius:999px; background:var(--brand-tint); color:var(--brand); }

/* ---- Group header rows (inside the single table) ---- */
/* 🔴 The sticky-left goes on the BUTTON, not on the colspan-16 <td>. That td is as wide as the
   whole table (2250px), so it has no room to slide and `position:sticky` on it does nothing —
   scrolling sideways left an empty grey band with the label cut off outside the viewport. The
   button is inline-flex and content-sized, so it can actually stick to the left edge. */
/* overflow must stay visible here: the generic `td { overflow:hidden }` (which gives the data
   cells their ellipsis) would make this cell the sticky button's scroll container, so the label
   would neither move nor escape the cell — the symptom was an empty grey band once scrolled. */
tr.group-row td { padding:0; overflow:visible; background:var(--surface); border-bottom:1px solid var(--line); border-top:1px solid var(--line); }
tr.group-row .s2-group-head { position:sticky; left:0; z-index:2; display:inline-flex; align-items:center; gap:8px; background:var(--surface); color:var(--text); padding:9px 14px; font-weight:700; font-size:13px; border-radius:0; }
tr.group-row .s2-group-head:hover { background:var(--surface-2); text-decoration:none; }
tr.group-row:hover td { background:var(--surface-2); }
.s2-group-head .caret { color:var(--muted); width:12px; font-size:11px; }
.s2-group-head .s2-group-count { font-size:11px; background:var(--brand-tint); color:var(--brand); padding:2px 8px; border-radius:999px; }

.grid-foot { flex:0 0 auto; display:flex; align-items:center; justify-content:space-between; gap:12px; padding:8px 20px; border-top:1px solid var(--line); background:var(--card); }
.grid-foot .empty { padding:0; }

/* ---- Editable cells ---- */
/* Only the eight fields Kent opened up carry .edit, and the affordance stays quiet (his call,
   2026-08-06 — keep the caret, drop the shading):
     · single-selects get a permanent ▾ caret, which is the whole signal for them;
     · typed values (remark / amount / date) get a dashed underline, since they have no caret;
     · a hover border, visible only under the cursor.
   No tinted background: eight of sixteen columns are writable, so shading them striped the grid.
   Empty cells render genuinely empty — no dash, no placeholder text. */
td.edit { cursor:pointer; position:relative; }
td.edit:hover { box-shadow:inset 0 0 0 2px var(--brand); }
td.edit .cell-val { border-bottom:1px dashed #c3cad3; }
td.edit:hover .cell-val { border-bottom-color:var(--brand); }
/* Nothing to underline in an empty cell — an underline alone would look like a stray mark. */
td.edit .cell-val.empty { border-bottom:none; }
/* An underline under a coloured chip just looks like a stray piece of the chip; selects carry
   the caret instead. */
td.edit.sel .cell-val { border-bottom:none; }
td.edit .cell-val .badge { border-bottom:none; }
/* The dropdown caret — the single-select signal Kent asked to keep. */
td.edit.sel { padding-right:26px; }
td.edit.sel .caret-sel { position:absolute; right:8px; top:50%; transform:translateY(-50%); color:#9aa1aa; font-size:11px; pointer-events:none; }
td.edit.sel:hover .caret-sel { color:var(--brand); }
td.edit.check-cell { cursor:pointer; }
td.edit.saving { opacity:.5; pointer-events:none; }
td.edit.saved { animation:flash-ok .7s ease; }
td.edit.failed { animation:flash-bad 1.1s ease; }
/* Spinner arrows off on the currency editor (Kent, 2026-08-06). type=number is kept for the
   numeric keypad on mobile and the browser's own validation. */
.cell-input[type=number]::-webkit-outer-spin-button,
.cell-input[type=number]::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }
.cell-input[type=number] { -moz-appearance:textfield; appearance:textfield; }
@keyframes flash-ok { 0%,60% { background:#d1f7c4; } 100% { background:transparent; } }
@keyframes flash-bad { 0%,70% { background:#ffdce5; } 100% { background:transparent; } }
/* In-cell editors: sized to the cell so the grid never reflows while editing. */
.cell-input { width:100%; font:inherit; font-size:13px; padding:4px 6px; border:1px solid var(--brand); border-radius:6px; background:var(--card); color:var(--text); outline:none; }
select.cell-input { cursor:pointer; }
/* The remark editor is a <textarea> — the field is Airtable long text and an <input> would strip
   the newlines out of it. It grows the row while open, which is the honest thing to do for
   multi-line content; ⌘/Ctrl+Enter or clicking away commits. */
textarea.cell-input.multi { display:block; min-height:78px; line-height:1.45; resize:vertical; }
td.check-cell { cursor:pointer; }
td.check-cell input { cursor:pointer; width:15px; height:15px; accent-color:var(--brand); }

/* Expand affordance — a button in the frozen first column, Airtable-style. */
td.freeze .expand-btn { float:right; visibility:hidden; background:var(--surface); color:var(--muted); border:1px solid var(--line); border-radius:6px; padding:1px 7px; font-size:12px; line-height:1.4; }
tr:hover td.freeze .expand-btn { visibility:visible; }
td.freeze .expand-btn:hover { background:var(--brand); color:#fff; border-color:var(--brand); }

/* ---- Expand panel (modal, like Airtable's expanded record) ---- */
.modal-back { position:fixed; inset:0; background:rgba(20,22,26,.45); z-index:40; display:flex; align-items:flex-start; justify-content:center; padding:40px 16px; overflow:auto; }
.modal-card { background:var(--card); width:min(880px,100%); border-radius:16px; box-shadow:0 18px 60px rgba(0,0,0,.28); overflow:hidden; }
.modal-head { display:flex; align-items:center; justify-content:space-between; gap:16px; padding:18px 24px; border-bottom:1px solid var(--line); }
.modal-head .sub-id { font-family:'JetBrains Mono',ui-monospace,monospace; font-size:19px; font-weight:700; color:var(--text); }
.modal-head .sub-sub { font-size:12px; color:var(--muted); margin-top:2px; }
.modal-close { background:var(--surface); color:var(--muted); border:1px solid var(--line); border-radius:8px; padding:6px 12px; font-size:14px; }
.modal-close:hover { background:var(--brand); color:#fff; border-color:var(--brand); }
.modal-body { padding:22px 24px 26px; display:flex; flex-direction:column; gap:18px; }
.fld { display:flex; flex-direction:column; gap:6px; min-width:0; }
.fld > label, .fld > .fld-label { font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); }
.fld .ro { font-size:14px; color:var(--text); word-break:break-word; }
.fld-pair { display:grid; grid-template-columns:1fr 1fr; gap:18px 24px; align-items:start; }
.fld-col { display:flex; flex-direction:column; gap:18px; min-width:0; }
/* White field on a tinted border reads as "you can type/pick here"; the read-only blocks above
   (LPCR data, documents) stay as plain text on the card, so the difference is obvious without
   labelling anything "editable". */
.fld input.f-in, .fld select.f-in, .fld textarea.f-in { width:100%; font:inherit; font-size:14px; padding:9px 11px; border:1.5px solid #cdd5e2; border-radius:var(--radius); background:var(--card); color:var(--text); cursor:pointer; }
.fld textarea.f-in { cursor:text; }
.fld .f-in:hover { border-color:#9fb0cc; }
.fld textarea.f-in { min-height:120px; resize:vertical; line-height:1.5; }
.fld .f-in:focus { outline:none; border-color:var(--brand); box-shadow:0 0 0 3px rgba(231,60,62,.15); background:var(--card); }
.fld.saving { opacity:.55; }
.fld.saved > label, .fld.saved > .fld-label { color:#338a17; }
.fld.failed > label, .fld.failed > .fld-label { color:#c0392b; }
.chk-row { display:flex; align-items:center; gap:9px; padding:9px 0; }
.chk-row input { width:18px; height:18px; accent-color:var(--brand); cursor:pointer; }
.chk-row span { font-size:14px; }
/* Attachments + linked records */
.att-list, .link-list { display:flex; flex-wrap:wrap; gap:8px; }
.att, .lnk { display:inline-flex; align-items:center; gap:7px; padding:7px 12px; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); font-size:13px; color:var(--text); text-decoration:none; max-width:100%; }
.att:hover { border-color:var(--brand); color:var(--brand); }
.att .att-size { color:var(--muted); font-size:11px; }
.att-thumb { width:26px; height:26px; object-fit:cover; border-radius:4px; flex:0 0 26px; }
.none { color:var(--muted); font-size:13px; font-style:italic; }
@media (max-width:720px){ .fld-pair { grid-template-columns:1fr; } .modal-back { padding:12px 8px; } }
.app-version { font-size:11px; color:var(--muted); opacity:.7; font-family:'JetBrains Mono', monospace; }

.toast { position:fixed; bottom:18px; left:50%; transform:translateX(-50%); background:#1b1f24; color:#fff; padding:10px 16px; border-radius:8px; opacity:0; transition:opacity .2s; z-index:30; }
.toast.show { opacity:1; }

@media (max-width:720px){
  /* Narrow screens: the drawer overlays the grid instead of eating its width, and starts
     collapsed to icons. The topbar keeps its fixed 64px — .main-col is a flex column whose
     height budget the grid depends on, so it must not grow here. */
  .sidebar { position:fixed; top:0; left:0; bottom:0; z-index:20; box-shadow:var(--shadow-lift); }
  .app:not(.nav-collapsed) .sidebar { width:248px; flex-basis:248px; }
  .main-col { margin-left:64px; }
  .page-meta, .page-title { display:none; }
  .controls input { min-width:0; flex:1; }
  .topbar { padding:0 12px; gap:8px; }
}
