/* ===== Shared UI Components ===== */

/* ─── Scroll panel — standardized scrollable-box shell used by any fixed-height,
     internally-scrolling list/log (System Logs terminal, NC Deploy pending list, etc.).
     Callers set their own height/max-height and any content-specific styling (font, etc.). */
.scroll-panel {
  background: var(--surface);
  border: 1px solid var(--border); /* --cell-border-h is for table-cell dividers, not panel outlines */
  border-radius: 6px;
  overflow-y: auto;
  padding: 6px 10px;
}

/* ─── App toast ──────────────────────────────────────────────────────────────── */

.app-toast {
  position: fixed;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.5rem 1.2rem;
  border-radius: 4px;
  font-size: 0.85rem;
  z-index: var(--z-toast);
  pointer-events: none;
  animation: app-toast-fade 3.5s ease forwards;
  background: var(--success);
  color: var(--on-success);
}
.app-toast--error { background: var(--danger); color: var(--on-primary); animation-duration: 4.5s; }
.app-toast--info  { background: var(--primary); color: var(--on-primary); animation: none; opacity: 1; }

@keyframes app-toast-fade {
  0%   { opacity: 0; transform: translateX(-50%) translateY(8px); }
  12%  { opacity: 1; transform: translateX(-50%) translateY(0); }
  72%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ─── Page / section headers ─────────────────────────────────────────────────── */

.page-header { margin-bottom: 1.5rem; }

.page-header h2 {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 1.4rem;
  font-weight: 600;
  margin-bottom: 0.6rem;
}

.page-header h2 svg {
  flex-shrink: 0;
  color: var(--primary);
  opacity: 0.85;
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-4);
}

.section-header h3 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-sub);
}

.section-header h3 svg {
  flex-shrink: 0;
  color: var(--primary);
  opacity: 0.85;
}

.filter-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 13px;
  height: 13px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--checkbox-bg);
  cursor: pointer;
  flex-shrink: 0;
  position: relative;
  vertical-align: middle;
}
input[type="checkbox"]:checked {
  background: var(--primary);
  border-color: var(--primary);
}
input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 3px;
  top: 0px;
  width: 4px;
  height: 8px;
  border: 2px solid var(--on-primary);
  border-top: none;
  border-left: none;
  transform: rotate(45deg);
}
input[type="checkbox"]:disabled {
  background: var(--border);
  border-color: var(--border);
  opacity: 0.5;
  cursor: not-allowed;
}
input[type="checkbox"]:disabled:checked {
  background: var(--border);
  border-color: var(--border);
}

.filter-row input[type="text"],
.filter-row input[type="date"],
.filter-row input[type="datetime-local"],
.filter-row select {
  padding: 0.38rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 0.875rem;
  color: var(--text);
}

.filter-row input[type="text"] { min-width: 220px; background: var(--bg); }
.filter-row input[type="date"] { background: var(--bg); }
.filter-row input[type="datetime-local"] { background: var(--bg); }
.filter-row select { background: var(--bg); }

.filter-row label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.875rem;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
}

.filter-sep {
  width: 1px;
  height: 1.1rem;
  background: var(--border);
  flex-shrink: 0;
}

.filter-inline-label {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-muted);
  white-space: nowrap;
  cursor: default;
}

.header-actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-left: auto;
}

/* ─── Form row ───────────────────────────────────────────────────────────────── */

.form-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.75rem;
}

.form-row label {
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-sub);
  white-space: nowrap;
}

.form-row select {
  flex: 1;
  min-width: 240px;
}

.form-row input[type="text"],
.form-row input[type="password"] {
  flex: 1;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 0.875rem;
  background: var(--bg);
  color: var(--text);
}
.form-row input:focus,
.form-row select:focus { outline: none; border-color: var(--primary); }

.form-label-sm { min-width: 80px; }
.form-label-md { min-width: 110px; }

.form-error {
  color: var(--danger);
  font-size: 0.82rem;
  margin-top: 0.25rem;
}

.form-row-checkbox {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.input-short { max-width: 60px; }

/* Searchable select — text input + <select size> pair, filtered live via bindSearchableSelect().
   Used app-wide (materials, components, files, task assignees, worker pickers, etc.) — not
   specific to any one module. */
.search-select {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.search-select input[type="text"] {
  padding: 0.38rem 0.6rem;
  background: var(--bg);
}

.search-select select {
  padding: 0.25rem;
  /* Distinct from the paired search input above (--bg) — otherwise .form-field select's
     background override collapses both controls to the same flat shade */
  background: var(--surface);
}

/* ─── Kit/module-scoped entity header — Picker row (Model/Kit/Ext Rev/Int Rev [/Module]), Action
     row (import/export/domain-specific buttons, History last), and Identity+Lock row
     (.drill-header) stacked with one consistent spacing, instead of each screen picking its own
     margins. Shared by PQP, Design Sheet, and Nest Studio (any future kit-scoped checkout screen
     should reuse this too — see feedback_section_header_single_row: section_header only ever
     fits ONE row beside its title, so all three of these rows belong outside that call). */
.entity-header {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
}
.entity-header .drill-header {
  margin-bottom: 0; /* the flex gap above already spaces it — avoid doubling up with drill-header's own margin */
}
/* Extra breathing room below the action row specifically — the base gap alone read as too
   tight between a row of buttons and the identity/lock bar right underneath it */
.entity-header-actions {
  margin-bottom: var(--space-2);
}

/* ─── Drill-down breadcrumb — one persistent header per multi-step tab, replacing what used
     to be a separate boxed .selection-header per tab/step. */
.drill-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
  padding: 0.6rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 1px 4px var(--shadow-sm);
}

.drill-breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.15rem;
}

.crumb {
  background: none;
  border: none;
  padding: 0.15rem 0.35rem;
  border-radius: 3px;
  font-size: 0.9rem;
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.crumb:hover { background: var(--row-selected); color: var(--text); }
.crumb--current {
  color: var(--text);
  font-weight: 600;
  cursor: default;
}
.crumb--current:hover { background: none; }

/* Root crumb (e.g. "Models", "Accounting") — the top of the whole trail, styled a touch
   heavier than intermediate crumbs so the hierarchy's anchor point reads clearly. */
.crumb--root {
  font-weight: 600;
  color: var(--text-sub);
}
.crumb--root:hover { color: var(--text); }
.crumb--root.crumb--current { color: var(--text); }

.crumb-sep {
  margin: 0 0.15rem;
  color: var(--text-faint);
}

.group-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 1.5rem 0 0.5rem;
}
.group-label:first-child {
  margin-top: 0;
}

/* ─── Buttons ────────────────────────────────────────────────────────────────── */

/* Primal button shape — every labeled button (primary/secondary/danger) shares this; only
   color/border/hover-target vary by role. Primary keeps extra padding — the main CTA is meant
   to read as more prominent, a deliberate exception, not drift. */
.btn-primary,
.btn-secondary,
.btn-danger,
.btn-danger-sm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.38rem 0.8rem;
  border-radius: 4px;
  font-size: 0.875rem;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.btn-primary .icon-slot,
.btn-secondary .icon-slot,
.btn-danger .icon-slot { display: inline-flex; flex-shrink: 0; }

.btn-primary {
  background: var(--primary);
  color: var(--on-primary);
  border: none;
  padding: 0.5rem 1.25rem;
}
.btn-primary:hover { background: var(--primary-hover); }
.btn-primary:disabled { opacity: 0.5; cursor: default; }

.btn-secondary {
  background: var(--surface-deep);
  color: var(--text-muted);
  border: 1px solid var(--border);
}
.btn-secondary:hover { background: var(--row-selected); }
.btn-secondary:disabled { opacity: 0.5; cursor: default; }

.btn-danger {
  background: none;
  color: var(--danger);
  border: 1px solid transparent;
}
.btn-danger:hover {
  background: var(--danger-bg);
  border-color: var(--danger-border);
}

.btn-info:disabled,
.btn-edit:disabled,
.btn-danger:disabled,
.cut-dupe-btn:disabled {
  opacity: 0.5;
  cursor: default;
}

/* Primal inline row-action shape — every faint icon-only per-row button shares this;
   only the hover color (default/danger/primary) varies via the modifier classes below. */
.btn-edit,
.btn-info,
.btn-duplicate,
.cut-dupe-btn,
.btn-kit-export,
.btn-kit-import,
.btn-release,
.op-stats-info-btn,
.cut-qty-reset,
.btn-pseudo-mat,
.btn-pseudo-mat-revert,
.btn-delete,
.btn-remove-note,
.btn-remove-customer,
.btn-bom-info,
.pkg-cell-pencil,
.btn-row-info,
.btn-nc-files {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 1rem;
  color: var(--text-faint);
  padding: 0.1rem 0.3rem;
  margin: 0 0.2rem;
  border-radius: 3px;
  line-height: 1;
  transition: color 0.15s, background 0.15s;
}

/* Default hover: text + row-selected tint */
.btn-edit:hover,
.btn-info:hover,
.btn-duplicate:hover,
.cut-dupe-btn:hover,
.btn-kit-export:hover,
.btn-kit-import:hover,
.btn-release:hover,
.op-stats-info-btn:hover,
.cut-qty-reset:hover,
.btn-pseudo-mat:hover,
.btn-pseudo-mat-revert:hover,
.btn-nc-files:hover {
  color: var(--text);
  background: var(--row-selected);
}
.btn-pseudo-mat,
.btn-pseudo-mat-revert {
  font-size: 0.8rem;
  vertical-align: middle;
}

/* Danger hover: destructive actions */
.btn-delete:hover,
.btn-remove-note:hover,
.btn-remove-customer:hover {
  color: var(--danger);
  background: var(--danger-bg);
}

/* Primary hover: edit/duplicate affordances (some anchored/absolute — see bom.css / production.css) */
.btn-bom-info:hover,
.pkg-cell-pencil:hover,
.btn-row-info:hover {
  color: var(--primary);
  background: var(--row-selected);
}

.btn-sm {
  padding: 0.2rem 0.55rem;
  font-size: 0.7rem;
}

/* Check In — same footprint as btn-sm (matches Check Out) so the two don't visibly swap sizes
   as a document goes from unlocked to checked-out-by-you */
.btn-check-in {
  padding: 0.2rem 0.55rem;
  font-size: 0.7rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

/* Inline icon-only button (e.g. row check-out/check-in/discard/force-release, rename pencil) —
   shared across module sheets, packaging sheets, BOM kits, and quotes */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  cursor: pointer;
  color: var(--text-muted);
  padding: 0.15rem 0.35rem;
  font-size: 0.85rem;
  line-height: 1;
  transition: background 0.1s, border-color 0.1s, color 0.1s;
}
.btn-icon:hover { background: var(--row-selected); border-color: var(--border); color: var(--text); }

/* Icon-only action buttons (accept / reject) */
.btn-icon-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border: none;
  border-radius: 4px;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  line-height: 1;
  margin-right: 0.2rem;
}
.btn-accept { background: var(--accept-bg);      color: var(--success); }
.btn-reject { background: var(--reject-bg);      color: var(--danger); }
.btn-accept:hover { background: var(--accept-bg-hover); }
.btn-reject:hover { background: var(--reject-bg-hover); }
.btn-export { background: var(--export-bg);      color: var(--accent); }
.btn-export:hover { background: var(--export-bg-hover); }
.btn-tooltip-toggle { background: var(--surface); color: var(--text-muted); font-style: italic; }
.btn-tooltip-toggle:hover { background: var(--surface-deep); }
.btn-tooltip-toggle.active { background: var(--export-bg); color: var(--accent); }
.td-last-info { position: relative; padding-right: 22px !important; }
.btn-row-info { position: absolute; top: 50%; right: 4px; transform: translateY(-50%); visibility: hidden; }
tr:hover .btn-row-info { visibility: visible; }

/* ─── Status chip archetype ──────────────────────────────────────────────────── */
/* One shape/radius/size for "current state of this entity" indicators, color coming only from
   a variant class. New call sites should use this instead of inventing another badge shape —
   see static/js/utils.js's chip() and _macros.html's chip() for the JS/Jinja constructors.
   Existing .badge/.status-badge/etc. below are pre-existing call sites, not yet migrated. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  border-radius: var(--radius-pill);
  padding: 0.15rem 0.6rem;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
}
.chip--neutral     { background: var(--surface-deep); color: var(--text-muted); }
.chip--success     { background: var(--success-bg);   color: var(--success); }
.chip--warning     { background: var(--warning-bg);   color: var(--warning); }
.chip--danger      { background: var(--danger-bg);    color: var(--danger); }
.chip--info        { background: var(--info-bg);      color: var(--info-color); }
.chip--exceptional { background: var(--exceptional-bg); color: var(--exceptional-color); }
/* For chips sitting on an already-tinted surface, where a filled pill reads as too heavy
   (e.g. the BOM hierarchy step's "current" state) */
.chip--outline { background: transparent; border: 1.5px solid currentColor; }
.chip .chip-icon { font-size: 0.85em; line-height: 1; }

/* ─── Badges ─────────────────────────────────────────────────────────────────── */

.badge {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  border-radius: 12px;
  font-size: 0.75rem;
  font-weight: 500;
}

.badge-active       { background: var(--success-bg); color: var(--success); }
.badge-inactive     { background: var(--danger-bg);  color: var(--danger); }
.badge-assembled    { background: var(--assembled-bg);   color: var(--assembled-color); }
.badge-flagged      { background: var(--warning-bg);        color: var(--warning); }

/* Generic status badge — shared base with quality-badge */
.status-badge,
.quality-badge {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 700;
  padding: 0.1rem 0.45rem;
  border-radius: 10px;
}

.badge-muted   { background: var(--surface-deep); color: var(--text-muted); }
.badge-system  { background: var(--info-bg); color: var(--info-color); }
.badge-warning { background: var(--badge-warning-bg); color: var(--warning); }
.badge-success { background: var(--badge-success-bg); color: var(--success); }
.badge-danger  { background: var(--badge-danger-bg);  color: var(--danger); }

.quality-badge.open     { background: var(--badge-danger-bg); color: var(--danger); }
.quality-badge.resolved { color: var(--text-muted); }

/* ─── Avatar ─────────────────────────────────────────────────────────────────── */
/* Initials circle for a user — id picks a deterministic color from _AVATAR_COLOR_VARS (see
   static/js/utils.js's avatarHtml()), so the same person always gets the same color rather
   than a fresh random one per render. Pair with assigneeTag() for "who's assigned" everywhere
   an assignee/approver/checkout owner is shown — don't hand-roll a bespoke circle per screen. */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--on-primary);
}
.avatar--sm { width: 18px; height: 18px; font-size: 0.56rem; }
.avatar--unassigned {
  background: var(--surface-deep);
  color: var(--text-faint);
  border: 1px dashed var(--border);
}

.assignee-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.875rem;
  color: var(--text-sub);
}
.assignee-tag--unassigned { color: var(--text-faint); font-style: italic; }

/* Compact inline assignee picker — for tables that let you (re)assign in place instead of
   opening a full edit modal just to change who's responsible */
.assignee-select {
  font-size: 0.8rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg);
  color: var(--text);
  padding: 0.2rem 0.4rem;
}

/* ─── Row highlight + table loading ──────────────────────────────────────────── */

tr.row-highlight td {
  background: var(--row-selected) !important;
  border-right-color: transparent !important;
}

.table-wrap-loading { position: relative; }
.table-wrap-loading::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--surface);
  opacity: 0.7;
  z-index: var(--z-raise-2);
}
.table-wrap-loading-label {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.78rem;
  color: var(--text-muted);
  z-index: var(--z-raise-3);
  pointer-events: none;
}

/* ─── Data table ─────────────────────────────────────────────────────────────── */

.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: 6px;
  margin-bottom: 2rem;
}

.data-table {
  width: 100%;
  min-width: 520px;
  border-collapse: collapse;
  background: var(--surface);
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 1px 4px var(--shadow-md);
}

.data-table:not(.grid-table) {
  background: var(--table-surface);
}


.data-table thead {
  background: var(--navbar-bg);
  color: var(--navbar-text);
  border-bottom: 1px solid var(--border);
}

.data-table th {
  text-align: center;
  padding: 0.65rem 0.9rem;
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.data-table td {
  padding: 0.6rem 0.9rem;
  border-bottom: 1px solid var(--border);
  color: var(--text-sub);
  text-align: center;
  font-size: 0.875rem;
}

.data-table:not(.grid-table) td {
  border-bottom: 1px solid var(--cell-border-h);
}

.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover { background: var(--row-hover); cursor: pointer; }
.data-table tbody tr.row-soft-selected { background: var(--row-hover); }

.data-table tbody tr.row-highlight td {
  background: var(--row-selected);
  outline: 2px solid var(--primary);
  outline-offset: -2px;
  transition: background 2s ease, outline-color 2s ease;
}

/* Vertical divider marking the end of a header/column group (e.g. Nominal vs Measured
   sections in a grouped table) — apply to the last th/td in each group, header and body alike */
.data-table .col-group-end {
  border-right: 2px solid var(--cell-border-v) !important;
}

/* Group-divider row — e.g. subkit sections in the PQP parts table */
.data-table tbody tr.group-divider-row:hover { cursor: default; }
.data-table tbody tr.group-divider-row td {
  background: var(--navbar-bg);
  color: var(--navbar-text);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.8rem;
  text-align: center;
}

/* PQP-specific delta/flag rules live in quality.css — .pqp-field-badge below stays here since
   Design Sheet reuses the same class for its own inline-edit validation badges */

/* PQP invalid-value badge â€” sits next to a parameter input whose current text isn't a valid
   number; tooltip (title attr) names the problem */
.pqp-field-badge {
  display: inline-block;
  margin-left: 0.25rem;
  color: var(--danger);
  cursor: help;
  font-size: 0.85rem;
}
.pqp-field-badge.hidden {
  display: none;
}

/* Sortable column headers */
.th-sort { cursor: pointer; user-select: none; white-space: nowrap; }
.th-sort::after {
  content: '';
  display: inline-block;
  width: 0.8em;
  margin-left: 0.3em;
  opacity: 0.3;
}
.th-sort.th-sort-active::after { opacity: 1; }
.th-sort.th-sort-active[data-dir="asc"]::after  { content: '↑'; }
.th-sort.th-sort-active[data-dir="desc"]::after { content: '↓'; }

/* Section separator between stacked tables */
.section-sep {
  margin: 1.75rem 0 0;
  border: none;
  border-top: 1px solid var(--border-light);
  padding-top: 1.75rem;
}

/* Column helpers */
.col-action { width: auto; text-align: center; white-space: nowrap; vertical-align: middle; }
td.col-action > * + * { margin-left: 0.2rem; }
thead .col-action { background: var(--navbar-bg); }

/* Bulk-select checkbox column */
th.col-check, td.cell-check {
  width: 2rem;
  text-align: center;
  vertical-align: middle;
  padding: 0 0.25rem;
}
thead th.col-check { background: var(--navbar-bg); }

/* Drag-to-reorder handle column — paired with static/js/drag_reorder.js; applies to both table
   rows and non-table row lists (e.g. a repeatable div-row list inside a modal) */
.col-drag {
  width: 28px;
  padding: 0 4px !important;
}

.drag-handle {
  cursor: grab;
  color: var(--text-faint);
  font-size: 0.85rem;
  user-select: none;
  display: block;
  text-align: center;
}

.drag-handle:active { cursor: grabbing; }

tr.dragging, .tpl-item-row.dragging { opacity: 0.35; }

tr.drop-above > td { box-shadow: 0 -2px 0 0 var(--primary); }
.tpl-item-row.drop-above { box-shadow: 0 -2px 0 0 var(--primary); }

/* Bulk action buttons that appear in the filter-row when rows are selected */
.bulk-actions { display: flex; gap: 0.4rem; align-items: center; }
.bulk-actions.hidden { display: none; }
.btn-danger-sm {
  background: transparent;
  border: 1px solid var(--danger-border);
  color: var(--danger);
}
.btn-danger-sm:hover { background: var(--danger); color: var(--on-primary); }
.col-date   { white-space: nowrap; color: var(--text-faint); font-size: 0.8rem; }
.col-nowrap { white-space: nowrap; }
.col-truncate {
  max-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-muted);
}

/* ─── Status / empty states ──────────────────────────────────────────────────── */

.status-text {
  color: var(--text-faint);
  font-size: 0.875rem;
  margin-bottom: 0.75rem;
  min-height: 1.2em;
}

/* ─── Disclaimer banner — small muted notice above a table/section ── */

.disclaimer-banner {
  font-size: 0.8rem;
  color: var(--text-muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.75rem;
}

/* ─── Checkout banner — check-in/check-out lock indicator (quote, engineering) ── */

.checkout-banner {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.65rem;
  border-radius: 12px;
  font-size: 0.8rem;
  font-weight: 500;
}

.checkout-banner::before {
  font-size: 0.85rem;
}

.checkout-banner--mine {
  background: var(--success-bg);
  color: var(--success);
}
.checkout-banner--mine::before {
  content: "\1F513\FE0E"; /* unlocked padlock, text/mono presentation */
}

.checkout-banner--locked {
  background: var(--warning-bg);
  color: var(--warning);
}
.checkout-banner--locked::before {
  content: "\1F512\FE0E"; /* padlock, text/mono presentation */
}

/* Mandatory-checkout hint (see createCheckoutController's mandatoryCheckout option) — neutral,
   not a warning, since nobody holds the document; it's just informing you what's required to edit */
.checkout-banner--hint {
  background: color-mix(in srgb, var(--text-faint) 15%, transparent);
  color: var(--text-faint);
}

/* Historical kit BOM snapshot viewer — "you're looking, not editing," distinct from
   --locked (which means someone else could edit it, just not you) */
.checkout-banner--snapshot {
  background: color-mix(in srgb, var(--text-faint) 15%, transparent);
  color: var(--text-faint);
  position: sticky;
  top: 0;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 0.75rem;
}
.checkout-banner--snapshot::before {
  content: "\1F441\FE0E"; /* eye, text/mono presentation */
}

/* Snapshot mode's drill-header sits directly above the read-only banner — shrink its usual gap so the two don't read as two separately-spaced blocks */
.snapshot-mode #bom-drill-header {
  margin-bottom: 0.75rem;
}

/* ─── Collapsible side panel — same mechanics as nc_deploy.css's .nc-encode-panel; kept here as
   the shared generic version since a second tab (Documents) now needs the identical pattern ── */

.collapsible-panel {
  flex-shrink: 0;
  width: 320px;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  transition: width 0.15s ease;
}

.collapsible-panel.collapsed {
  width: 2.5rem;
}
.collapsible-panel.collapsed .collapsible-panel-header h4,
.collapsible-panel.collapsed .collapsible-panel-body {
  display: none;
}

.collapsible-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.collapsible-panel-header h4 {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-sub);
}

.collapsible-panel-body {
  padding: 1rem;
  overflow-y: auto;
}

.btn-collapse-panel {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: 1rem;
  width: 1.5rem;
  height: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  flex-shrink: 0;
}
.btn-collapse-panel:hover {
  background: var(--row-hover);
  color: var(--text);
}

/* Wraps a rendered snapshot tree — desaturated tint is the "this is frozen" signal; no
   edit affordances are ever rendered inside a snapshot view, so unlike .kit-locked there's
   nothing to display:none here */
.snapshot-mode {
  filter: grayscale(0.85) saturate(0.4);
}

/* One collapsible level of a check-in diff (renderFieldChanges in utils.js) — every field/
   child-collection group folds independently, closed by default, so a deep change doesn't dump
   every nesting level expanded at once. Compact vs. .history-entry since these can nest several
   levels deep (e.g. builds -> modules -> files). */
.diff-nest > summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.diff-nest > summary::-webkit-details-marker {
  display: none;
}
.diff-nest > summary::before {
  content: '\25B8';
  display: inline-block;
  width: 1rem;
  text-align: center;
  margin-right: 0.3rem;
  font-size: 0.75rem;
  transition: transform 0.15s ease;
}
.diff-nest[open] > summary::before {
  transform: rotate(90deg);
}

/* ─── Kit-locked BOM sections — hide structural edit affordances while a kit (or one of
   its builds) is checked out by another user; the write is already blocked server-side,
   this just avoids a dead-end click ── */
.kit-locked .btn-edit,
.kit-locked .btn-delete,
.kit-locked .btn-duplicate,
.kit-locked [data-kit-edit-only],
.kit-locked th.col-check,
.kit-locked td.cell-check,
.kit-locked .bulk-actions {
  display: none !important;
}

.empty-state {
  text-align: center;
  padding: 3rem;
  color: var(--text-faint);
  background: var(--table-surface);
  border-radius: 6px;
  box-shadow: 0 1px 4px var(--shadow-md);
}

/* ─── Range slider ───────────────────────────────────────────────────────────── */

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  height: 4px;
  background: var(--border);
  border-radius: 2px;
  outline: none;
  cursor: pointer;
  vertical-align: middle;
}

input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: var(--border);
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--primary);
  cursor: pointer;
  border: none;
  box-shadow: 0 1px 3px var(--shadow-md);
  margin-top: -5px;
}

input[type="range"]::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: var(--border);
}

input[type="range"]::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--primary);
  cursor: pointer;
  border: none;
  box-shadow: 0 1px 3px var(--shadow-md);
}

input[type="range"]:focus-visible::-webkit-slider-thumb {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* ─── Shared overlay backdrop ────────────────────────────────────────────────── */

#loading-overlay,
.modal-overlay,
.login-overlay,
.op-feedback-overlay,
.op-review-overlay,
.op-event-panel-overlay {
  position: fixed;
  inset: 0;
  background: var(--overlay);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ─── Loading overlay ────────────────────────────────────────────────────────── */

#loading-overlay {
  z-index: var(--z-toast);
}
#loading-overlay.hidden { display: none; }

.loading-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 2rem 2.5rem;
  text-align: center;
  min-width: 240px;
}

.loading-spinner {
  width: 36px;
  height: 36px;
  border: 3px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  margin: 0 auto 1rem;
}

.spinner-sm {
  display: inline-block;
  width: 11px;
  height: 11px;
  border: 2px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  vertical-align: middle;
  margin-right: 0.4rem;
}

@keyframes spin { to { transform: rotate(360deg); } }

@keyframes row-highlight-fade {
  0%   { background-color: var(--warning-highlight); }
  100% { background-color: transparent; }
}
.row-highlight { animation: row-highlight-fade 2.5s ease-out forwards; }

#loading-message {
  font-weight: 600;
  font-size: 0.95rem;
  margin: 0 0 0.25rem;
}
.loading-sub {
  font-size: 0.78rem;
  color: var(--text-faint);
  margin: 0;
}

/* ─── Modal ──────────────────────────────────────────────────────────────────── */

.modal-overlay {
  z-index: var(--z-panel);
}

.modal {
  background: var(--surface);
  border-radius: 8px;
  width: 520px;
  max-width: 95vw;
  box-shadow: 0 8px 32px var(--shadow-lg);
}
.modal-sm { width: 340px; }
.modal-lg { width: 820px; }
.modal-xl { width: 1100px; max-width: 95vw; }

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.25rem 0.75rem;
  border-bottom: 1px solid var(--border-light);
}
.modal-header h3 { font-size: 1rem; font-weight: 600; color: var(--text); }

.modal-close {
  background: none;
  border: none;
  font-size: 1.4rem;
  cursor: pointer;
  color: var(--text-faint);
  line-height: 1;
}
.modal-close:hover { color: var(--text-sub); }

.modal-body {
  padding: 1.25rem;
  max-height: 62vh;
  overflow-y: auto;
}

.modal-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1.25rem 1rem;
  border-top: 1px solid var(--border-light);
}
.modal-footer-right { display: flex; gap: 0.75rem; }

.modal-error {
  margin-top: 0.75rem;
  padding: 0.6rem 0.75rem;
  background: var(--danger-bg);
  border: 1px solid var(--danger-border);
  border-radius: 4px;
  color: var(--danger);
  font-size: 0.85rem;
  font-weight: 600;
}

/* ─── Form fields ────────────────────────────────────────────────────────────── */

.form-section-label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  margin: 1rem 0 0.4rem;
}

.form-section-title,
.info-section-title {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text);
  padding: 0.75rem 0 0.3rem;
  border-bottom: 2px solid var(--primary);
  margin-bottom: 0.75rem;
}
.info-section-title { padding: 0.6rem 0 0.2rem; margin-bottom: 0.2rem; }

.form-field { margin-bottom: 0.9rem; }

.form-field label {
  display: block;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-muted);
  margin-bottom: 0.3rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* De-emphasized aside inside a .form-field label — e.g. "(hold Ctrl to select multiple)" */
.label-hint {
  font-weight: 400;
  color: var(--text-faint);
}

.form-field input[type="text"],
.form-field input[type="number"],
.form-field input[type="date"],
.form-field select,
.form-field textarea {
  width: 100%;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 0.875rem;
  background: var(--bg);
  color: var(--text);
}
.form-field textarea { font-family: inherit; resize: vertical; }
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus { outline: none; border-color: var(--primary); }

/* Read-only counterpart to a .form-field input/select — same box weight (border + --bg fill)
   so a view/edit toggle (e.g. engineering change ECR/ECO) doesn't flatten into bare text against
   the surrounding panel when not editable. */
.form-field .field-value {
  width: 100%;
  min-height: 1.9rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 0.875rem;
  background: var(--bg);
  color: var(--text);
  box-sizing: border-box;
}

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1rem;
}

/* A .form-field that should span both .form-grid columns */
.form-field-wide { grid-column: span 2; }

.form-checks {
  display: flex;
  gap: 1.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border-light);
  margin-top: 0.5rem;
}
.form-checks label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.875rem;
  color: var(--text-muted);
  cursor: pointer;
}

/* ─── Info grid ──────────────────────────────────────────────────────────────── */

.info-grid {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.info-row {
  display: flex;
  justify-content: space-between;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--border-light);
}

.info-label { font-weight: 600; color: var(--text-muted); }
.info-value { color: var(--text-sub); }

.info-block {
  font-size: 0.8rem;
  color: var(--text-sub);
  line-height: 1.5;
  padding: 0.5rem 0.75rem;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
}

/* ─── Login card ─────────────────────────────────────────────────────────────── */

.login-overlay {
  z-index: var(--z-login);
}

.login-card {
  background: var(--surface);
  border-radius: 10px;
  width: 340px;
  max-width: 95vw;
  padding: 2rem;
  box-shadow: 0 8px 32px var(--shadow-lg);
  text-align: center;
}
.login-card .form-field label { text-align: left; }

.login-input {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.875rem;
  background: var(--bg);
  color: var(--text);
  transition: border-color 0.15s;
  text-align: left;
}
.login-input:focus {
  outline: none;
  border-color: var(--navbar-bg);
  box-shadow: 0 0 0 2px rgba(26,26,46,0.12);
}

.login-error {
  font-size: 0.825rem;
  color: var(--danger);
  min-height: 1.2em;
  margin-bottom: 0.5rem;
  text-align: center;
}

/* ─── Palette items ──────────────────────────────────────────────────────────── */

.prod-palette-item,
.pkg-palette-item,
.bom-palette-item {
  font-size: 0.8rem;
  cursor: grab;
  border-radius: 4px;
  background: var(--surface-deep); /* inset against the --surface panel, not flush with it */
  user-select: none;
  transition: background 0.1s, border-color 0.1s;
}

/* ─── Palette sidebars ───────────────────────────────────────────────────────── */

.prod-file-palette,
.pkg-palette,
.bom-part-palette {
  border-radius: 6px;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 9.5rem; /* floor beneath the ResizeObserver max-height sync so the list stays at ~2 items */
}

/* ─── Searchable combobox (archetype) ────────────────────────────────────────── */
/* Canonical text-search-to-pick widget — see static/js/shared/combo.js for the logic this pairs
   with. Markup: .combo > .combo-input-wrap > (.combo-input + optional .combo-clear), .combo-panel */

.combo { position: relative; }
.combo--md { width: 220px; }

.combo-input-wrap { position: relative; display: flex; align-items: center; }

.combo-input {
  width: 100%;
  box-sizing: border-box;
  padding: 0.45rem 2rem 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.875rem;
  font-family: inherit;
}
.combo-input:focus { outline: none; border-color: var(--primary); }
.combo.is-selected .combo-input { border-color: var(--success); }

.combo-clear {
  position: absolute;
  right: 0.35rem;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  border: none;
  background: none;
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
}
.combo-clear:hover { background: var(--row-hover); color: var(--danger); }
.combo.is-selected .combo-clear { display: flex; }

.combo-panel {
  position: absolute;
  top: calc(100% + 3px);
  left: 0;
  right: 0;
  z-index: var(--z-dropdown);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.12);
  max-height: 220px;
  overflow-y: auto;
  list-style: none;
  margin: 0;
  padding: 4px;
  display: none;
}
.combo-panel.is-open { display: block; }

.combo-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.55rem;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--text);
}
.combo-row:hover, .combo-row.is-active { background: var(--row-hover); }
.combo-row.is-empty { color: var(--text-muted); cursor: default; font-style: italic; }
.combo-row.is-empty:hover { background: transparent; }
.combo-row .sub { color: var(--text-muted); font-size: 0.75rem; margin-left: auto; }

/* Nest Studio sheet viewer — read-only SVG of part outlines + label placement */
.nest-browser-grid {
  display: grid;
  grid-template-columns: 1fr 22rem;
  grid-template-areas:
    "nav    ."
    "canvas info";
  column-gap: 1.5rem;
}
.nest-browser-nav { grid-area: nav; align-items: center; justify-content: center; margin: 0.75rem 0; }
.nest-browser-canvas { grid-area: canvas; }
.nest-browser-info { grid-area: info; margin-bottom: 2rem; }
/* Fixed height (not min-height) so the container never resizes between loading and loaded
   states, or between sheets of different aspect ratios — the SVG's default preserveAspectRatio
   (xMidYMid meet) centers/contains the sheet within this fixed box instead */
.nest-viewer-wrap { margin: 0 0.5rem 2rem; height: 60vh; }
.nest-viewer-loading { height: 100%; display: flex; align-items: center; justify-content: center; gap: 0.5rem; }
.nest-sheet-svg { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 1rem; box-sizing: border-box; }
.nest-part-outline {
  fill: var(--surface-deep); /* inset against the --surface sheet, not flush with it */
  stroke: var(--border); /* --text-muted is too faint to read as a shape edge */
  stroke-width: 1; /* bumped from 0.5 so the boundary stays visible */
  transition: filter 0.1s;
}
.nest-part-selectable { cursor: pointer; }
.nest-part-selectable:hover .nest-part-outline { filter: drop-shadow(0 0 3px var(--primary)) drop-shadow(0 0 3px var(--primary)); }
.nest-part-selectable--selected .nest-part-outline { fill: var(--primary); fill-opacity: 0.25; stroke: var(--primary); stroke-width: 1.2; }
.nest-part-label { fill: var(--text); font-family: monospace; }
.nest-part-label-group--draggable { cursor: grab; touch-action: none; }
.nest-part-label-group--dragging { cursor: grabbing; }
.nest-part-label-group--dragging .nest-part-label { fill: var(--primary); }
.nest-sheet-outline { fill: none; stroke: var(--primary); stroke-width: 1; stroke-dasharray: 6 4; }
.nest-position-label { min-width: 14rem; text-align: center; font-size: 1.1rem; }
.nest-part-base-outline { fill: none; stroke: var(--accent); stroke-width: 0.5; stroke-dasharray: 4 3; }
.nest-part-inset-line { stroke: #b91c1c; stroke-width: 2; }
.nest-legend-box {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.6rem;
  font-size: 0.75rem;
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.nest-legend-swatch {
  display: inline-block;
  width: 1rem;
  height: 0;
  border-top: 2px solid;
  margin-right: 0.35rem;
  vertical-align: middle;
}
.nest-legend-swatch--surface { border-top-style: solid; border-top-color: var(--text-muted); }
.nest-legend-swatch--base { border-top-style: dashed; border-top-color: var(--accent); }
.nest-legend-swatch--sheet { border-top-style: dashed; border-top-color: var(--primary); }
.nest-legend-swatch--inset { border-top-style: solid; border-top-color: #b91c1c; }
.nest-file-info-card {
  background: var(--surface);
  border: var(--panel-border-width) solid var(--border);
  border-radius: 8px;
  padding: 1rem 1.25rem;
  height: 60vh;
  overflow-y: auto;
  box-sizing: border-box;
}
/* The card's own background is var(--surface), not var(--bg) — so the tab-bar sits on a
   var(--surface-deep) strip instead (visibly distinct from the card body either way it's
   scrolled to), and the active tab matches the card's actual content background rather than
   the page's, which is what it's supposed to blend into. */
.nest-file-info-card .tab-bar {
  background: var(--surface-deep);
  margin: -1rem -1.25rem 0.75rem;
  padding: 0.5rem 1.25rem 0;
  border-radius: 8px 8px 0 0;
}
.nest-file-info-card .tab-btn.active {
  background: var(--surface);
  border-bottom-color: var(--surface);
}
.nest-parts-list-header {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0 0 0.3rem;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
}
.nest-parts-list { list-style: none; margin: 0; padding: 0; }
.nest-parts-list li {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
}
.nest-parts-list li:last-child { border-bottom: none; }
.nest-parts-list .nest-part-segment { color: var(--text-muted); text-transform: capitalize; }
.nest-detail-component-row { background: var(--surface); font-weight: 600; }
.nest-detail-selected-row { background: var(--primary); background: color-mix(in srgb, var(--primary) 12%, transparent); }

/* ─── Layout utilities (column widths, common flex rows) ────────────────────── */
/* Replaces repeated inline style="width:Npx" on table header/cells across templates */
.col-w-60  { width: 60px; }
.col-w-70  { width: 70px; }
.col-w-75  { width: 75px; }
.col-w-80  { width: 80px; }
.col-w-90  { width: 90px; }
.col-w-100 { width: 100px; }
.col-w-110 { width: 110px; }
.col-w-120 { width: 120px; }
.col-w-130 { width: 130px; }
.col-w-140 { width: 140px; }
.col-w-150 { width: 150px; }
.col-w-160 { width: 160px; }

/* Small inline flex row — icon + label groups, etc. */
.flex-row-sm { display: flex; align-items: center; gap: 0.4rem; }

/* Standard top gap for a form-grid/info-grid that follows a section header */
.section-gap-top { margin-top: 1rem; }
.section-gap-top-sm { margin-top: 0.5rem; }
.section-gap-top-lg { margin-top: 1.5rem; }

/* Right-aligned inline button row — stage/view nav controls, etc. */
.inline-nav-right { margin-left: auto; display: flex; gap: 0.5rem; align-items: center; }

/* ─── Chooser card ───────────────────────────────────────────────────────────── */
/* Clickable "pick a sub-page" tile: icon + name + description. Used across
   Production/Engineering/Design/Quality/Quote/System — not module-specific,
   hence living here rather than in any one module's CSS file. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  max-width: 560px;
  margin-top: 1rem;
}

.card {
  padding: 1.5rem 1.75rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.card:hover {
  border-color: var(--primary);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.07);
}

.card--disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

.card--disabled:hover {
  border-color: var(--border);
  box-shadow: none;
}

.card-name {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  font-size: 1rem;
  margin-bottom: 0.4rem;
}

.card-name svg {
  flex-shrink: 0;
  color: var(--primary);
  opacity: 0.85;
}

.card-desc {
  font-size: 0.825rem;
  color: var(--text-muted);
  line-height: 1.4;
}

/* ─── History entry — collapsible <details> row for a single document check-in, used by every
     "History" modal (kit BOM, cutting list sheet, ...). Summary shows who/when; body (description
     + field diff) only renders once expanded. */
.history-entry {
  background: var(--surface);
  border-radius: 4px;
  margin-bottom: 0.3rem;
}

.history-entry summary {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  cursor: pointer;
  list-style: none;
  user-select: none;
  padding: 0.4rem 0.6rem;
  border-radius: 4px;
  font-size: 0.875rem;
  transition: background 0.15s ease, box-shadow 0.15s ease, color 0.15s ease;
}

.history-entry summary::-webkit-details-marker {
  display: none;
}

.history-entry summary::before {
  content: '\25B8';
  display: inline-block;
  width: 1rem;
  text-align: center;
  transition: transform 0.15s ease;
}

.history-entry[open] summary::before {
  transform: rotate(90deg);
}

.history-entry summary:hover {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}

.history-entry summary .history-entry-version {
  color: var(--text-faint);
  font-size: 0.75rem;
  font-weight: 600;
  font-family: ui-monospace, 'Cascadia Code', 'Fira Mono', monospace;
}

.history-entry summary .history-entry-date {
  margin-left: auto;
  color: var(--text-faint);
  font-size: 0.8rem;
  white-space: nowrap;
}

.history-entry-body {
  padding: 0 0.6rem 0.6rem 2.2rem; /* summary's 0.6rem padding + 1rem fixed-width arrow + 0.6rem flex gap, kept in exact lockstep with .history-entry summary above */
}
