/* ============================================================
   Factory ERP design system (from scratch)
   Dense, calm, industrial. Light and dark from one token set.
   ============================================================ */

:root {
  /* Neutrals: warm stone */
  --bg:            #f4f4f2;
  --bg-raised:     #ffffff;
  --bg-sunken:     #ecece9;
  --surface:       #ffffff;
  --border:        #dcdcd7;
  --border-strong: #c6c6bf;
  --text:          #24241f;
  --text-soft:     #5b5b53;
  --text-faint:    #8b8b81;

  /* Brand: deep teal */
  --accent:        #0f766e;
  --accent-strong: #0b5d57;
  --accent-soft:   #e2f1ef;
  --accent-text:   #ffffff;

  /* Status */
  --ok:        #15803d;  --ok-soft:     #e3f2e7;
  --warn:      #b45309;  --warn-soft:   #fdf0dd;
  --danger:    #b91c1c;  --danger-soft: #fdeaea;
  --info:      #1d4ed8;  --info-soft:   #e7edfd;

  --shadow-sm: 0 1px 2px rgba(30, 30, 20, .06);
  --shadow-md: 0 4px 16px rgba(30, 30, 20, .10), 0 1px 3px rgba(30,30,20,.07);
  --shadow-lg: 0 18px 50px rgba(30, 30, 20, .22);

  --r-sm: 6px; --r-md: 10px; --r-lg: 14px;
  --sidebar-w: 228px;
  --topbar-h: 52px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
}

/* The design system is px-sized and tuned for ~1400-1700px viewports (the
   factory office laptops). On big monitors the same layout renders tiny with
   dead margins, and users compensate with browser zoom — so do it for them:
   step the root zoom so the EFFECTIVE width always lands back around 1600px.
   Media queries evaluate against the unzoomed viewport, so this can't loop.
   (Firefox < 126 ignores zoom and simply stays unscaled — harmless.)
   Unlike browser zoom, CSS zoom does NOT shrink the viewport, so vh/vw
   lengths render zoom× too large; every viewport-unit rule below divides by
   --zoom to land back on the real viewport. Keep the two in lockstep. */
:root { --zoom: 1; }
@media (min-width: 2000px) { html { zoom: 1.25; } :root { --zoom: 1.25; } }
@media (min-width: 2400px) { html { zoom: 1.5; }  :root { --zoom: 1.5; } }
@media (min-width: 2800px) { html { zoom: 1.75; } :root { --zoom: 1.75; } }
@media (min-width: 3200px) { html { zoom: 2; }    :root { --zoom: 2; } }

[data-theme="dark"] {
  --bg:            #16181a;
  --bg-raised:     #1e2124;
  --bg-sunken:     #101214;
  --surface:       #1e2124;
  --border:        #30343a;
  --border-strong: #40454d;
  --text:          #e8e8e4;
  --text-soft:     #a3a49c;
  --text-faint:    #71726b;

  --accent:        #2bb3a3;
  --accent-strong: #43cdbd;
  --accent-soft:   #14332f;
  --accent-text:   #06211e;

  --ok:      #4ade80;  --ok-soft:     #143221;
  --warn:    #fbbf24;  --warn-soft:   #362a10;
  --danger:  #f87171;  --danger-soft: #3b1a1a;
  --info:    #93b4f8;  --info-soft:   #1a2440;

  --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --shadow-md: 0 4px 16px rgba(0,0,0,.5);
  --shadow-lg: 0 18px 50px rgba(0,0,0,.6);
}

/* ---------- accent presets (picked in the Account dialog) ---------- */

[data-accent="ocean"] {
  --accent: #1d4ed8; --accent-strong: #1e40af; --accent-soft: #e4ebfc; --accent-text: #ffffff;
}
[data-theme="dark"][data-accent="ocean"] {
  --accent: #7aa5f8; --accent-strong: #a3c0fa; --accent-soft: #16233f; --accent-text: #0a1226;
}
[data-accent="violet"] {
  --accent: #6d28d9; --accent-strong: #5b21b6; --accent-soft: #efe8fc; --accent-text: #ffffff;
}
[data-theme="dark"][data-accent="violet"] {
  --accent: #b195f5; --accent-strong: #c7b2f8; --accent-soft: #251740; --accent-text: #150a2e;
}
[data-accent="magenta"] {
  --accent: #be185d; --accent-strong: #9d174d; --accent-soft: #fbe7f0; --accent-text: #ffffff;
}
[data-theme="dark"][data-accent="magenta"] {
  --accent: #f27ab0; --accent-strong: #f5a3c6; --accent-soft: #3b1226; --accent-text: #2a0a18;
}
[data-accent="ember"] {
  --accent: #c2410c; --accent-strong: #9a3412; --accent-soft: #fcece2; --accent-text: #ffffff;
}
[data-theme="dark"][data-accent="ember"] {
  --accent: #f59e6c; --accent-strong: #f8bd97; --accent-soft: #3a1d0d; --accent-text: #2a1204;
}
[data-accent="forest"] {
  --accent: #15803d; --accent-strong: #166534; --accent-soft: #e4f2e8; --accent-text: #ffffff;
}
[data-theme="dark"][data-accent="forest"] {
  --accent: #5fce8a; --accent-strong: #8adcaa; --accent-soft: #12301d; --accent-text: #06210f;
}

.accent-dots { display: flex; gap: 10px; }
.accent-dot {
  width: 28px; height: 28px; border-radius: 50%;
  border: 2px solid var(--border-strong);
  cursor: pointer; padding: 0;
}
.accent-dot.sel { border-color: var(--text); box-shadow: 0 0 0 2px var(--bg-raised), 0 0 0 4px var(--text); }
.accent-dot[data-accent="teal"]    { background: #0f766e; }
.accent-dot[data-accent="ocean"]   { background: #1d4ed8; }
.accent-dot[data-accent="violet"]  { background: #6d28d9; }
.accent-dot[data-accent="magenta"] { background: #be185d; }
.accent-dot[data-accent="ember"]   { background: #c2410c; }
.accent-dot[data-accent="forest"]  { background: #15803d; }

/* ---------- base ---------- */

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -.01em; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
::selection { background: color-mix(in srgb, var(--accent) 25%, transparent); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-radius: var(--r-sm);
}

/* ---------- app shell ---------- */

.app-root { height: 100%; }
/* minmax(0, 1fr) pins the single row to the shell's height: an implicit
   auto row sizes to CONTENT, so a tall page (a long chat, a big grid)
   would grow the row straight past the fixed shell and hand the overflow
   to the document instead of .content's own scrollbar. */
.shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; grid-template-rows: minmax(0, 1fr); height: calc(100vh / var(--zoom)); }

.sidebar {
  background: var(--bg-raised);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  overflow-y: auto;
}
.brand {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px 12px;
  border-bottom: 1px solid var(--border);
}
.brand img, .brand svg { width: 30px; height: 30px; border-radius: 8px; }
/* The name is a full company name — keep it a touch smaller and let it wrap
   snugly (with the TEST chip it can need two lines). */
.brand .brand-name { font-weight: 700; font-size: 13.5px; letter-spacing: -.01em; line-height: 1.25; }

.nav { padding: 10px 8px 20px; flex: 1; }
.nav-group { margin-top: 14px; }
.nav-group:first-child { margin-top: 4px; }
.nav-group-title {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-faint);
  padding: 0 10px 5px;
}
.nav-item {
  display: flex; align-items: center; gap: 9px;
  width: 100%; text-align: left;
  padding: 6.5px 10px;
  border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--text-soft);
  font: inherit; font-size: 13px; font-weight: 500;
  cursor: pointer;
}
.nav-item svg { width: 16px; height: 16px; flex: none; opacity: .75; }
.nav-item:hover { background: var(--bg-sunken); color: var(--text); }
.nav-item.active {
  background: var(--accent-soft); color: var(--accent);
  font-weight: 600;
}
.nav-item.active svg { opacity: 1; }

.main { display: flex; flex-direction: column; min-width: 0; }
.topbar {
  height: var(--topbar-h); flex: none;
  display: flex; align-items: center; gap: 12px;
  padding: 0 18px;
  background: var(--bg-raised);
  border-bottom: 1px solid var(--border);
}
.topbar .page-title { font-size: 15px; font-weight: 650; }
.topbar .spacer { flex: 1; }
.userchip {
  display: flex; align-items: center; gap: 8px;
  white-space: nowrap;
  padding: 4px 10px 4px 4px; border-radius: 99px;
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer; font: inherit; font-size: 12.5px; color: var(--text-soft);
}
.userchip .avatar {
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: var(--accent-text);
  font-size: 11px; font-weight: 700;
}
.rolepill {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: 2px 7px; border-radius: 99px;
  background: var(--accent-soft); color: var(--accent);
}

.hamburger { display: none; }

/* min-height: 0 makes .content the page's real scroller: without it the
   flex minimum (auto = content size) lets tall pages GROW the column and
   push the overflow out to the document — the topbar scrolls away, and the
   chat page's height:100% chain silently breaks. */
.content { flex: 1; overflow: auto; padding: 18px; min-height: 0; }
.content-inner { max-width: 1500px; margin: 0 auto; display: flex; flex-direction: column; gap: 14px; }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text);
  font: inherit; font-size: 12.5px; font-weight: 600;
  cursor: pointer; white-space: nowrap;
  box-shadow: var(--shadow-sm);
}
.btn svg { width: 14px; height: 14px; }
.btn:hover { background: var(--bg-sunken); }
.btn:active { transform: translateY(.5px); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.btn.primary:hover { background: var(--accent-strong); border-color: var(--accent-strong); }
.btn.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--border-strong)); }
.btn.danger:hover { background: var(--danger-soft); }
.btn.ghost { border-color: transparent; background: transparent; box-shadow: none; color: var(--text-soft); }
.btn.ghost:hover { background: var(--bg-sunken); color: var(--text); }
.btn.small { padding: 3.5px 8px; font-size: 12px; }

.icon-btn {
  display: inline-grid; place-items: center;
  width: 28px; height: 28px; border-radius: var(--r-sm);
  border: 0; background: transparent; color: var(--text-soft); cursor: pointer;
}
.icon-btn:hover { background: var(--bg-sunken); color: var(--text); }
/* Two icon buttons in one grid cell (a document's PDF and dot-matrix prints). */
.cell-actions { display: inline-flex; gap: 2px; }
.icon-btn:disabled { opacity: 0.35; pointer-events: none; }
.icon-btn svg { width: 15px; height: 15px; }

/* ---------- forms ---------- */

.field { display: flex; flex-direction: column; gap: 4px; }
.field > label { font-size: 11.5px; font-weight: 650; color: var(--text-soft); }
.field .req { color: var(--danger); }
.input, select.input, textarea.input {
  font: inherit; font-size: 13px;
  color: var(--text);
  background: var(--bg-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  padding: 6px 9px;
  width: 100%;
}
.input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 60%, transparent); outline-offset: 0; border-color: var(--accent); }
.input[readonly] { background: var(--bg-sunken); color: var(--text-soft); }
.input.num { text-align: right; font-variant-numeric: tabular-nums; }
textarea.input { resize: vertical; min-height: 56px; }
.checkbox-line { display: flex; align-items: center; gap: 8px; font-size: 13px; padding: 4px 0; }
.checkbox-line input { width: 15px; height: 15px; accent-color: var(--accent); }

.combo { position: relative; }
.combo .input { padding-right: 30px; }
.combo-clear {
  position: absolute; top: 50%; right: 5px; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; border: 0; border-radius: var(--r-sm);
  background: none; color: var(--text-faint); cursor: pointer;
}
.combo-clear:hover { color: var(--text); background: var(--bg-sunken); }
.combo-clear svg { width: 13px; height: 13px; }
.combo .input:placeholder-shown + .combo-clear { display: none; }
.combo-list {
  position: absolute; z-index: 60; left: 0; right: 0; top: calc(100% + 3px);
  background: var(--bg-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  max-height: 260px; overflow: auto;
  padding: 4px;
}
.combo-item { padding: 6px 8px; border-radius: var(--r-sm); cursor: pointer; font-size: 12.5px; }
.combo-item:hover, .combo-item.hi { background: var(--accent-soft); color: var(--accent); }
.combo-item .sub { font-size: 11px; color: var(--text-faint); }
.combo-item.hi .sub { color: inherit; opacity: .75; }

/* ---------- cards, tiles ---------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.card .card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  font-weight: 650; font-size: 13.5px;
}
.card .card-body { padding: 14px 16px; }

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 13px 15px;
  box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column;
  min-height: 88px;
}
.tile .tile-label { font-size: 11.5px; font-weight: 650; color: var(--text-soft); }
.tile .tile-value { font-size: 24px; font-weight: 700; letter-spacing: -.02em; margin-top: auto; font-variant-numeric: tabular-nums; }
.tile.alert .tile-value { color: var(--danger); }
.tile.good .tile-value { color: var(--ok); }

/* ---------- badges ---------- */

.badge {
  display: inline-block;
  font-size: 11px; font-weight: 700;
  padding: 2px 8px; border-radius: 99px;
  background: var(--bg-sunken); color: var(--text-soft);
}
.badge.ok     { background: var(--ok-soft); color: var(--ok); }
.badge.warn   { background: var(--warn-soft); color: var(--warn); }
.badge.danger { background: var(--danger-soft); color: var(--danger); }
.badge.info   { background: var(--info-soft); color: var(--info); }
.badge.accent { background: var(--accent-soft); color: var(--accent); }

/* ---------- data grid ---------- */

.grid { display: flex; flex-direction: column; min-height: 0; }
.grid-toolbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}
.grid-toolbar .sep { width: 1px; height: 20px; background: var(--border); margin: 0 2px; }
.grid-toolbar .spacer { flex: 1; }
.searchbox { position: relative; }
.searchbox input {
  font: inherit; font-size: 12.5px;
  padding: 5.5px 9px 5.5px 28px;
  border: 1px solid var(--border-strong);
  border-radius: 99px;
  background: var(--bg);
  color: var(--text);
  width: 210px;
}
.searchbox svg {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  width: 13px; height: 13px; color: var(--text-faint); pointer-events: none;
}

.table-scroll { overflow: auto; }
/* Bare LIST pages put the grid straight into .content-inner: there the grid
   is the scroller (viewport cap, so the toolbar and pager stay put).
   Everywhere else — stacked document pages (WO tabs, SO/PO line cards,
   dashboard) — the grid grows with its rows and the PAGE is the one
   vertical scroller, never a second nested one (2026-07-28 report: double
   scroll on the WO page's BOM tab). */
.content-inner > .grid .table-scroll { max-height: calc(100vh / var(--zoom) - 285px); }
.grid.fill .table-scroll { max-height: none; flex: 1; }

/* Detail pages whose line grid FITS the viewport instead of growing the page
   (material/supplier — a price list can run hundreds of rows): the flex
   chain hands the leftover height to the grid card, and the grid's own
   .fill mode (table-scroll flex:1, sticky headers) scrolls the rows
   internally, so .content never grows a page scrollbar. */
.content-inner.page-fill { height: 100%; }
/* The header cards keep their natural height — only the grid gives way
   (and never below a usable strip; a too-short window falls back to the
   normal page scroll). */
.content-inner.page-fill > :not(.card-fill) { flex-shrink: 0; }
.content-inner.page-fill > .card-fill {
  flex: 1; min-height: 160px;
  display: flex; flex-direction: column;
}
.card-fill > .grid { flex: 1; min-height: 0; }
/* Tabbed fill (the WO page): the tab strip keeps its height, the active
   grid takes the rest — the same internal row scroll as every other fill
   page. */
.card-fill > .tab-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.tab-body > .grid { flex: 1; min-height: 0; }
table.dt { border-collapse: separate; border-spacing: 0; width: 100%; font-size: 12.5px; }
table.dt th {
  position: sticky; top: 0; z-index: 5;
  text-align: left;
  background: var(--bg-sunken);
  color: var(--text-soft);
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  padding: 7px 10px;
  border-bottom: 1px solid var(--border-strong);
  white-space: nowrap;
  user-select: none;
}
table.dt th.sortable { cursor: pointer; }
table.dt th.sortable:hover { color: var(--text); }
table.dt th .arrow { font-size: 9px; margin-left: 3px; }
table.dt td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  max-width: 340px; overflow: hidden; text-overflow: ellipsis;
}
table.dt td.num, table.dt th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.dt td.neg { color: var(--danger); font-weight: 650; }
table.dt tbody tr { cursor: default; }
table.dt tbody tr:hover td { background: color-mix(in srgb, var(--accent) 5%, transparent); }
table.dt tbody tr.selected td { background: var(--accent-soft); }
table.dt tbody tr.clickable { cursor: pointer; }
table.dt tbody tr:last-child td { border-bottom: 0; }
table.dt .checkcell { width: 30px; text-align: center; }
table.dt .checkcell input { accent-color: var(--accent); }

.grid-foot {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  border-top: 1px solid var(--border);
  font-size: 12px; color: var(--text-soft);
}
.grid-foot .spacer { flex: 1; }
.pager { display: flex; align-items: center; gap: 4px; }
.pager button {
  border: 1px solid var(--border-strong); background: var(--surface);
  color: var(--text-soft);
  border-radius: var(--r-sm); padding: 3px 8px; font: inherit; font-size: 12px; cursor: pointer;
}
.pager button:disabled { opacity: .4; cursor: default; }
.pager .page-now { font-weight: 700; color: var(--text); padding: 0 6px; }
.grid-foot select.page-size {
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-soft);
  border-radius: var(--r-sm); padding: 3px 6px; font: inherit; font-size: 12px; cursor: pointer;
}
.grid-foot input.jump {
  width: 64px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  border-radius: var(--r-sm); padding: 3px 8px; font: inherit; font-size: 12px;
}
/* row highlighted after "jump to row" */
@keyframes rowflash { from { background: var(--accent-soft); } to { background: transparent; } }
table.dt tbody tr.flash td { animation: rowflash 1.6s ease-out; }
/* refresh in progress: dim the rows, spin the reload icon */
.grid.busy table.dt { opacity: .45; transition: opacity .15s; }
.grid.busy .grid-refresh svg,
.grid .grid-refresh.spin svg { animation: spin .7s linear infinite; }

.empty {
  padding: 40px 20px; text-align: center; color: var(--text-faint); font-size: 13px;
}

/* ---------- drawer / modal / toast ---------- */

.scrim {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(15, 15, 10, .40);
  backdrop-filter: blur(1.5px);
}
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 95;
  /* 540: the widest edit-drawer footer (History/Delete/Duplicate/Cancel/Save)
     measures 501px incl. paddings — anything tighter clips or wraps it. */
  width: min(540px, calc(96vw / var(--zoom)));
  background: var(--bg-raised);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  animation: slidein .18s ease-out;
}
@keyframes slidein { from { transform: translateX(30px); opacity: .4; } to { transform: none; opacity: 1; } }
.drawer-head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  font-weight: 650; font-size: 14px;
}
.drawer-head .spacer { flex: 1; }
.drawer-body { flex: 1; overflow-y: auto; padding: 16px 18px; display: flex; flex-direction: column; gap: 12px; }
.drawer-body .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.drawer-foot {
  /* wrap, don't clip: with flex-end, an overflowing row spills off the LEFT
     edge (it cut off the History button at 460px — the five buttons measure
     ~487px in English) */
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end;
  padding: 12px 18px;
  border-top: 1px solid var(--border);
  background: var(--bg);
  border-bottom-left-radius: 0;
}

.modal-wrap {
  position: fixed; inset: 0; z-index: 95;
  display: grid; place-items: center; padding: 20px;
  outline: none; /* focused programmatically so Esc addresses the dialog */
}
.modal {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  width: 100%; max-width: 480px;
  max-height: calc(86vh / var(--zoom)); display: flex; flex-direction: column;
  animation: pop .16s ease-out;
}
.modal.wide { max-width: 860px; }
.modal.danger .modal-head { color: var(--danger); }
.modal-danger-title { display: inline-flex; align-items: center; gap: 7px; }
.modal-danger-title svg { width: 17px; height: 17px; flex: none; }
@keyframes pop { from { transform: scale(.97); opacity: .5; } to { transform: none; opacity: 1; } }
.modal-head { padding: 14px 18px; border-bottom: 1px solid var(--border); font-weight: 650; display: flex; align-items: center; }
.modal-head .spacer { flex: 1; }
.modal-body { padding: 16px 18px; overflow-y: auto; }
.modal-foot { padding: 12px 18px; border-top: 1px solid var(--border); display: flex; gap: 8px; justify-content: flex-end; }

.toasts {
  position: fixed; top: 14px; right: 14px; z-index: 120;
  display: flex; flex-direction: column; gap: 8px;
}
.toast {
  background: var(--bg-raised);
  color: var(--text);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  padding: 10px 14px;
  font-size: 12.5px; font-weight: 550;
  max-width: 360px;
  animation: pop .16s ease-out;
}
.toast.error { border-left-color: var(--danger); }
.toast.ok { border-left-color: var(--ok); }

/* ---------- login ---------- */

.login-wrap {
  min-height: calc(100vh / var(--zoom));
  display: grid; place-items: center;
  padding: 24px;
  background:
    radial-gradient(700px 380px at 50% -8%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 70%),
    var(--bg);
}
.login-card {
  width: 100%; max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: var(--shadow-md);
  padding: 34px 30px 28px;
  text-align: center;
  display: flex; flex-direction: column; gap: 14px;
}
.login-card .logo { width: 52px; height: 52px; margin: 0 auto; border-radius: 13px; }
.login-card h1 { font-size: 19px; }
.login-card p { margin: 0; color: var(--text-soft); font-size: 13px; }
.login-card .btn { justify-content: center; padding: 9px 12px; font-size: 13.5px; }
.login-div { display: flex; align-items: center; gap: 10px; color: var(--text-faint); font-size: 11.5px; }
.login-div::before, .login-div::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.login-note { font-size: 11.5px !important; color: var(--text-faint) !important; }
.login-code { display: flex; flex-direction: column; gap: 8px; text-align: left; }
/* display:flex above would defeat the UA's [hidden] rule — restate it. */
.login-code[hidden] { display: none; }
.login-code label { font-size: 12px; color: var(--text-soft); }
.login-code input { text-transform: uppercase; text-align: center; letter-spacing: .14em; font-family: var(--mono); }
.login-code input::placeholder { letter-spacing: normal; }

/* ---------- detail pages ---------- */

.page-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.page-head h2 { font-size: 17px; }
.page-head .crumb { color: var(--text-faint); font-size: 12.5px; }
.page-head .crumb-link {
  display: inline-flex; align-items: center; gap: 2px;
  border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 12.5px; color: var(--text-faint);
}
.page-head .crumb-link:hover { color: var(--accent); text-decoration: underline; }
.page-head .crumb-link svg { width: 13px; height: 13px; }
.page-head .spacer { flex: 1; }

.kv-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px 22px;
}
.kv { display: flex; flex-direction: column; gap: 1px; }
.kv .k { font-size: 11px; font-weight: 700; color: var(--text-faint); text-transform: uppercase; letter-spacing: .04em; }
.kv .v { font-size: 13.5px; font-weight: 550; }
.kv .v.num { font-variant-numeric: tabular-nums; }

.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); padding: 0 8px; }
.tab {
  border: 0; background: transparent; font: inherit;
  font-size: 12.5px; font-weight: 600; color: var(--text-soft);
  padding: 9px 12px; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }

/* Product photo gallery: thumbnail tiles with an on-hover delete, click for
   full size (in a wide modal). */
.photo-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.photo-thumb {
  position: relative; width: 128px; height: 128px;
  border: 1px solid var(--border); border-radius: var(--r-md);
  overflow: hidden; cursor: zoom-in;
  background: var(--bg-sunken);
}
.photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-thumb .photo-del {
  position: absolute; top: 5px; right: 5px;
  width: 24px; height: 24px;
  display: flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(20, 20, 15, .55); color: #fff;
  opacity: 0; transition: opacity .12s;
}
.photo-thumb:hover .photo-del, .photo-thumb .photo-del:focus-visible { opacity: 1; }
@media (hover: none) { .photo-thumb .photo-del { opacity: 1; } }
.photo-thumb .photo-del:hover { background: var(--danger); }
.photo-thumb .photo-del svg { width: 13px; height: 13px; }
.photo-full { display: block; max-width: 100%; max-height: 72vh; margin: 0 auto; border-radius: var(--r-sm); }

.approvals { display: flex; gap: 14px; flex-wrap: wrap; }
.approval {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 8px 13px; font-size: 12.5px; font-weight: 600;
  background: var(--surface); cursor: pointer;
}
.approval input { width: 15px; height: 15px; accent-color: var(--ok); }
.approval.on { border-color: color-mix(in srgb, var(--ok) 45%, var(--border)); background: var(--ok-soft); color: var(--ok); }

/* ---------- misc ---------- */

.loading { display: grid; place-items: center; padding: 50px; color: var(--text-faint); }
.spinner {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2.5px solid var(--border);
  border-top-color: var(--accent);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.muted { color: var(--text-faint); }
.mono { font-family: var(--mono); font-size: 12px; }
.hist-row { border-bottom: 1px solid var(--border); padding: 8px 0; font-size: 12.5px; }
.hist-row .mono { white-space: pre-wrap; word-break: break-all; color: var(--text-soft); }

@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar { position: fixed; z-index: 80; width: var(--sidebar-w); height: 100vh; transform: translateX(-100%); transition: transform .18s; }
  .sidebar.open { transform: none; box-shadow: var(--shadow-lg); }
  .hamburger { display: inline-grid; }
  .content { padding: 12px; }
  .topbar { padding: 0 10px; gap: 8px; }
  .two-col { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  .userchip .userchip-name { display: none; }
}

/* ---------- history diff viewer ---------- */

.hist-block {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  margin-bottom: 10px;
  overflow: hidden;
}
.hist-head {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 10px;
  background: var(--bg-sunken);
  font-size: 12px;
}
.hist-note { padding: 8px 12px; font-size: 12.5px; color: var(--text-soft); }
table.hist-diff { width: 100%; border-collapse: collapse; font-size: 12px; }
.hist-diff th {
  text-align: left; padding: 5px 12px 3px;
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-faint);
}
/* Uniform row rhythm (verified by measurement): a fixed min-height keeps rows
   with EMPTY values exactly as tall as filled ones (an empty cell has no line
   box, which otherwise shrinks its row), and middle alignment centers the two
   different font sizes without baseline coupling. Wrapped values still grow. */
.hist-diff td { padding: 4px 12px; border-top: 1px solid var(--border); vertical-align: middle; line-height: 18px; height: 27px; word-break: break-word; }
/* NOT class "field": the generic form rule `.field { display:flex }` would
   turn the cell into a flex box, breaking table-cell border collapsing (the
   row lines then jog at the column boundary). */
.hist-diff td.hist-field { font-family: var(--mono); font-size: 11px; color: var(--text-soft); white-space: nowrap; }
.hist-diff td.before { color: var(--danger); }
.hist-diff td.after { color: var(--ok); }

.hist-diff tr.changed td { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.hist-diff tr.changed td.hist-field { color: var(--accent); font-weight: 700; }

/* ---------- test-environment watermark ---------- */

.test-watermark {
  position: fixed; bottom: 10px; left: 50%; transform: translateX(-50%);
  z-index: 200; pointer-events: none;
  padding: 4px 14px; border-radius: 99px;
  background: color-mix(in srgb, var(--warn) 12%, var(--bg-raised));
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  color: var(--warn);
  font-size: 11.5px; font-weight: 700; letter-spacing: .05em;
  box-shadow: var(--shadow-md);
  opacity: .92;
}
.test-chip {
  display: inline-block; vertical-align: 2px;
  margin-left: 7px; padding: 1px 6px; border-radius: 99px;
  background: var(--warn-soft); color: var(--warn);
  font-size: 9.5px; font-weight: 800; letter-spacing: .08em;
}

/* The sign-in warning and the acknowledgement dialog. Both wear the WARNING
   colour rather than the accent: this is the one thing on the page that must
   not read as decoration. */
.test-banner {
  text-align: left;
  padding: 10px 12px; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--warn) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  color: var(--text);
  font-size: 12px; line-height: 1.45;
}
.test-banner-title {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 3px;
  color: var(--warn); font-weight: 800; letter-spacing: .06em;
}
.test-banner-title svg { width: 15px; height: 15px; flex: none; }
.modal.ack { max-width: 460px; border-color: color-mix(in srgb, var(--warn) 45%, var(--border)); }
.modal.ack .modal-head { color: var(--warn); }
.test-ack-title { display: inline-flex; align-items: center; gap: 7px; }
.test-ack-title svg { width: 17px; height: 17px; flex: none; }
.test-ack p { margin: 0 0 9px; font-size: 13px; line-height: 1.5; }
.test-ack p:last-child { margin-bottom: 0; }
.test-ack-host {
  font-family: var(--mono); font-size: 12px !important;
  color: var(--text-faint); word-break: break-all;
}

/* ---------- app-language date field ---------- */

.datefield { position: relative; }
.datefield .input { padding-right: 34px; }
.datefield .cal-btn {
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px;
}
.datefield .date-hidden {
  position: absolute; right: 8px; bottom: 0;
  width: 1px; height: 1px; opacity: 0; pointer-events: none; border: 0; padding: 0;
}
.input.invalid { border-color: var(--danger); outline-color: var(--danger); }

/* ---------- passkey manager (account dialog) ---------- */

.pk-list { display: flex; flex-direction: column; gap: 6px; }
.pk-row {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
}
.pk-row > svg { width: 16px; height: 16px; color: var(--text-soft); flex: none; }
.pk-row .pk-name { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- resizable columns ---------- */

table.dt th { overflow: hidden; text-overflow: ellipsis; }
table.dt th .col-resizer {
  position: absolute; top: 0; right: -4px;
  width: 9px; height: 100%;
  cursor: col-resize; z-index: 7;
}
table.dt th .col-resizer::after {
  content: ''; position: absolute; right: 4px; top: 18%;
  height: 64%; width: 2px; border-radius: 2px;
  background: var(--border-strong); /* always faintly visible so the drag spot is discoverable */
}
table.dt th .col-resizer:hover::after,
table.dt th .col-resizer.active::after { background: var(--accent); }

/* ---------- workflow guide (#/guide) ---------- */
.guide-intro { margin: -4px 0 14px; color: var(--text-soft); font-size: 13.5px; max-width: 70ch; }

/* The pipeline strip: stops joined by labeled arrows; scrolls sideways on
   narrow screens rather than wrapping (the sequence IS the content). */
.guide-flow-card { padding: 8px 10px; margin-bottom: 14px; }
.flow { display: flex; align-items: stretch; gap: 2px; overflow-x: auto; padding: 6px 2px; }
.flow-node {
  flex: 1 0 108px; display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 11px 8px; border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--bg-raised); cursor: pointer; text-align: center; font: inherit; color: inherit;
  transition: border-color .15s, box-shadow .15s;
}
.flow-node:hover { border-color: var(--accent); box-shadow: var(--shadow-sm); }
.flow-node .fn-icon { color: var(--accent); display: inline-flex; }
.flow-node .fn-icon svg { width: 22px; height: 22px; }
.flow-node .fn-title { font-weight: 600; font-size: 13px; }
.flow-node .fn-sub { font-size: 11.5px; color: var(--text-soft); }
.flow-arrow {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0; min-width: 62px; max-width: 84px; padding: 0 3px; color: var(--text-faint); text-align: center;
}
.flow-arrow span { font-size: 11px; font-weight: 600; color: var(--accent-strong); }
.flow-arrow svg { width: 15px; height: 15px; }
[data-theme="dark"] .flow-arrow span { color: var(--accent); }

/* Step cards */
.guide-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); gap: 14px; margin-bottom: 14px; }
.guide-step .card-head { display: flex; align-items: center; gap: 8px; }
.step-no {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; flex: 0 0 22px;
  background: var(--accent); color: var(--accent-text); font-size: 12px; font-weight: 700;
}
.guide-points { margin: 0; padding: 10px 16px 12px 32px; display: grid; gap: 6px; }
.guide-points li { font-size: 13px; color: var(--text); line-height: 1.45; }
.guide-points li::marker { color: var(--text-faint); }

/* Glossary */
.guide-terms { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 8px 20px; }
.guide-term { display: flex; gap: 8px; font-size: 13px; align-items: baseline; }
.guide-term b { flex: 0 0 auto; min-width: 86px; }
.guide-term span { color: var(--text-soft); }

.guide .two-col { margin-bottom: 14px; }
@media (max-width: 900px) { .guide .two-col { grid-template-columns: 1fr; } }

/* ============ AI assistant (#/assistant) ============ */

/* The chat fills the content area exactly — page never scrolls, only the
   thread does. Height comes from the .content flex chain (not a 100vh
   calc, which drifts from the real chrome and ignores --zoom). */
.chat-page { height: 100%; }
.chat-card { display: flex; flex-direction: column; }
.chat-page .chat-card { flex: 1; min-height: 0; }
.chat-top { display: flex; gap: 8px; align-items: center; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.chat-conv-select { flex: 1; min-width: 0; }
.chat-thread { flex: 1; min-height: 0; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.chat-msg { display: flex; flex-direction: column; max-width: 78%; }
.chat-msg.user { align-self: flex-end; align-items: flex-end; }
.chat-msg.assistant { align-self: flex-start; align-items: flex-start; }
.chat-bubble {
  padding: 9px 12px; border-radius: var(--r-md); font-size: 13.5px; line-height: 1.5;
  overflow-wrap: anywhere; box-shadow: var(--shadow-sm); min-width: 0; max-width: 100%;
}
/* The user's own text is plain and keeps its typed line breaks; assistant
   answers are Markdown-rendered (md.js) and manage their own layout. */
.chat-msg.user .chat-bubble, .chat-bubble.refusal { white-space: pre-wrap; }
.chat-msg.user .chat-bubble { background: var(--accent); color: var(--accent-text); border-bottom-right-radius: 4px; }
/* The global ::selection is a translucent wash of the ACCENT — invisible on
   this bubble, whose background is the accent itself. Invert the pair
   instead: the accent-text/accent-strong tokens are a designed contrast
   pair in every accent preset and both themes, so selected text reads
   clearly everywhere. */
.chat-msg.user .chat-bubble::selection,
.chat-msg.user .chat-bubble ::selection {
  background: var(--accent-text);
  color: var(--accent-strong);
}
.chat-msg.assistant .chat-bubble {
  background: var(--bg-sunken); color: var(--text);
  border: 1px solid var(--border); border-bottom-left-radius: 4px;
}
.chat-bubble.refusal { background: var(--danger-soft); color: var(--danger); border-color: var(--danger); }
/* "…cut off" notice, inside the bubble under a truncated answer. */
.chat-cutoff {
  display: flex; align-items: center; gap: 5px; margin-top: 8px;
  padding-top: 6px; border-top: 1px dashed var(--border-strong);
  font-size: 11.5px; color: var(--warn);
}
.chat-cutoff svg { width: 13px; height: 13px; flex: 0 0 auto; }

/* Markdown content inside an answer bubble. */
.chat-md > :last-child { margin-bottom: 0; }
.chat-md p { margin: 0 0 8px; }
.chat-md .md-h { font-weight: 700; margin: 10px 0 6px; }
.chat-md > .md-h:first-child { margin-top: 0; }
.chat-md .md-h1 { font-size: 15px; }
.chat-md .md-h2 { font-size: 14px; }
.chat-md .md-h3 { font-size: 13.5px; }
.chat-md ul, .chat-md ol { margin: 0 0 8px; padding-left: 20px; display: grid; gap: 3px; }
.chat-md .table-scroll { margin: 0 0 8px; max-width: 100%; }
.chat-md .dt { font-size: 12.5px; }
.chat-md .dt td, .chat-md .dt th { white-space: nowrap; }
.chat-md code {
  font-family: var(--mono); font-size: 12px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 0 4px;
}
.chat-md pre {
  margin: 0 0 8px; padding: 8px 10px; overflow-x: auto;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--r-sm);
}
.chat-md pre code { background: none; border: 0; padding: 0; }
.chat-md hr { border: 0; border-top: 1px solid var(--border); margin: 8px 0; }
.chat-trace { display: flex; gap: 5px; align-items: center; margin-top: 4px; font-size: 11px; color: var(--text-faint); }
.chat-trace svg { width: 12px; height: 12px; flex: 0 0 auto; }
/* stretch (not flex-end): the textarea and the actions column share one
   height, so the box's top edge lines up with the attach button and its
   bottom with Send. */
.chat-compose { display: flex; gap: 8px; align-items: stretch; padding: 10px 12px; border-top: 1px solid var(--border); }
.chat-compose textarea { flex: 1; resize: none; }
/* Actions in a column on the right — attach above Send, equal width AND
   equal height: the same arrangement as the azcode ticket reply composer.
   The column stretch widens the buttons past their natural size, so the
   content (a lone paperclip) must center itself. */
.chat-compose-actions { display: flex; flex-direction: column; gap: 8px; }
.chat-compose-actions .btn { flex: 1; justify-content: center; }
.chat-remaining { padding: 0 12px 8px; font-size: 11px; text-align: right; }

/* Typing indicator: three blinking dots while the answer is on its way. */
.chat-typing { display: flex; gap: 4px; padding: 3px 2px; }
.chat-typing span {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-faint); animation: chat-blink 1.2s infinite;
}
.chat-typing span:nth-child(2) { animation-delay: .2s; }
.chat-typing span:nth-child(3) { animation-delay: .4s; }
@keyframes chat-blink { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }

/* Attachments: picked-file chips in the composer (draggable to reorder)
   and sent attachments under thread bubbles. */
.chat-card.drop-target { outline: 2px dashed var(--accent); outline-offset: -6px; }
.chat-files {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 8px 12px 0; border-top: 1px solid var(--border);
}
.chat-files[hidden] { display: none; }
.chat-chip, .chat-att-chip {
  display: inline-flex; align-items: center; gap: 6px;
  max-width: 240px; padding: 4px 8px; font-size: 12px; color: var(--text);
  background: var(--bg-sunken); border: 1px solid var(--border);
  border-radius: var(--r-sm); cursor: pointer;
}
.chat-chip { cursor: grab; }
.chat-chip.dragging { opacity: .4; }
.chat-chip svg, .chat-att-chip svg { width: 14px; height: 14px; flex: 0 0 auto; color: var(--text-faint); }
.chip-thumb { width: 22px; height: 22px; object-fit: cover; border-radius: 4px; flex: 0 0 auto; }
.chat-att-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-att-size { color: var(--text-faint); flex: 0 0 auto; }
.chip-remove {
  border: 0; background: none; color: var(--text-faint); cursor: pointer;
  font-size: 15px; line-height: 1; padding: 0 2px; flex: 0 0 auto;
}
.chip-remove:hover { color: var(--danger); }
.chat-atts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.chat-msg.user .chat-atts { justify-content: flex-end; }
.chat-att-thumb {
  border: 1px solid var(--border); border-radius: var(--r-sm); padding: 0;
  background: var(--bg-sunken); cursor: zoom-in; overflow: hidden; max-width: 220px;
}
.chat-att-thumb img { display: block; max-width: 220px; max-height: 160px; object-fit: cover; }
