/* PPAP Auto-Ballooning
   ---------------------------------------------------------------------------
   A sidebar shell with four views. Everything is driven from the tokens in
   :root, so spacing and colour stay consistent across the sign-in screen, the
   drawing list and the editor. */

:root {
  --ink: #16202e;
  --ink-2: #33415c;
  --muted: #64748b;
  --line: #e4e9f1;
  --line-2: #eef2f7;
  --bg: #f4f6fa;
  --card: #ffffff;
  --navy: #0f1c30;
  --navy-2: #16273f;
  --accent: #1a46b8;
  --accent-ink: #123090;
  --accent-soft: #e8eeff;
  --crit: #c4161c;
  --ok: #157347;
  --warn-bg: #fffbeb;
  --warn-ink: #92400e;
  --r: 10px;
  --r-lg: 14px;
  --shadow: 0 1px 2px rgba(15, 28, 48, .05), 0 8px 24px rgba(15, 28, 48, .06);
  --side: 248px;
  --side-min: 68px;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font: 14px/1.55 "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

.hidden { display: none !important; }
.muted { color: var(--muted); font-size: 12.5px; }
a { color: var(--accent); }

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

.mark {
  font-weight: 800; letter-spacing: .06em; font-size: 13px;
  background: var(--accent); color: #fff; padding: 6px 9px; border-radius: 8px;
}

/* ---------------------------------------------------------------- buttons */
.btn, button.ghost, button.primary, a.ghost, a.btn {
  font: inherit; font-size: 13px; font-weight: 550;
  padding: 7px 13px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--line); background: #fff; color: var(--ink);
  text-decoration: none; display: inline-flex; align-items: center; gap: 6px;
  white-space: nowrap; transition: background .12s, border-color .12s;
}
.btn:hover, button.ghost:hover, a.ghost:hover { background: var(--line-2); }
.btn.primary, button.primary {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.btn.primary:hover, button.primary:hover { background: var(--accent-ink); }
.btn.block, .block { width: 100%; justify-content: center; }
button.small, a.small { padding: 4px 9px; font-size: 12px; border-radius: 6px; }
button.danger { color: var(--crit); }
button.danger:hover { background: #fdeaea; border-color: #f3c6c6; }
button:disabled { opacity: .55; cursor: not-allowed; }
.linkish {
  background: none; border: none; padding: 0; font: inherit;
  color: var(--accent); text-decoration: underline; cursor: pointer;
}
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: inherit; cursor: pointer;
}
.icon-btn:hover { background: rgba(255, 255, 255, .12); }
.main .icon-btn:hover { background: var(--line-2); }

/* ------------------------------------------------------------- sign in */
.auth {
  min-height: 100%; display: grid; place-items: center; padding: 24px;
  background:
    radial-gradient(900px 500px at 15% -10%, #1b3560 0%, transparent 60%),
    var(--navy);
}
.auth-card {
  width: 100%; max-width: 380px; background: var(--card);
  border-radius: var(--r-lg); padding: 28px 28px 24px;
  box-shadow: 0 30px 70px rgba(5, 12, 25, .45);
}
.auth-brand {
  display: flex; align-items: center; gap: 10px;
  font-weight: 700; font-size: 14px; color: var(--ink-2);
}
.auth-card h1 { margin: 20px 0 4px; font-size: 21px; letter-spacing: -.01em; }
.auth-sub { margin: 0 0 18px; font-size: 13px; color: var(--muted); }
.auth-error {
  margin: 0 0 12px; padding: 9px 11px; border-radius: 8px;
  background: #fdeaea; color: #8f1c1c; font-size: 13px;
}
.auth-hint { margin: 12px 0 0; font-size: 12px; color: var(--muted); text-align: center; }

/* --------------------------------------------------------------- fields */
.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 14px; }
.field > span {
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
.field input, .field select, .field textarea {
  font: inherit; font-size: 13.5px; color: var(--ink);
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px;
  background: #fff; width: 100%;
}
.field textarea { resize: vertical; min-height: 44px; }
.field input[type=color] { width: 56px; height: 36px; padding: 3px; cursor: pointer; }
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px var(--accent-soft);
}
/* A field the drawing did not state has to be filled in by a person before
   the PPAP goes out, so it is marked rather than left looking complete. */
.field input.missing { background: var(--warn-bg); border-color: #f59e0b; }

.check { display: flex; gap: 9px; align-items: flex-start; cursor: pointer; font-size: 13px; }
.check input { margin-top: 2px; }
.check span { display: flex; flex-direction: column; }
.check em { font-style: normal; font-size: 12px; color: var(--muted); }
.check.inline { align-items: center; }
.check.inline span { flex-direction: row; gap: 5px; align-items: baseline; }

/* ---------------------------------------------------------------- shell */
.app { display: flex; min-height: 100vh; }

.sidebar {
  position: fixed; inset: 0 auto 0 0; z-index: 30;
  width: var(--side); display: flex; flex-direction: column;
  background: var(--navy); color: #cfdcf0;
  transition: width .16s ease;
}
.side-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 16px 14px 16px 18px; color: #fff;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
}
.side-title { font-weight: 650; font-size: 14.5px; white-space: nowrap; }
.side-brand .icon-btn { margin-left: auto; color: #8ea6c8; }

.side-nav { padding: 12px 10px; display: flex; flex-direction: column; gap: 3px; flex: 1; }
.nav-item {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 11px; border-radius: 9px;
  color: #b9c9e2; text-decoration: none; font-size: 13.5px; font-weight: 500;
  white-space: nowrap; overflow: hidden;
}
.nav-item:hover { background: rgba(255, 255, 255, .07); color: #fff; }
.nav-item.active { background: var(--accent); color: #fff; }
.nav-item svg { flex: none; }

.side-foot { padding: 12px 12px 16px; border-top: 1px solid rgba(255, 255, 255, .07); }
.who { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; overflow: hidden; }
.avatar {
  flex: none; width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center; background: #24406b; color: #fff;
  font-weight: 700; font-size: 13px;
}
.who-text { display: flex; flex-direction: column; overflow: hidden; }
.who-text b { color: #fff; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.who-text em { font-style: normal; font-size: 11.5px; color: #8ea6c8; }
.side-foot .ghost { background: transparent; border-color: rgba(255, 255, 255, .16); color: #cfdcf0; }
.side-foot .ghost:hover { background: rgba(255, 255, 255, .1); }

/* collapsed: icons only */
body.collapsed .sidebar { width: var(--side-min); }
body.collapsed .side-title,
body.collapsed .nav-item span,
body.collapsed .who-text,
body.collapsed .side-foot .ghost { display: none; }
body.collapsed .side-brand { padding: 16px 0; justify-content: center; position: relative; }
body.collapsed .side-brand .icon-btn {
  position: absolute; top: 58px; right: -14px; width: 28px; height: 28px;
  background: var(--navy-2); border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 50%; transform: rotate(180deg);
}
body.collapsed .nav-item { justify-content: center; padding: 10px 0; }
body.collapsed .who { justify-content: center; }
body.collapsed .main { margin-left: var(--side-min); }

.main { flex: 1; margin-left: var(--side); min-width: 0; display: flex; flex-direction: column; }

.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 14px;
  padding: 14px 24px; background: rgba(244, 246, 250, .92);
  backdrop-filter: blur(8px); border-bottom: 1px solid var(--line);
}
.topbar #menuBtn { display: none; }
.titles { min-width: 0; }
.titles h1 {
  margin: 0; font-size: 17px; font-weight: 650; letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.titles p {
  margin: 1px 0 0; font-size: 12.5px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.top-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }

.views { padding: 20px 24px 32px; }
.view { display: none; }
.view.on { display: block; }

.scrim { display: none; }

/* ---------------------------------------------------------------- cards */
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow);
  margin-bottom: 18px; overflow: hidden;
}
.card.pad { padding: 20px 22px; }
.card-title { margin: 0 0 3px; font-size: 15px; font-weight: 650; }
.card-sub { margin: 0 0 18px; font-size: 12.5px; color: var(--muted); }
.card-head {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--line);
}
.card-head input[type=search] {
  flex: 1 1 240px; max-width: 360px; font: inherit; font-size: 13px;
  padding: 7px 10px; border: 1px solid var(--line); border-radius: 8px;
}
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 0 16px; }
.form-grid.tight { margin-top: 14px; }
.form-acts { display: flex; gap: 8px; margin-top: 4px; }
.opt-list { display: flex; flex-direction: column; gap: 12px; margin: 6px 0 18px; }

/* --------------------------------------------------------------- tables */
.table-scroll { max-height: 62vh; overflow: auto; }
.table-scroll.grow { max-height: none; flex: 1; }
table.grid { width: 100%; border-collapse: collapse; font-size: 13px; }
table.grid th {
  position: sticky; top: 0; z-index: 1; background: #fbfcfe; text-align: left;
  padding: 9px 14px; border-bottom: 1px solid var(--line);
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
table.grid td { padding: 10px 14px; border-bottom: 1px solid var(--line-2); vertical-align: middle; }
table.grid tbody tr:hover { background: #fafbfe; }
table.grid td.when, table.grid td.num { white-space: nowrap; }
table.grid td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.grid th.num { text-align: right; }
table.grid td .sub { display: block; font-size: 11.5px; color: var(--muted); }
table.grid td.acts { text-align: right; white-space: nowrap; }
table.grid td.acts > * { margin-left: 5px; }

/* Only the narrow layout, which folds the columns away, wants this line.
   Scoped past "table.grid td .sub", which would otherwise show it. */
table.grid td .sub.rowmeta { display: none; }
@media (max-width: 720px) {
  table.grid td .sub.rowmeta { display: block; margin-top: 2px; }
}

.pager {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 14px; border-top: 1px solid var(--line); flex-wrap: wrap;
}
/* display:flex would otherwise win over the browser's own [hidden] rule. */
.pager[hidden] { display: none; }
.pager-acts { display: flex; align-items: center; gap: 10px; }
.pager button[disabled] { opacity: .45; cursor: default; }

.empty { padding: 44px 24px; text-align: center; }
.empty p { margin: 0 0 6px; }

.tag {
  margin-left: 6px; padding: 1px 6px; border-radius: 5px;
  font-size: 10.5px; font-weight: 600; color: var(--ok); background: #e7f4ec;
  vertical-align: 1px;
}
.tag.ref { color: var(--muted); background: #eceff4; font-style: normal; }

/* ------------------------------------------------------------ new drawing */
.drop {
  border: 1.5px dashed #c4d0e4; border-radius: var(--r);
  padding: 34px 20px; text-align: center; color: var(--muted);
  background: #fbfcfe; margin-bottom: 20px; transition: background .12s, border-color .12s;
}
.drop.over { border-color: var(--accent); background: var(--accent-soft); }
.drop svg { color: #91a5c4; }
.drop-title { margin: 10px 0 2px; font-size: 14.5px; color: var(--ink); font-weight: 550; }
.drop-sub { margin: 0; font-size: 12.5px; }

/* --------------------------------------------------------------- logo */
.logo-row { display: flex; gap: 16px; align-items: center; margin: 4px 0 18px; flex-wrap: wrap; }
.logo-box {
  width: 190px; height: 76px; border: 1px dashed var(--line); border-radius: var(--r);
  display: grid; place-items: center; overflow: hidden; background: #fbfcfe;
  font-size: 11.5px; color: var(--muted);
}
.logo-box img { max-width: 100%; max-height: 100%; }
.logo-acts { display: flex; flex-direction: column; gap: 7px; align-items: flex-start; }
.logo-acts p { margin: 0; max-width: 340px; }

/* ------------------------------------------------------------- the editor */
.chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.chip {
  background: #fff; border: 1px solid var(--line); border-radius: 999px;
  padding: 5px 12px; font-size: 12.5px; color: var(--ink-2);
}
.chip b { color: var(--ink); }
.chip.crit { color: var(--crit); border-color: #f0cccd; }
.chip.warnchip { background: var(--warn-bg); border-color: #f5d79a; color: var(--warn-ink); }

.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: 18px; align-items: start; }
@media (max-width: 1180px) { .split { grid-template-columns: 1fr; } }

.viewer-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 14px; border-bottom: 1px solid var(--line);
}
.viewer-head .check { min-width: 0; }
.viewer-head .check span { min-width: 0; }
.viewer-head .check em { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.viewer-head select {
  font: inherit; font-size: 13px; padding: 5px 9px;
  border: 1px solid var(--line); border-radius: 7px; background: #fff;
}
.zoom { margin-left: auto; display: flex; align-items: center; gap: 4px; }
.zoom button {
  width: 28px; height: 28px; padding: 0; justify-content: center;
  border: 1px solid var(--line); border-radius: 7px; background: #fff; cursor: pointer;
}
.zoom span { font-size: 12px; color: var(--muted); min-width: 36px; text-align: center; }

/* The canvas's own tools - inside .viewer, so full screen (which covers
   everything outside it) never cuts them off. */
.viewer-toolbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 14px; border-bottom: 1px solid var(--line); background: #fbfcfe;
}
.tool-btn { padding: 6px 11px; font-size: 12.5px; }
.tool-btn svg { flex: none; }
@media (max-width: 560px) { .tool-label { display: none; } }

.hint {
  margin: 0; padding: 9px 14px; font-size: 12.5px; color: var(--muted);
  background: #fbfcfe; border-bottom: 1px solid var(--line);
}
.hint b { color: var(--ink); }

.canvas { overflow: auto; max-height: 74vh; background: #eef1f6; padding: 14px; }
.canvas.adding { cursor: crosshair; }
.stage { position: relative; margin: 0 auto; background: #fff; box-shadow: var(--shadow); }
.stage img { display: block; width: 100%; height: auto; }
#handles, #markers, #brandBoxes, #viewBoxes { position: absolute; inset: 0; }
/* Both of these lie over the handles. Without this they swallow the pointer
   and no balloon can be dragged. */
#markers, #brandBoxes, #viewBoxes { pointer-events: none; }
#brandBoxes .brand-box { pointer-events: auto; }

.handle {
  position: absolute; transform: translate(-50%, -50%);
  border-radius: 50%; cursor: grab; touch-action: none; border: 2px solid transparent;
}
.handle:hover { border-color: rgba(26, 70, 184, .55); background: rgba(26, 70, 184, .1); }
.handle.dragging { cursor: grabbing; border-color: var(--accent); background: rgba(26, 70, 184, .18); }
.handle.moved { border-color: rgba(21, 115, 71, .5); border-style: dashed; }
/* A reference balloon is already drawn dashed and grey on the sheet, so its
   handle only changes what hovering it looks like. */
.handle.ref:hover { border-color: rgba(115, 115, 115, .7); background: rgba(115, 115, 115, .1); }
.handle.ref.dragging { border-color: #737373; background: rgba(115, 115, 115, .18); }
.canvas.adding .handle { pointer-events: none; }

.canvas.resequencing .handle { cursor: pointer; }
.handle.reseq-dim { opacity: .3; }
.handle.reseq-picked {
  display: flex; align-items: center; justify-content: center;
  border-color: var(--accent); border-style: solid; background: var(--accent);
  color: #fff; font-weight: 700; font-size: 12px; opacity: 1;
}

.marker {
  position: absolute; width: 34px; height: 34px; transform: translate(-50%, -50%);
  border: 2px solid var(--accent); border-radius: 50%;
  box-shadow: 0 0 0 4px rgba(26, 70, 184, .18); pointer-events: none;
}
.marker.crit { border-color: var(--crit); box-shadow: 0 0 0 4px rgba(196, 22, 28, .18); }

/* The block that will be removed. Dashed while it is only proposed, solid
   once it is actually being replaced on the print. */
.brand-box {
  position: absolute; border: 1.5px dashed rgba(180, 35, 35, .75);
  background: rgba(180, 35, 35, .07); cursor: grab; touch-action: none;
}
.brand-box.on { border-style: solid; background: rgba(180, 35, 35, .16); }
.brand-box.logo { border-width: 2px; }
.brand-box span {
  position: absolute; top: -17px; left: 0; white-space: nowrap;
  font-size: 10px; font-weight: 700; letter-spacing: .02em;
  color: #b42323; background: rgba(255, 255, 255, .92); padding: 1px 4px; border-radius: 3px;
}
.brand-box .drop {
  position: absolute; top: -9px; right: -9px; width: 18px; height: 18px;
  padding: 0; line-height: 1; border-radius: 50%; border: 1px solid #b42323;
  background: #fff; color: #b42323; font-size: 13px; cursor: pointer;
  display: grid; place-items: center; margin: 0;
}
.brand-box::after {
  content: ""; position: absolute; right: -1px; bottom: -1px; width: 11px; height: 11px;
  background: rgba(180, 35, 35, .75); cursor: nwse-resize;
}

/* A view/section's own border - detected automatically, never drawn by
   hand, never shown on its own. Invisible until the pointer is over it
   while resequencing, a cue for which section a click will land in. */
.view-box {
  position: absolute; pointer-events: none; background: transparent;
  transition: background .1s;
}
.view-box.hovered { background: rgba(26, 70, 184, .18); }

/* The balloon's own editor, opened by clicking it. It sits beside the balloon
   on the sheet, so the value and the thing it describes are read together. */
.char-pop {
  position: absolute; z-index: 6; width: 268px;
  display: flex; flex-direction: column; gap: 9px;
  background: #fff; border: 1px solid var(--line); border-radius: 11px;
  padding: 12px; box-shadow: 0 14px 40px rgba(15, 28, 48, .28);
  overflow-y: auto; overscroll-behavior: contain;
}
.viewer { position: relative; }
.pop-head { display: flex; align-items: baseline; gap: 2px; font-size: 14px; }
.pop-head .muted { font-size: 12px; }
.pop-x {
  margin-left: auto; border: none; background: none; cursor: pointer;
  font-size: 18px; line-height: 1; color: var(--muted); padding: 0 2px;
}
.pop-drawn, .pop-lim { margin: 0; font-size: 11.5px; }
.pop-nums { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; }
.char-pop .field span { font-size: 10px; }
.char-pop input[type=text], .char-pop input[type=number] {
  font: inherit; font-size: 13px; padding: 6px 8px; width: 100%;
  border: 1px solid var(--line); border-radius: 7px; background: #fff;
}
.char-pop input:focus { border-color: var(--accent); outline: none; }
.pop-acts { display: flex; align-items: center; gap: 7px; }
.pop-acts .grow { flex: 1; }
.btn.small { font-size: 12.5px; padding: 6px 12px; }

/* Right-click menu - fixed to the viewport (not .viewer's own scroll), so
   it opens at the cursor correctly whether the sheet is scrolled, zoomed,
   or the whole canvas is in full screen. */
.ctx-menu {
  position: fixed; z-index: 70; min-width: 168px;
  background: #fff; border: 1px solid var(--line); border-radius: 9px;
  padding: 5px; box-shadow: 0 14px 40px rgba(15, 28, 48, .3);
  display: flex; flex-direction: column;
}
.ctx-menu.hidden { display: none; }
.ctx-menu button {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 10px; border: none; background: none; border-radius: 6px;
  font: inherit; font-size: 13px; color: var(--ink); text-align: left; cursor: pointer;
}
.ctx-menu button:hover { background: var(--line-2); }
.ctx-menu button.danger { color: var(--crit); }
.ctx-menu button.danger:hover { background: #fdeaea; }
.ctx-menu svg { flex: none; }

/* The sheet on its own. The browser's full screen and the fallback class end
   up in the same layout, so the rules are written once for both. */
.viewer:fullscreen, body.viewer-max .viewer {
  border-radius: 0; border: none; width: 100%; height: 100%;
  display: flex; flex-direction: column; background: #fff;
}
body.viewer-max .viewer { position: fixed; inset: 0; z-index: 50; }
.viewer:fullscreen .canvas, body.viewer-max .canvas { max-height: none; flex: 1; }
.viewer:fullscreen .hint, body.viewer-max .hint { display: none; }

.reseq-banner {
  position: sticky; top: 0; z-index: 6;
  background: var(--accent); color: #fff; font-size: 13px; line-height: 1.4;
  padding: 10px 16px; margin: -14px -14px 14px;
  box-shadow: 0 2px 10px rgba(15, 28, 48, .2);
}
.reseq-banner.hidden { display: none; }
.reseq-banner b { font-weight: 700; }
.reseq-banner .reseq-status { display: block; margin-top: 2px; font-size: 12px; opacity: .9; }
.reseq-banner .reseq-exit {
  display: block; margin-top: 10px;
  background: #fff; border-color: #fff; color: var(--accent);
}
.reseq-banner .reseq-exit:hover { background: var(--line-2); }

.reseq-confirm-backdrop {
  position: fixed; inset: 0; z-index: 60; background: rgba(15, 28, 48, .4);
  display: flex; align-items: center; justify-content: center;
}
.reseq-confirm-backdrop.hidden { display: none; }
.reseq-confirm {
  background: #fff; border-radius: 12px; padding: 18px 20px; max-width: 320px;
  box-shadow: 0 20px 60px rgba(15, 28, 48, .35); text-align: center;
}
.reseq-confirm p { margin: 0 0 14px; font-size: 13.5px; color: var(--ink); }
.reseq-confirm .pop-acts { justify-content: center; }

.add-form {
  position: absolute; z-index: 5; display: flex; gap: 6px;
  transform: translate(-50%, calc(-100% - 12px));
  background: #fff; border: 1px solid var(--line); border-radius: 9px;
  padding: 7px; box-shadow: 0 8px 26px rgba(15, 28, 48, .22);
}
.add-form input {
  font: inherit; font-size: 13px; padding: 6px 8px;
  border: 1px solid var(--line); border-radius: 7px; min-width: 190px;
}
.add-form select {
  font: inherit; font-size: 13px; padding: 6px 8px;
  border: 1px solid var(--line); border-radius: 7px; background: #fff; cursor: pointer;
}
/* Sized to sit in a small popup, but never for the Add button itself: it
   carries .primary (accent background, white text) from the general button
   rules, and this used to have equal specificity and win on source order -
   white background over white text, so "Add" was there and clickable but
   never visible. */
.add-form button {
  font-size: 12.5px; padding: 6px 10px; border-radius: 7px;
}
.add-form button:not(.primary) {
  border: 1px solid var(--line); background: #fff; cursor: pointer;
}

.table-wrap { display: flex; flex-direction: column; max-height: 84vh; }
#charTable th, #charTable td { padding: 7px 9px; }
#charTable th { font-size: 10.5px; letter-spacing: .03em; }
#charTable td:first-child { font-weight: 700; width: 44px; }
/* The specification is elided when it is long, but the tags after it say
   whether the value was corrected or the balloon moved - so they keep their
   place and only the text gives way. */
td.spec { display: flex; align-items: center; gap: 2px; max-width: 210px; }
td.spec .spec-text {
  font-family: "SFMono-Regular", Consolas, monospace;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
td.spec .tag { flex: 0 0 auto; }
td.lim { color: var(--muted); white-space: nowrap; }
#charTable input[type=number] {
  width: 62px; padding: 3px 6px; border: 1px solid transparent; border-radius: 6px;
  font: inherit; font-size: 12.5px; text-align: right; background: transparent;
}
/* The spinners are no use for a dimension - nobody steps 111.5 up by one -
   and the space the browser reserves for them clipped values like "111.5"
   down to "111", which is a wrong number on screen. */
#charTable input[type=number] { appearance: textfield; -moz-appearance: textfield; }
#charTable input[type=number]::-webkit-outer-spin-button,
#charTable input[type=number]::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
#charTable input[type=number]:hover { border-color: var(--line); background: #fff; }
#charTable input[type=number]:focus { border-color: var(--accent); background: #fff; outline: none; }
/* A fixed width, not width:100% - the table has no table-layout:fixed, so a
   percentage here left the column's auto-computed width with nothing to
   resolve against and it collapsed to a few pixels, hiding the text behind
   an arrow with no room left to show it. */
#charTable select[data-f="char_type"] {
  width: 82px; padding: 3px 4px; border: 1px solid transparent;
  border-radius: 6px; font: inherit; font-size: 11px; background: transparent; cursor: pointer;
}
#charTable select[data-f="char_type"]:hover { border-color: var(--line); background: #fff; }
#charTable select[data-f="char_type"]:focus { border-color: var(--accent); background: #fff; outline: none; }
button.del {
  border: none; background: none; color: var(--muted); font-size: 15px;
  cursor: pointer; padding: 0 4px; line-height: 1;
}
button.del:hover { color: var(--crit); }

tr.view-row, tr.view-row:hover { background: #eef2f9; }
tr.view-row td { padding: 6px 10px; font-size: 11.5px; letter-spacing: .02em; }
tr.view-row span { font-weight: 700; text-transform: uppercase; }
tr.view-row em { font-style: normal; color: var(--muted); margin-left: 8px; }
tr.ref-head, tr.ref-head:hover { background: #f4f5f7; }
tbody tr.sel { background: var(--accent-soft) !important; }
tbody tr.crit td:first-child { color: var(--crit); }
/* A value that no longer matches the drawing is never silent in the app, even
   though the print carries it in the sheet's own lettering. */
.tag.edit { background: #fdf0d5; border-color: #f0d08a; color: #8a5a00; }
/* A reference dimension is shown, dimmed, so it is clearly a decision and
   not something the reader missed. */
tbody tr.ref td { color: var(--muted); font-style: italic; }
tbody tr.ref:hover { background: transparent; }
/* Nominal and the tolerances update the moment they're typed; Specification
   is a formatted string the server composes and can't be, so a row with an
   unconfirmed edit dims its old text rather than leave it sitting there
   looking finished and contradicting the numbers beside it. Clears itself -
   nothing sets this after a real server response is applied. */
tbody tr.pending td.spec .spec-text { opacity: .45; }
tbody tr.pending td.spec::after {
  content: ""; display: inline-block; width: 5px; height: 5px;
  margin-left: 6px; border-radius: 50%; background: var(--accent);
  animation: pulse 1.1s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: .25; } }

/* Type used to be read-only, and readable from the specification anyway
   ("Ø25" is plainly a diameter), so it gave way first on a narrower screen.
   It is now how a misread type gets corrected - Ø vs a plain diameter the
   sheet never marked - so it stays, and the row tightens elsewhere instead:
   trimmed padding, a narrower nominal/tolerance and a shorter type control. */
@media (max-width: 1599px) {
  #charTable th, #charTable td { padding: 7px 7px; }
  #charTable input[type=number] { width: 44px; }
  #charTable select[data-f="char_type"] { width: 68px; font-size: 10px; }
  td.spec { max-width: 100px; }
}
/* Narrower still: the limits are nominal plus and minus the two tolerances,
   all three of which are in the same row a few columns to the left, so that
   is the column to drop before anything that cannot be read off elsewhere. */
@media (max-width: 1400px) {
  #charTable th:nth-child(7), #charTable td:nth-child(7) { display: none; }
}

/* The reader's notes can run long on a scanned sheet. They are worth reading,
   but not at the price of the table they are about, so they are held to a
   few lines and scroll within themselves. */
.warn {
  margin: 0; padding: 11px 14px; color: var(--warn-ink); background: var(--warn-bg);
  font-size: 12.5px; border-top: 2px solid #f59e0b;
  max-height: 122px; overflow-y: auto; overscroll-behavior: contain;
}
.warn:empty { display: none; }

.meta-pane summary {
  cursor: pointer; font-weight: 700; font-size: 12.5px;
  text-transform: uppercase; letter-spacing: .03em;
}
.meta-pane summary .muted { font-weight: 400; text-transform: none; letter-spacing: 0; }
.meta-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 0 16px; margin-top: 14px;
}
.meta-read { margin: 6px 0 0; font-size: 12.5px; color: var(--muted); }
.meta-read b { color: var(--ink); margin-right: 6px; }
.notes-box { margin-top: 10px; font-size: 12.5px; color: var(--muted); }
.notes-box ol { margin: 4px 0 0; padding-left: 20px; }

/* --------------------------------------------------------- busy + toasts */
.busy {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  background: rgba(244, 246, 250, .72); backdrop-filter: blur(2px);
}
.busy p { margin: 14px 0 0; font-size: 13.5px; color: var(--ink-2); text-align: center; }
.spinner {
  width: 34px; height: 34px; border-radius: 50%; margin: 0 auto;
  border: 3px solid #d7deea; border-top-color: var(--accent);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.toasts {
  position: fixed; z-index: 70; right: 18px; bottom: 18px;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-end;
}
.toast {
  background: var(--navy); color: #fff; padding: 10px 14px; border-radius: 9px;
  font-size: 13px; max-width: 420px; box-shadow: 0 10px 30px rgba(15, 28, 48, .25);
  animation: rise .16s ease;
}
.toast.error { background: #8f1c1c; }
.toast.out { opacity: 0; transform: translateY(6px); transition: opacity .35s, transform .35s; }
.toast.undo { display: flex; align-items: center; gap: 10px; }
.toast-undo {
  background: rgba(255, 255, 255, .16); color: #fff; border: none; border-radius: 6px;
  padding: 4px 10px; font-size: 12.5px; font-weight: 600; cursor: pointer; flex: none;
}
.toast-undo:hover { background: rgba(255, 255, 255, .28); }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }

/* ------------------------------------------------------------- narrow */
@media (max-width: 900px) {
  .sidebar { transform: translateX(-100%); transition: transform .18s ease; width: var(--side); }
  body.menu-open .sidebar { transform: none; }
  body.menu-open .scrim {
    display: block; position: fixed; inset: 0; z-index: 25;
    background: rgba(15, 28, 48, .45);
  }
  .main, body.collapsed .main { margin-left: 0; }
  .topbar #menuBtn { display: inline-flex; }
  .views { padding: 16px 14px 28px; }
  .topbar { padding: 12px 14px; }
  .top-actions { gap: 6px; }
  .card.pad { padding: 16px; }
  .canvas { max-height: 60vh; }
}

/* On a phone the page's own buttons would otherwise stack four deep and push
   the drawing off the first screen, so the header becomes two rows and the
   actions scroll sideways within their own. */
@media (max-width: 720px) {
  .topbar {
    display: grid; grid-template-columns: auto 1fr; grid-template-areas: "menu titles" "acts acts";
    row-gap: 10px; column-gap: 12px; align-items: center;
  }
  .topbar #menuBtn { grid-area: menu; }
  .titles { grid-area: titles; }
  .top-actions {
    grid-area: acts; margin-left: 0; flex-wrap: nowrap; justify-content: flex-start;
    overflow-x: auto; overscroll-behavior-x: contain;
    /* the strip scrolls; its own scrollbar would only steal a line of height */
    scrollbar-width: none; padding-bottom: 1px;
  }
  .top-actions::-webkit-scrollbar { display: none; }
  .top-actions .btn { flex: 0 0 auto; font-size: 12.5px; padding: 7px 11px; }
  /* Room is too tight for the explanation beside a switch; the label carries it. */
  .viewer-head .check em { display: none; }
  /* A seven-column table cannot be read on a phone, so each drawing becomes a
     card instead: the part, then what the folded columns held, then the three
     things you came to press. */
  #histTable, #histTable tbody, #histTable tr, #histTable td { display: block; }
  #histTable thead { display: none; }
  #histTable tr { padding: 12px 14px; border-bottom: 1px solid var(--line-2); }
  #histTable td { padding: 0; border: none; }
  #histTable td:nth-child(1), #histTable td:nth-child(3),
  #histTable td:nth-child(4), #histTable td:nth-child(5) { display: none; }
  #histTable td.acts {
    display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-start;
    white-space: normal; margin-top: 10px;
  }
  #histTable td.acts > * { margin: 0; }
  #histTable td.acts .ghost.small { padding: 6px 10px; font-size: 12.5px; }
  table.grid td.acts > * { margin-left: 3px; }
  .chips { gap: 6px; }
  .chip { font-size: 12px; padding: 4px 10px; }
}

/* --------------------------------------------------------------- rates & costing */
.rate-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0 16px; }
.rate-grid.tight { margin-top: 14px; }

.cs-head { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0 16px; margin-bottom: 14px; }
.cost-grid td.num, .cost-grid th.num { text-align: right; }
.cost-indent { padding-left: 26px !important; }
.with-btn { display: flex; gap: 6px; align-items: center; }
.with-btn input { flex: 1; min-width: 0; }
