/* --------------------------------------------------------------------------
   Niche Shop Drawings - one stylesheet for every page. Every colour is a token
   so the viewer page can reuse exactly the same palette.

   Day mode is the default: the light palette lives on :root, so the site is
   light even before any script runs and however the OS is set. Night mode is
   opt-in and only applies when the user has picked it (html[data-theme="dark"]).

   The brand green #76B72F is a mid-tone: it only reaches 2.4:1 against white,
   so it can be a FILL but never body text on a light background. That is what
   --accent-text is for - a darkened olive on light (5.1:1) and a lightened one
   on dark (10:1). --accent-ink is what sits ON the green, and is near-black in
   both themes because white on #76B72F fails too.
   -------------------------------------------------------------------------- */

:root {
  --bg:        #f3f6f0;
  --bg-2:      #e9efe2;
  --panel:     #ffffff;
  --panel-2:   #f5f8f1;
  --line:      #d6dfcb;
  --line-soft: #e6ecdd;
  --ink:       #18220f;
  --ink-2:     #3c4a30;
  --muted:     #637354;
  --faint:     #8d9a80;

  --accent:      #76B72F;
  --accent-d:    #5F9526;
  --accent-ink:  #14260b;
  --accent-text: #4E7A1D;

  --ok:      #2f8a3f;
  --warn:    #96660f;
  --danger:  #c23c3c;
  --info:    #1b6fa8;
  --purple:  #7248ad;

  --radius:   12px;
  --radius-s: 8px;
  --shadow:   0 10px 26px rgba(30,45,20,.14);
  --mono: ui-monospace, "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, Inter, Arial, sans-serif;
}

html[data-theme="dark"] {
  --bg:        #10150c;
  --bg-2:      #161d10;
  --panel:     #19210f;
  --panel-2:   #1f2915;
  --line:      #33421f;
  --line-soft: #27321a;
  --ink:       #e9f0e0;
  --ink-2:     #c2cfb4;
  --muted:     #97a888;
  --faint:     #6d7c60;

  --accent:      #76B72F;
  --accent-d:    #5F9526;
  --accent-ink:  #10200a;
  --accent-text: #93CE4F;

  --ok:      #62c96f;
  --warn:    #e8b95c;
  --danger:  #ef6b6b;
  --info:    #6bb8ef;
  --purple:  #b48ce8;
  --shadow:  0 10px 30px rgba(0,0,0,.45);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 { margin: 0 0 .5em; font-weight: 650; letter-spacing: -.01em; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.15rem; }
h3 { font-size: 1rem; }

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

.shell { min-height: 100vh; display: flex; flex-direction: column; }

.topbar {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; gap: 14px;
  padding: 10px 18px;
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.brand { display: flex; align-items: center; gap: 10px; font-weight: 680; letter-spacing: -.015em; }
.brand .mark {
  width: 28px; height: 28px; border-radius: 8px; flex: none;
  background: linear-gradient(140deg, var(--accent), var(--accent-d));
  display: grid; place-items: center; color: var(--accent-ink);
  font-size: 13px; font-weight: 800;
}
.brand small { display: block; font-size: 11px; color: var(--muted); font-weight: 500; letter-spacing: .04em; }

.topnav { display: flex; gap: 4px; margin-left: 8px; }
.topnav a {
  padding: 7px 12px; border-radius: var(--radius-s);
  color: var(--ink-2); font-size: 14px; font-weight: 550;
}
.topnav a:hover { background: var(--panel-2); text-decoration: none; color: var(--ink); }
.topnav a.on { background: var(--panel-2); color: var(--accent-text); }

.spacer { flex: 1 1 auto; }

.who { text-align: right; line-height: 1.25; font-size: 13px; }
.who b { display: block; font-weight: 600; }
.who span { color: var(--muted); font-size: 12px; }

/* The page fills the window: the panel gets the full width, and stretches to
   the bottom, with the same 20px gap on every side as between the top bar and
   the panel. The table scrolls inside the panel, so the pager stays put. */
.page {
  flex: 1 1 auto; padding: 20px; width: 100%;
  display: flex; flex-direction: column; min-height: 0;
}
.page > section { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.page > section.hidden { display: none; }
.page > section > .panel,
.page > .panel { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.page > section .table-wrap { flex: 1 1 auto; min-height: 0; overflow: auto; }
.panel-body#tab-body { flex: 1 1 auto; min-height: 0; overflow: auto; }

/* --------------------------------------------------------------- panels */

.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.panel + .panel { margin-top: 16px; }
.panel-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 13px 16px; border-bottom: 1px solid var(--line);
  background: var(--panel-2);
}
.panel-head h2 { margin: 0; font-size: 1rem; }
.panel-body { padding: 16px; }
.panel-body.tight { padding: 0; }

.grid { display: grid; gap: 16px; }
.grid.two { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.grid.stats { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }

.stat {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 13px 15px;
}
.stat b { display: block; font-size: 1.55rem; font-weight: 680; letter-spacing: -.02em; }
.stat span { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .05em; }
.stat.alert b { color: var(--warn); }
.stat.bad b { color: var(--danger); }

/* --------------------------------------------------------------- inputs */

.field { display: block; margin-bottom: 12px; }
.field > span {
  display: block; font-size: 12px; color: var(--muted);
  margin-bottom: 5px; font-weight: 550; letter-spacing: .02em;
}

input[type=text], input[type=email], input[type=number], input[type=search],
input[type=password], input[type=datetime-local], select, textarea {
  width: 100%; padding: 9px 11px;
  background: var(--bg-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius-s);
  font: inherit; font-size: 14px;
  transition: border-color .12s, box-shadow .12s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
input:disabled, select:disabled, textarea:disabled { opacity: .55; cursor: not-allowed; }
textarea { resize: vertical; min-height: 74px; }
select { cursor: pointer; }

.check { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; user-select: none; }
.check input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; flex: none; }

.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }
.row > * { min-width: 0; }
.grow { flex: 1 1 180px; }

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

button, .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 15px; border-radius: var(--radius-s);
  border: 1px solid var(--line); background: var(--panel-2); color: var(--ink);
  font: inherit; font-size: 14px; font-weight: 550; cursor: pointer;
  transition: background .12s, border-color .12s, transform .05s;
  white-space: nowrap;
}
button:hover, .btn:hover { background: var(--line-soft); text-decoration: none; }
button:active, .btn:active { transform: translateY(1px); }
button:disabled { opacity: .5; cursor: not-allowed; transform: none; }

.btn-primary, button.primary {
  background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 620;
}
.btn-primary:hover, button.primary:hover { background: var(--accent-d); border-color: var(--accent-d); }

button.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--line)); }
button.danger:hover { background: color-mix(in srgb, var(--danger) 15%, transparent); }

/* Filled, high-contrast decision buttons - the approve/request-changes/reject
   trio reads like a traffic light. */
button.warn-solid, .btn.warn-solid {
  background: var(--warn); border-color: var(--warn); color: #1a1204; font-weight: 650;
}
button.warn-solid:hover { background: color-mix(in srgb, var(--warn) 88%, #000); }
button.danger-solid, .btn.danger-solid {
  background: var(--danger); border-color: var(--danger); color: #fff; font-weight: 650;
}
button.danger-solid:hover { background: color-mix(in srgb, var(--danger) 88%, #000); }

button.ghost { background: transparent; border-color: transparent; color: var(--muted); }
button.ghost:hover { background: var(--panel-2); color: var(--ink); }

button.small, .btn.small { padding: 5px 10px; font-size: 13px; }
button.icon { padding: 7px; width: 34px; height: 34px; }

/* --------------------------------------------------------------- tables */

.table-wrap { overflow-x: auto; }

table.data { width: 100%; border-collapse: collapse; font-size: 14px; }
table.data th {
  text-align: left; padding: 10px 12px;
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); font-weight: 650;
  border-bottom: 1px solid var(--line); background: var(--panel-2);
  white-space: nowrap; position: sticky; top: 0; z-index: 2;
}
table.data th.sortable { cursor: pointer; user-select: none; }
table.data th.sortable:hover { color: var(--ink); }
table.data th .arrow { opacity: .5; font-size: 10px; }
table.data td { padding: 10px 12px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
table.data tbody tr:hover { background: var(--panel-2); }
table.data tbody tr.clickable { cursor: pointer; }
table.data td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data .nowrap { white-space: nowrap; }

.cell-title { font-weight: 600; color: var(--ink); }
.cell-sub { color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.mono { font-family: var(--mono); font-size: .93em; }

/* --------------------------------------------------------- long filenames
   Shop-drawing filenames run to 80+ characters with no spaces
   (SAMPLE-VLP450-450KG-2SS-RHO09-MACHINE-ROOM-SIDE-PIT-200-CAR-2300H.dwg),
   and in an auto-layout table neither wrapping rule works: break-all lets the
   browser squeeze the column down to one character per line, while break-word
   makes the column as wide as the whole name and pushes the layout out.

   So the file table is fixed-layout - the column keeps the width we give it
   whatever the name is - and the name wraps inside it, clamped to two lines.
   The whole name is always reachable: hover for the tooltip, click to unclamp. */

table.files { table-layout: fixed; width: 100%; }

.fname {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
  line-height: 1.35;
  font-weight: 600;
  cursor: pointer;
}
.fname.open {
  display: block;
  -webkit-line-clamp: unset;
}
.fname:hover { color: var(--accent-text); }

/* Same trick where a filename sits under a drawing name in the register:
   one line, ellipsis, full text on hover. */
.fname-1 {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 380px;
}

/* A hidden drawing, shown only to people who can hide one. Greyed rather than
   removed so it stays findable and can be put back; the stripe makes it
   obvious at a glance that this row is not in circulation. */
table.data tbody tr.row-hidden { opacity: .55; }
table.data tbody tr.row-hidden:hover { opacity: .8; }
table.data tbody tr.row-hidden td:first-child {
  box-shadow: inset 3px 0 0 var(--faint);
}
table.data tbody tr.row-hidden .cell-title { font-style: italic; }

.empty { padding: 46px 20px; text-align: center; color: var(--muted); }
.empty b { display: block; color: var(--ink-2); margin-bottom: 6px; font-size: 15px; }

/* --------------------------------------------------------------- chips */

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600; letter-spacing: .02em;
  border: 1px solid var(--line); background: var(--panel-2); color: var(--ink-2);
  white-space: nowrap;
}
.chip.dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.st-pending    { color: var(--warn);   border-color: color-mix(in srgb, var(--warn) 42%, var(--line));
                 background: color-mix(in srgb, var(--warn) 13%, transparent); }
.st-approved   { color: var(--ok);     border-color: color-mix(in srgb, var(--ok) 42%, var(--line));
                 background: color-mix(in srgb, var(--ok) 13%, transparent); }
.st-rejected   { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 42%, var(--line));
                 background: color-mix(in srgb, var(--danger) 13%, transparent); }
.st-commented  { color: var(--info);   border-color: color-mix(in srgb, var(--info) 42%, var(--line));
                 background: color-mix(in srgb, var(--info) 13%, transparent); }
.st-cancelled  { color: var(--faint); }
.st-superseded { color: var(--purple); border-color: color-mix(in srgb, var(--purple) 42%, var(--line));
                 background: color-mix(in srgb, var(--purple) 13%, transparent); }
.st-revoked    { color: #fff; background: var(--danger); border-color: var(--danger); }
.st-locked     { color: var(--muted);  border-color: color-mix(in srgb, var(--muted) 42%, var(--line));
                 background: color-mix(in srgb, var(--muted) 13%, transparent); }

/* @-mention picker + highlighted names in the discussion */
.mention-pop {
  position: fixed; z-index: 9999; max-height: 240px; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0,0,0,.22); padding: 4px;
}
.mention-item { padding: 7px 10px; border-radius: 7px; cursor: pointer; font-size: 13px; white-space: nowrap; }
.mention-item.active, .mention-item:hover { background: var(--panel-2); }
.mention { color: var(--accent); font-weight: 700; }

.kind {
  display: inline-block; padding: 1px 6px; border-radius: 5px;
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  border: 1px solid var(--line); color: var(--muted);
}
.kind.has { color: var(--accent-text); border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
            background: color-mix(in srgb, var(--accent) 12%, transparent); }
.kind.none { opacity: .35; }
.kinds { display: inline-flex; gap: 4px; }

.warnflag {
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--warn); font-size: 12px; font-weight: 600; margin-top: 3px;
}

/* ------------------------------------------------------------ pagination */

.pager {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 11px 16px; border-top: 1px solid var(--line); background: var(--panel-2);
}
.pager .count { color: var(--muted); font-size: 13px; }
.pager .pages { display: flex; gap: 4px; margin-left: auto; align-items: center; }
.pager button { padding: 5px 11px; font-size: 13px; }
.pager button.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* --------------------------------------------------------------- modals */

.backdrop {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(4,10,12,.62); backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: 20px;
  animation: fade .12s ease;
}
@keyframes fade { from { opacity: 0; } }

.modal {
  width: min(820px, 100%); max-height: calc(100vh - 40px);
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  display: flex; flex-direction: column; overflow: hidden;
}
.modal.wide { width: min(1180px, 100%); }
.modal.narrow { width: min(500px, 100%); }
/* Near-fullscreen, with a slim gap all round so the blurred page behind is
   still visible. Height is fixed (not max-) so the two-column drawing layout
   gets the whole window to spend. */
.modal.full {
  width: calc(100vw - 48px);
  height: calc(100vh - 48px);
  max-height: calc(100vh - 48px);
}
.modal-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px; border-bottom: 1px solid var(--line); background: var(--panel-2);
}
.modal-head h2 { margin: 0; font-size: 1.05rem; }
.modal-body { padding: 18px; overflow: auto; flex: 1 1 auto; }
.modal-foot {
  display: flex; gap: 10px; justify-content: flex-end; align-items: center;
  padding: 13px 18px; border-top: 1px solid var(--line); background: var(--panel-2);
}
.modal-foot .left { margin-right: auto; color: var(--muted); font-size: 13px; }

/* ------------------------------------------------------------ drop zones */

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

.drop {
  border: 1.5px dashed var(--line); border-radius: var(--radius);
  padding: 14px; background: var(--bg-2);
  transition: border-color .15s, background .15s;
  min-height: 128px; display: flex; flex-direction: column;
}
.drop.over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--bg-2)); }
.drop.filled { border-style: solid; border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.drop h4 {
  margin: 0 0 8px; font-size: 12px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted); display: flex; align-items: center; gap: 7px;
}
.drop .hint { color: var(--faint); font-size: 12.5px; margin-top: auto; }
.drop .filename { font-weight: 600; word-break: break-all; font-size: 13.5px; }
.drop dl { margin: 8px 0 0; font-size: 12px; color: var(--muted); display: grid;
           grid-template-columns: auto 1fr; gap: 2px 10px; }
.drop dt { color: var(--faint); }
.drop dd { margin: 0; font-family: var(--mono); font-size: 11.5px; }

/* ------------------------------------------------------------ chat / log */

.chat { display: flex; flex-direction: column; gap: 12px; padding: 4px 2px; }
.msg { display: flex; gap: 10px; max-width: 82%; }
.msg.me { margin-left: auto; flex-direction: row-reverse; }
.avatar {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: grid; place-items: center; font-size: 12px; font-weight: 700;
  background: var(--panel-2); border: 1px solid var(--line); color: var(--accent-text);
}
.bubble {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 14px; padding: 9px 13px; font-size: 14px;
}
.msg.me .bubble { background: color-mix(in srgb, var(--accent) 15%, var(--panel-2));
                  border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); }
.bubble .meta { font-size: 11.5px; color: var(--muted); margin-bottom: 3px; display: flex; gap: 7px; }
.bubble .meta b { color: var(--ink-2); font-weight: 620; }
.bubble p { margin: 0; white-space: pre-wrap; word-break: break-word; }

.msg.system { max-width: 100%; margin: 0; }
.msg.system .bubble {
  background: transparent; border: none; border-left: 2px solid var(--line);
  border-radius: 0; color: var(--muted); font-size: 13px; padding: 2px 0 2px 12px;
}
.msg.system .avatar { display: none; }
.msg.system .sys-line { font-weight: 650; }
.msg.system .sys-note { margin-top: 2px; color: var(--muted); white-space: pre-wrap; }
/* Share links and long pasted URLs must wrap inside the bubble, not push the
   modal sideways. */
.msg .bubble p { overflow-wrap: anywhere; }

/* Signpost in the thread each time the conversation moves to a new revision -
   one drawing keeps one discussion, so this is what keeps it readable. */
.rev-divider {
  display: flex; align-items: center; gap: 10px;
  margin: 6px 0 2px; color: var(--muted);
  font-size: 12px; font-weight: 650; letter-spacing: .04em; text-transform: uppercase;
}
.rev-divider::before, .rev-divider::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--line);
}

/* Colour each history event by what it was, and tint its left rule + a soft
   highlight so it stands out from ordinary chat. */
.msg.system.sys-submitted  .bubble { border-left-color: var(--info); }
.msg.system.sys-submitted  .sys-line { color: var(--info); }
.msg.system.sys-approved   .bubble { border-left-color: var(--ok); }
.msg.system.sys-approved   .sys-line { color: var(--ok); }
.msg.system.sys-commented  .bubble {
  border-left-color: var(--warn);
  background: color-mix(in srgb, var(--warn) 9%, transparent); border-radius: 0 7px 7px 0;
  padding-right: 8px;
}
.msg.system.sys-commented  .sys-line { color: var(--warn); }
.msg.system.sys-rejected   .bubble,
.msg.system.sys-revoked    .bubble {
  border-left-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent); border-radius: 0 7px 7px 0;
  padding-right: 8px;
}
.msg.system.sys-rejected   .sys-line,
.msg.system.sys-revoked    .sys-line { color: var(--danger); }
.msg.system.sys-reopened   .bubble { border-left-color: var(--info); }
.msg.system.sys-reopened   .sys-line { color: var(--info); }
.msg.system.sys-superseded .bubble,
.msg.system.sys-supersede_pending .bubble { border-left-color: var(--purple); }
.msg.system.sys-superseded .sys-line,
.msg.system.sys-supersede_pending .sys-line { color: var(--purple); }
.msg.system.sys-cancelled  .sys-line,
.msg.system.sys-hidden     .sys-line,
.msg.system.sys-unhidden   .sys-line { color: var(--ink-2); }
/* Sharing and taking copies: the record of who let the drawing out and who
   holds it. Shares get the info tint; downloads stay quiet grey so decisions
   still dominate the thread. */
.msg.system.sys-shared     .bubble { border-left-color: var(--info); }
.msg.system.sys-shared     .sys-line { color: var(--info); }
.msg.system.sys-downloaded .sys-line,
.msg.system.sys-viewed     .sys-line { color: var(--ink-2); }

/* ------------------------------------------------------------ notes/banners */

.note {
  padding: 11px 14px; border-radius: var(--radius-s);
  border: 1px solid var(--line); background: var(--panel-2);
  font-size: 13.5px; color: var(--ink-2); margin-bottom: 14px;
}
.note b { color: var(--ink); }
.note.warn   { border-color: color-mix(in srgb, var(--warn) 45%, var(--line));
               background: color-mix(in srgb, var(--warn) 12%, transparent); color: var(--warn); }
.note.danger { border-color: color-mix(in srgb, var(--danger) 45%, var(--line));
               background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger); }
.note.ok     { border-color: color-mix(in srgb, var(--ok) 45%, var(--line));
               background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok); }
.note.info   { border-color: color-mix(in srgb, var(--info) 45%, var(--line));
               background: color-mix(in srgb, var(--info) 12%, transparent); color: var(--info); }

/* --------------------------------------------------------------- toasts */

#toasts {
  position: fixed; right: 16px; bottom: 16px; z-index: 300;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-end;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  background: var(--panel); border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-s); box-shadow: var(--shadow);
  padding: 11px 15px; font-size: 14px; max-width: 420px;
  animation: slidein .18s ease;
}
.toast.bad  { border-left-color: var(--danger); }
.toast.warn { border-left-color: var(--warn); }
@keyframes slidein { from { opacity: 0; transform: translateY(8px); } }

/* --------------------------------------------------------- notifications */

.bell { position: relative; }
.bell .badge {
  position: absolute; top: -3px; right: -3px;
  min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 9px; background: var(--danger); color: #fff;
  font-size: 10.5px; font-weight: 700; display: grid; place-items: center;
}
.notif-list { max-height: 60vh; overflow: auto; }
.notif {
  padding: 11px 14px; border-bottom: 1px solid var(--line-soft);
  display: flex; gap: 11px; align-items: flex-start; cursor: pointer;
}
.notif:hover { background: var(--panel-2); }
.notif.unread { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.notif .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent);
              margin-top: 6px; flex: none; }
.notif.high .dot { background: var(--danger); }
.notif .body b { display: block; font-size: 13.5px; margin-bottom: 2px; }
.notif .body span { color: var(--muted); font-size: 12.5px; }
.notif time { color: var(--faint); font-size: 11.5px; white-space: nowrap; margin-left: auto; }

/* ------------------------------------------------------------- sign-in */

.auth-wrap { min-height: 100vh; display: grid; place-items: center; padding: 22px; }
.auth {
  width: min(430px, 100%);
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 16px; box-shadow: var(--shadow); padding: 30px;
}
.auth .brand { justify-content: center; margin-bottom: 6px; }
.auth h1 { text-align: center; font-size: 1.3rem; margin-bottom: 4px; }
.auth .sub { text-align: center; color: var(--muted); font-size: 13.5px; margin-bottom: 22px; }
.code-input {
  text-align: center; font-family: var(--mono);
  font-size: 27px !important; letter-spacing: .38em; padding: 13px !important;
  text-indent: .38em;
}

/* --------------------------------------------------------------- tabs */

.tabs { display: flex; gap: 3px; border-bottom: 1px solid var(--line); padding: 0 16px;
        background: var(--panel-2); overflow-x: auto; }
.tabs button {
  border: none; background: none; border-radius: 0;
  border-bottom: 2px solid transparent; padding: 11px 13px;
  color: var(--muted); font-weight: 560; font-size: 14px;
}
.tabs button:hover { background: none; color: var(--ink); }
.tabs button.on { color: var(--accent-text); border-bottom-color: var(--accent); }

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

.spin {
  width: 15px; height: 15px; border-radius: 50%; flex: none;
  border: 2px solid color-mix(in srgb, currentColor 28%, transparent);
  border-top-color: currentColor; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.loading { padding: 40px; text-align: center; color: var(--muted); }
.hidden { display: none !important; }
.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; font-size: 13.5px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }

.tip { position: relative; cursor: help; border-bottom: 1px dotted currentColor; }

hr.sep { border: none; border-top: 1px solid var(--line); margin: 16px 0; }

/* ------------------------------------------------------- storage meters */

.meter {
  display: flex; height: 28px; border-radius: 9px; overflow: hidden;
  background: var(--bg-2); border: 1px solid var(--line);
}
.meter > span { display: block; height: 100%; min-width: 2px; transition: width .4s ease; }
.meter-legend { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 10px; font-size: 13px; }
.meter-legend .k {
  width: 11px; height: 11px; border-radius: 3px; display: inline-block;
  margin-right: 6px; vertical-align: -1px;
}

/* ------------------------------------------------------------ responsive */

/* Columns the table can live without when the window narrows: first the file
   dates, then the download counter. The data is still on the drawing page. */
@media (max-width: 1800px) { .col-opt  { display: none; } }
@media (max-width: 1330px) { .col-opt2 { display: none; } }

@media (max-width: 780px) {
  .page { padding: 12px; }
  .topbar { padding: 9px 12px; gap: 9px; flex-wrap: wrap; }
  .topnav { overflow-x: auto; scrollbar-width: none; max-width: 100%; }
  .topnav::-webkit-scrollbar { display: none; }
  .topnav a { padding: 6px 9px; font-size: 13px; white-space: nowrap; }
  .who { display: none; }
  .msg { max-width: 94%; }

  /* Dialogs take the whole screen instead of cramming into a card. */
  .backdrop { padding: 0; }
  .modal, .modal.wide, .modal.narrow, .modal.full {
    width: 100%; max-height: 100vh; height: 100vh; border-radius: 0; border: none;
  }
  .grid.two { grid-template-columns: 1fr; }
  .row > .field { flex: 1 1 100%; width: auto !important; }
  .fname-1 { max-width: 60vw; }

  /* A footer with info text plus three-or-more buttons will not fit one row:
     the info line goes to the top, on its own, and the buttons wrap under it
     right-aligned - instead of being pushed off the left edge. */
  .modal-foot { flex-wrap: wrap; }
  .modal-foot .left { flex: 1 1 100%; order: -1; margin: 0 0 6px; }
  .modal-foot button, .modal-foot .btn { flex: 0 1 auto; }

  /* Header actions can wrap too, rather than crushing the title. */
  .panel-head { row-gap: 8px; }
}

/* ------------------------------------------------- register table fitting */
/* The register carries eleven columns; without a ceiling the two free-text
   ones (drawing filename, project site name) stretch the table past the
   window and force sideways scrolling. Both clip with an ellipsis and keep
   the full text in a tooltip - and on the drawing page, which is where the
   detail belongs. */
.cell-clip {
  display: block; max-width: 230px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#reg-table .fname-1 { max-width: 300px; }
#reg-table th, #reg-table td { padding-left: 9px; padding-right: 9px; }

/* Wide screens can afford more of the names; narrow ones give the space to
   the columns that carry status. */
@media (min-width: 1900px) {
  .cell-clip { max-width: 320px; }
  #reg-table .fname-1 { max-width: 420px; }
}
@media (max-width: 1100px) {
  .cell-clip { max-width: 150px; }
  #reg-table .fname-1 { max-width: 190px; }
}

/* ------------------------------------------------------ drag-merge (admin) */
/* Merge mode on the Projects tab: the row being dragged fades, and the row it
   would merge INTO is outlined - so the direction of the merge (dragged one
   disappears) is visible before letting go. */
#tab-body tr[draggable="true"] { cursor: grab; }
#tab-body tr[draggable="true"]:active { cursor: grabbing; }
#tab-body tr.drag-src { opacity: .45; }
#tab-body tr.drag-over > td {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  box-shadow: inset 0 2px 0 var(--accent), inset 0 -2px 0 var(--accent);
}
#tab-body tr.drag-over > td:first-child { box-shadow: inset 2px 0 0 var(--accent), inset 0 2px 0 var(--accent), inset 0 -2px 0 var(--accent); }
#tab-body tr.drag-over > td:last-child  { box-shadow: inset -2px 0 0 var(--accent), inset 0 2px 0 var(--accent), inset 0 -2px 0 var(--accent); }
#p-mergemode-wrap:has(#p-mergemode:checked) {
  background: color-mix(in srgb, var(--warn) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--line));
  border-radius: var(--radius-s); padding: 8px 11px;
}
