/* ===========================================================================
   Forever Imprinted — shared styles for the website and inventory dashboard.
   Chart colors are the validated categorical slots (blue / orange / aqua);
   both themes are explicitly stepped rather than auto-flipped.
   =========================================================================== */

:root {
  color-scheme: light;

  /* Surfaces come straight from the logo's cream, with cards a shade lighter
     so they lift off the page. */
  --page: #f6efe6;               /* the logo's background cream */
  --surface-1: #fffcf7;          /* cards, chart surface */
  --surface-2: #efe5d8;          /* table headers, subtle fills */
  --text-primary: #4a382b;       /* logo's deepest brown */
  --text-secondary: #6e5b48;     /* the "FOREVER" wordmark brown */
  --text-muted: #8b7460;         /* the tagline taupe */
  --gridline: #e7dbca;
  --baseline: #d3c3ae;
  --border: rgba(74, 56, 43, 0.12);
  --border-strong: rgba(74, 56, 43, 0.22);

  /* Categorical slots — fixed order, never cycled. Deliberately NOT brand
     colours: this is a colourblind-safe set, re-validated against the cream
     surface above. Warm browns would collide with each other in a chart. */
  --series-1: #2a78d6;           /* blue    — materials / received */
  --series-2: #eb6834;           /* orange  — components / consumed */
  --series-3: #1baf7a;           /* aqua    — finished */
  --series-4: #eda100;           /* yellow  — fourth slot, the lead-time stages */

  /* Sequential blue ramp (magnitude encoding). */
  --seq-250: #86b6ef;
  --seq-400: #3987e5;
  --seq-550: #1c5cab;

  /* Status — reserved, never reused as a series or brand color. */
  --status-good: #0ca30c;
  --status-warning: #fab219;
  --status-serious: #ec835a;
  --status-critical: #d03b3b;
  --success-text: #006300;

  /* ===== BRAND — taken from forever-imprinted-logo.svg ===================
     --brand-primary      the wordmark brown (buttons, active tab, toast)
     --brand-on-primary   text sitting ON that brown — 5.66:1
     --brand-accent       the monogram gold (decorative fills, rules)
     --brand-accent-text  a darkened gold for when it must carry text — the
                          raw #b08655 only reaches 3.1:1 on cream, so it is
                          never used for words. */
  --brand-primary: #6e5b48;
  --brand-on-primary: #f6efe6;
  --brand-accent: #b08655;
  --brand-accent-text: #8a6238;

  --radius: 10px;
  --radius-lg: 16px;
  --shadow: 0 1px 2px rgba(74, 56, 43, 0.06), 0 8px 24px rgba(74, 56, 43, 0.07);
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    /* Warm dark, stepped from the same brown family — not a neutral grey, which
       would read as a different brand. */
    --page: #17110c;
    --surface-1: #211a13;
    --surface-2: #2c231a;
    --text-primary: #f6efe6;       /* the logo cream becomes the ink */
    --text-secondary: #d9c9b4;
    --text-muted: #a89482;
    --gridline: #33291f;
    --baseline: #4a3b2c;
    --border: rgba(246, 239, 230, 0.12);
    --border-strong: rgba(246, 239, 230, 0.22);
    --series-1: #3987e5;
    --series-2: #d95926;
    --series-3: #199e70;
    --series-4: #c98500;
    --seq-250: #184f95;
    --seq-400: #3987e5;
    --seq-550: #86b6ef;
    --success-text: #0ca30c;
    --brand-primary: #c6a57f;      /* the frame tan carries on dark */
    --brand-on-primary: #17110c;
    --brand-accent: #c6a57f;
    --brand-accent-text: #c6a57f;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 8px 24px rgba(0, 0, 0, 0.38);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  /* Warm dark, stepped from the same brown family — not a neutral grey, which
     would read as a different brand. */
  --page: #17110c;
  --surface-1: #211a13;
  --surface-2: #2c231a;
  --text-primary: #f6efe6;       /* the logo cream becomes the ink */
  --text-secondary: #d9c9b4;
  --text-muted: #a89482;
  --gridline: #33291f;
  --baseline: #4a3b2c;
  --border: rgba(246, 239, 230, 0.12);
  --border-strong: rgba(246, 239, 230, 0.22);
  --series-1: #3987e5;
  --series-2: #d95926;
  --series-3: #199e70;
  --series-4: #c98500;
  --seq-250: #184f95;
  --seq-400: #3987e5;
  --seq-550: #86b6ef;
  --success-text: #0ca30c;
  --brand-primary: #c6a57f;      /* the frame tan carries on dark */
  --brand-on-primary: #17110c;
  --brand-accent: #c6a57f;
  --brand-accent-text: #c6a57f;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 8px 24px rgba(0, 0, 0, 0.38);
}

*, *::before, *::after { box-sizing: border-box; }

/* An explicit `display` on a component beats the UA's [hidden] rule, so make
   the attribute win — .btn and .panel both set display and would leak through. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: var(--sans);
  background: var(--page);
  color: var(--text-primary);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { line-height: 1.2; margin: 0; font-weight: 650; letter-spacing: -0.01em; }
a { color: inherit; }
button { font: inherit; }

/* --- Site chrome ---------------------------------------------------------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 0 24px;
  height: 60px;
  background: color-mix(in srgb, var(--surface-1) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-decoration: none;
  white-space: nowrap;
}
/* The header mark is public/img/mark.svg — the monogram cropped square out of
   the full lockup. Transparent background, so no plate or radius; the full
   logo (with its cream plate) is reserved for the landing hero. */
.brand-mark {
  height: 32px;
  width: auto;
  max-width: 160px;
  object-fit: contain;
  display: block;
  flex: none;
}
.brand-name { font-size: 15px; }
.brand-name small {
  display: block;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* --- Global search ---------------------------------------------------------
   One box in the header across orders, items and products. `margin-left: auto`
   moves here from .nav so the field takes the slack between the brand and the
   navigation rather than being pinned to either. */
.global-search {
  position: relative;
  margin-left: auto;
  flex: 0 1 340px;
  min-width: 0;
}
.global-search-icon {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
}
.global-search input {
  width: 100%;
  height: 36px;
  padding: 0 32px 0 33px;
  border-radius: 9px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text-primary);
  font-size: 14px;
  font-family: inherit;
}
.global-search input::placeholder { color: var(--text-muted); }
.global-search input:focus {
  outline: none;
  border-color: var(--border-strong);
  background: var(--surface-1);
}
/* The browser's own clear button on type="search" sits where the hint is. */
.global-search input::-webkit-search-cancel-button { display: none; }

/* The "/" hint, hidden the moment the field is in use — it is a thing to
   discover once, not a thing to read while typing. */
.global-search-hint {
  position: absolute;
  right: 9px;
  top: 50%;
  transform: translateY(-50%);
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 5px;
  font-family: inherit;
  font-size: 11.5px;
  color: var(--text-muted);
  pointer-events: none;
}
.global-search input:focus ~ .global-search-hint,
.global-search input:not(:placeholder-shown) ~ .global-search-hint { display: none; }

.global-search-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  max-height: min(70vh, 520px);
  overflow-y: auto;
  z-index: 40;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 6px;
}
.global-search-results .gs-group {
  padding: 9px 10px 5px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.global-search-results .gs-hit {
  display: flex;
  align-items: baseline;
  gap: 9px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 8px;
  background: none;
  font: inherit;
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
}
.global-search-results .gs-hit:hover,
.global-search-results .gs-hit[aria-selected="true"] { background: var(--surface-2); }
.global-search-results .gs-hit .gs-title { font-weight: 600; flex: 0 1 auto; }
.global-search-results .gs-hit .gs-sub {
  color: var(--text-secondary);
  font-size: 13px;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.global-search-results .gs-empty { padding: 16px 12px; color: var(--text-muted); font-size: 13.5px; }
.global-search-results .gs-note {
  padding: 8px 12px 4px;
  color: var(--text-muted);
  font-size: 12px;
  border-top: 1px solid var(--border);
  margin-top: 4px;
}

/* Below the tab strip's breakpoint the header is already tight; the box drops
   to its own line rather than squeezing the brand out. */
@media (max-width: 860px) {
  .topbar { flex-wrap: wrap; height: auto; padding: 10px 16px; gap: 10px; }
  .global-search { order: 3; flex: 1 1 100%; margin-left: 0; }
  .nav { margin-left: auto; }
}

.nav { display: flex; gap: 4px; align-items: center; }
.nav a, .nav button.linklike {
  padding: 7px 12px;
  border-radius: 8px;
  font-size: 14px;
  color: var(--text-secondary);
  text-decoration: none;
  background: none;
  border: 0;
  cursor: pointer;
}
.nav a:hover, .nav button.linklike:hover { background: var(--surface-2); color: var(--text-primary); }
.nav a.active { color: var(--text-primary); font-weight: 600; background: var(--surface-2); }

.icon-btn {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface-1);
  color: var(--text-secondary);
  cursor: pointer;
}
.icon-btn:hover { background: var(--surface-2); color: var(--text-primary); }

/* --- Buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 16px;
  border-radius: 8px;
  border: 1px solid var(--border-strong);
  background: var(--surface-1);
  color: var(--text-primary);
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background 120ms ease, border-color 120ms ease;
}
.btn:hover { background: var(--surface-2); }
.btn-primary {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
  color: var(--brand-on-primary);
}
.btn-primary:hover { filter: brightness(1.15); background: var(--brand-primary); }
.btn-sm { padding: 5px 10px; font-size: 13px; border-radius: 7px; }
.btn-danger { color: var(--status-critical); border-color: color-mix(in srgb, var(--status-critical) 40%, transparent); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

/*
  The refresh button, working.

  The arrow turns while the fetch is in flight, because a refresh that reaches
  the same numbers is indistinguishable from a button that did nothing — and a
  studio that cannot tell the two apart presses it again instead of trusting it.
  Held still for anyone who has asked their machine for less movement.
*/
.btn.is-busy .refresh-icon { animation: spin 900ms linear infinite; transform-origin: 50% 50%; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn.is-busy .refresh-icon { animation: none; opacity: 0.6; }
}

/* --- Layout --------------------------------------------------------------- */

.wrap { max-width: 1280px; margin: 0 auto; padding: 28px 24px 64px; }
.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.section-head p { margin: 4px 0 0; color: var(--text-secondary); font-size: 14px; }
/*
  Figures old enough that somebody should press refresh before trusting them.

  Marked with a dot rather than by colouring the sentence: amber text on this
  background is the one thing on the page nobody could read, and the warning is
  wasted on whoever needs it most.
*/
.section-head p.stale { color: var(--text-primary); font-weight: 550; }
.section-head p.stale::before {
  content: ''; display: inline-block; vertical-align: middle;
  width: 8px; height: 8px; margin-right: 7px; border-radius: 50%;
  background: var(--status-warning);
}
.eyebrow {
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.card-head h3 { font-size: 15px; }
.card-head .sub { font-size: 12.5px; color: var(--text-muted); margin: 2px 0 0; }
.card-body { padding: 20px; }
.card-body.flush { padding: 0; }

.grid { display: grid; gap: 16px; }
.grid-kpi { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.grid-2 { grid-template-columns: 1.35fr 1fr; }
@media (max-width: 940px) { .grid-2 { grid-template-columns: 1fr; } }

/* --- Stat tiles ----------------------------------------------------------- */

.stat { padding: 18px 20px; }
.stat .label { font-size: 13px; color: var(--text-secondary); }
.stat .value {
  margin-top: 6px;
  font-size: 30px;
  font-weight: 650;
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.stat .value.hero { font-size: 48px; }
.stat .meta { margin-top: 6px; font-size: 12.5px; color: var(--text-muted); }
.stat .meta strong { color: var(--text-secondary); font-weight: 600; }
.stat.alert .value { color: var(--status-critical); }
.stat .meta.good { color: var(--success-text); }

/* --- Tables --------------------------------------------------------------- */

.table-scroll { overflow-x: auto; }
table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
table.data th {
  text-align: left;
  font-size: 11.5px;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 10px 14px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  position: sticky;
  top: 0;
}
table.data th.sortable { cursor: pointer; user-select: none; }
table.data th.sortable:hover { color: var(--text-primary); }
table.data td {
  padding: 11px 14px;
  border-bottom: 1px solid var(--gridline);
  vertical-align: middle;
}
table.data tbody tr:hover { background: var(--surface-2); }
table.data tbody tr:last-child td { border-bottom: 0; }
/* Give the name column room so titles don't wrap into narrow towers. */
table.data td.name-cell { min-width: 190px; }
table.data th.name-col { min-width: 190px; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.muted { color: var(--text-muted); }
.secondary { color: var(--text-secondary); }
.nowrap { white-space: nowrap; }
.strong { font-weight: 600; }
.mono {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 12.5px;
  color: var(--text-secondary);
}

.empty {
  padding: 44px 20px;
  text-align: center;
  color: var(--text-muted);
  font-size: 14px;
}

/* --- Badges & pills ------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text-secondary);
}
.badge .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
/* Stock kinds and production processes reuse the validated categorical slots.
   The dot is a secondary cue only — the label always names the value. */
.badge.kind-material .dot  { background: var(--series-1); }
.badge.kind-component .dot { background: var(--series-2); }
.badge.kind-finished .dot  { background: var(--series-3); }

.badge.process-clay .dot     { background: var(--series-2); }
.badge.process-print_3d .dot { background: var(--series-1); }
.badge.process-casting .dot  { background: var(--series-3); }
.badge.process-mixed .dot    { background: var(--text-muted); }

/* Hands-on vs waiting time. The dot is secondary — the label always says which. */
.badge.labour-active .dot  { background: var(--series-1); }
.badge.labour-passive .dot { background: var(--text-muted); }

/* Etsy-sourced orders. Tinted, never a status colour — where an order came
   from is not a state it is in. */
.badge.etsy {
  background: color-mix(in srgb, var(--series-2) 14%, var(--surface-1));
  border-color: color-mix(in srgb, var(--series-2) 40%, transparent);
  color: var(--text-primary);
}

/* Collection themes read as quiet tints, never as status. */
.badge.theme-pet_memorial    { background: color-mix(in srgb, var(--series-2) 12%, var(--surface-1)); }
.badge.theme-person_memorial { background: color-mix(in srgb, var(--series-7, var(--series-1)) 12%, var(--surface-1)); }
.badge.theme-baby_keepsake   { background: color-mix(in srgb, var(--series-3) 12%, var(--surface-1)); }

/* Status colors always ship with a label, never color alone. */
.badge.ok       { color: var(--success-text);     border-color: color-mix(in srgb, var(--status-good) 35%, transparent); }
.badge.warn     { color: var(--text-primary);     border-color: color-mix(in srgb, var(--status-warning) 55%, transparent); background: color-mix(in srgb, var(--status-warning) 14%, var(--surface-1)); }
.badge.critical { color: var(--status-critical);  border-color: color-mix(in srgb, var(--status-critical) 40%, transparent); background: color-mix(in srgb, var(--status-critical) 8%, var(--surface-1)); }

/* --- Meter (stock level vs reorder point) --------------------------------- */

.meter {
  display: block;          /* the span is inline by default — height needs a block box */
  position: relative;
  height: 6px;
  min-width: 72px;
  border-radius: 999px;
  background: var(--gridline);
  overflow: hidden;
}
.meter > span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--seq-400);
}
.meter.low > span { background: var(--status-warning); }
.meter.out > span { background: var(--status-critical); }

/* --- Forms ---------------------------------------------------------------- */

.field { display: flex; flex-direction: column; gap: 5px; }
.field label { font-size: 12.5px; font-weight: 600; color: var(--text-secondary); }
input, select, textarea {
  font: inherit;
  font-size: 14px;
  padding: 8px 11px;
  border-radius: 8px;
  border: 1px solid var(--border-strong);
  background: var(--surface-1);
  color: var(--text-primary);
  width: 100%;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--seq-400);
  outline-offset: -1px;
  border-color: transparent;
}
textarea { resize: vertical; min-height: 68px; }
.field .hint { font-size: 12px; color: var(--text-muted); }

/* A link that sits inside a sentence but does something on this page rather
   than going anywhere — "create a new customer" in the order form. */
.linkish {
  font: inherit;
  color: var(--text-primary);
  background: none;
  border: 0;
  padding: 0;
  width: auto;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.linkish:hover { color: var(--brand-primary, var(--text-primary)); }

/* --- Search-and-pick field ------------------------------------------------ */

/* A search box whose matches drop over what follows it, so choosing somebody
   already on file never pushes the rest of the form down the screen. */
.picker { position: relative; }
.picker-results {
  position: absolute;
  z-index: 5;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 232px;
  overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  background: var(--surface-1);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.24);
}
.picker-results button {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  padding: 7px 9px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--text-primary);
  cursor: pointer;
}
.picker-results button:hover, .picker-results button:focus-visible { background: var(--surface-2); }
.picker-results .line2 { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.picker-results .none { padding: 8px 9px; font-size: 12.5px; color: var(--text-muted); }

/* The person picked, sitting under the search box until they are cleared. */
.picked {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 9px 11px;
  border: 1px solid color-mix(in srgb, var(--status-good) 35%, transparent);
  border-radius: 9px;
  background: color-mix(in srgb, var(--status-good) 8%, var(--surface-1));
  font-size: 13px;
}
.picked .who { font-weight: 600; }
.picked .spacer { flex: 1; }

.toolbar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
}
.toolbar .search { flex: 1 1 240px; max-width: 340px; }
.toolbar select { width: auto; min-width: 130px; }
.toolbar .spacer { flex: 1; }

.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; }
.form-grid .span-2 { grid-column: span 2; }
/* Full width whatever the column count works out to — for a block of
   checkboxes, which reads badly squeezed into half a row. */
.form-grid .span-all { grid-column: 1 / -1; }
@media (max-width: 560px) { .form-grid .span-2 { grid-column: span 1; } }

/* --- Modal ---------------------------------------------------------------- */

dialog.modal {
  width: min(680px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface-1);
  color: var(--text-primary);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.28);
}
dialog.modal::backdrop { background: rgba(0, 0, 0, 0.45); backdrop-filter: blur(2px); }
dialog.modal .card-head { padding: 18px 22px; }
dialog.modal .modal-body { padding: 22px; max-height: 68vh; overflow-y: auto; }
dialog.modal .modal-foot {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 16px 22px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

/* --- Charts --------------------------------------------------------------- */

.chart { width: 100%; display: block; overflow: visible; }
.chart text { font-family: var(--sans); }
.chart .axis-label { font-size: 11px; fill: var(--text-muted); }
.chart .value-label { font-size: 11.5px; fill: var(--text-secondary); font-weight: 600; }
.chart .gridline { stroke: var(--gridline); stroke-width: 1; }
.chart .baseline { stroke: var(--baseline); stroke-width: 1; }
.chart .hit { fill: transparent; cursor: pointer; }
.chart .hit:hover + .mark, .chart .mark.active { filter: brightness(1.12); }

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  align-items: center;
  font-size: 12.5px;
  color: var(--text-secondary);
}
.legend .key { display: inline-flex; align-items: center; gap: 6px; }
.legend .swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.legend .line-key { width: 14px; height: 2px; border-radius: 2px; flex: none; }

.tooltip {
  position: fixed;
  z-index: 60;
  pointer-events: none;
  padding: 8px 11px;
  border-radius: 8px;
  background: var(--surface-1);
  border: 1px solid var(--border-strong);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  font-size: 12.5px;
  color: var(--text-primary);
  max-width: 240px;
  opacity: 0;
  transition: opacity 90ms ease;
}
.tooltip.show { opacity: 1; }
.tooltip .t-title { font-weight: 650; margin-bottom: 3px; }
.tooltip .t-row { display: flex; align-items: center; gap: 7px; color: var(--text-secondary); }
.tooltip .t-row .swatch { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.tooltip .t-row b { color: var(--text-primary); font-variant-numeric: tabular-nums; margin-left: auto; }

/* Category bar rows — direct labels satisfy the light-mode contrast relief. */
.barlist { display: flex; flex-direction: column; gap: 12px; }
.barrow { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; align-items: baseline; }
.barrow .name { font-size: 13.5px; }
.barrow .amount { font-size: 13.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.barrow .track {
  display: block;
  grid-column: 1 / -1;
  height: 8px;
  background: var(--surface-2);
  border-radius: 4px;
  overflow: hidden;
}
/* Block box so the height resolves — an inline span would collapse to nothing. */
.barrow .fill { display: block; height: 100%; border-radius: 0 4px 4px 0; }

/* --- Banner --------------------------------------------------------------- */

.banner {
  display: none;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 18px;
  margin-bottom: 20px;
  border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--status-critical) 35%, transparent);
  background: color-mix(in srgb, var(--status-critical) 8%, var(--surface-1));
  font-size: 14px;
}
.banner.show { display: flex; }
.banner strong { display: block; margin-bottom: 3px; }
.banner code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--surface-2);
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 12px);
  z-index: 80;
  padding: 11px 18px;
  border-radius: 999px;
  background: var(--brand-primary);
  color: var(--brand-on-primary);
  font-size: 13.5px;
  font-weight: 550;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
  opacity: 0;
  pointer-events: none;
  transition: opacity 160ms ease, transform 160ms ease;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.error { background: var(--status-critical); color: #fff; }

/* Filter chips: a row of toggles that also carry their counts. */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chips button {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface-1); color: var(--text-secondary);
  font-size: 12.5px; font-weight: 550; cursor: pointer;
}
.chips button:hover { background: var(--surface-2); color: var(--text-primary); }
.chips button[aria-pressed="true"] {
  background: var(--brand-primary); border-color: var(--brand-primary); color: var(--brand-on-primary);
}
.chips button .n { font-variant-numeric: tabular-nums; opacity: 0.75; }

/* Status timeline on an order. */
.timeline { list-style: none; padding: 0; margin: 0; display: grid; gap: 0; }
.timeline li { display: grid; grid-template-columns: 14px 1fr; gap: 12px; padding-bottom: 14px; position: relative; }
.timeline li::before {
  content: ''; grid-column: 1; width: 9px; height: 9px; border-radius: 50%;
  background: var(--brand-accent); margin-top: 5px; z-index: 1;
}
.timeline li:not(:last-child)::after {
  content: ''; position: absolute; left: 4px; top: 14px; bottom: 0;
  width: 1px; background: var(--gridline);
}
.timeline .when { font-size: 12px; color: var(--text-muted); }
.timeline .what { font-size: 13.5px; }

/* Notes thread. */
.note { padding: 12px 0; border-bottom: 1px solid var(--gridline); }
.note:last-child { border-bottom: 0; }
.note .meta { font-size: 12px; color: var(--text-muted); margin-bottom: 3px; }
.note .body { font-size: 13.5px; white-space: pre-wrap; }

/* --- Tabs ----------------------------------------------------------------- */

.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 22px; }
.tabs button {
  padding: 10px 14px;
  border: 0;
  background: none;
  color: var(--text-secondary);
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.tabs button:hover { color: var(--text-primary); }
.tabs button[aria-selected="true"] { color: var(--text-primary); border-bottom-color: var(--brand-primary); }

.panel[hidden] { display: none; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Shipping ------------------------------------------------------------ */

/* A checkbox that reads as one line rather than a label stacked on a control. */
.check {
  display: flex; align-items: center; gap: 8px;
  font-size: 13.5px; font-weight: 500; color: var(--text-secondary);
}
/* Radios too: a control that inherits the full-width input rule stops looking
   like something you pick and starts looking like something you drag. */
.check input[type="checkbox"],
.check input[type="radio"] { width: auto; margin: 0; flex: none; }
/* A choice that carries an explanation under it lines its control up with the
   first line of text rather than with the middle of the paragraph. */
.check input[type="radio"] { align-self: flex-start; margin-top: 2px; }
.check + .check { margin-top: 8px; }

/* Where the parcel is going, shown while choosing how to send it. */
.addr-card {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  margin-bottom: 16px;
  background: var(--surface-2);
  font-size: 13.5px;
  line-height: 1.5;
}
.addr-card .to { font-size: 11.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); }

/* Label, packing slip and the attachments that follow. Links, not buttons:
   these open a PDF, and a middle click should work the way it looks. */
.doc-list { display: flex; flex-wrap: wrap; gap: 8px; }
.doc-list a {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 11px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 13px;
  color: var(--text-secondary);
  text-decoration: none;
  background: var(--surface-1);
}
.doc-list a:hover { background: var(--surface-2); color: var(--text-primary); }
.doc-list a .size { color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* The shipping facts on an order: label on the left, value on the right. */
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 0; font-size: 13.5px; }
.kv dt { color: var(--text-muted); }
.kv dd { margin: 0; color: var(--text-primary); }
.kv dd a { color: inherit; }

/* --- Order attachments ---------------------------------------------------- */

.drop {
  border: 1.5px dashed var(--border);
  border-radius: 10px;
  padding: 16px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.drop:hover { border-color: var(--brand-primary); color: var(--text-secondary); }
/* Held while a file is over the zone, so it is obvious where it will land. */
.drop.over {
  border-color: var(--brand-primary);
  background: color-mix(in srgb, var(--brand-primary) 8%, var(--surface-1));
  color: var(--text-primary);
}
.drop strong { display: block; color: var(--text-secondary); font-size: 13.5px; margin-bottom: 2px; }
.drop.busy { cursor: progress; opacity: 0.7; }

/* Photos of the finished piece. Square tiles so a mixed set of portrait and
   landscape shots still reads as a grid. */
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(86px, 1fr)); gap: 8px; }
.photo-tile { position: relative; aspect-ratio: 1; border-radius: 9px; overflow: hidden; border: 1px solid var(--border); }
.photo-tile img { width: 100%; height: 100%; object-fit: cover; display: block; background: var(--surface-2); }
.photo-tile .kill {
  position: absolute; top: 4px; right: 4px;
  width: 22px; height: 22px; border-radius: 50%;
  border: 0; cursor: pointer;
  background: rgba(0, 0, 0, 0.6); color: #fff;
  font-size: 14px; line-height: 1;
  opacity: 0; transition: opacity 0.12s;
}
.photo-tile:hover .kill, .photo-tile:focus-within .kill { opacity: 1; }

/* Print files. A row each, because the name and size are what you pick by. */
.file-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 9px;
  font-size: 13.5px;
}
.file-row + .file-row { margin-top: 6px; }
.file-row .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-row .size { color: var(--text-muted); font-variant-numeric: tabular-nums; flex: none; }
.file-row a { color: var(--text-secondary); text-decoration: none; }
.file-row a:hover { color: var(--text-primary); text-decoration: underline; }

/* A button that reads as a link — for a table cell where the identifier itself
   is the thing you click, rather than an "Open" button beside it. */
.linkbtn {
  border: 0; background: none; padding: 0;
  color: var(--text-primary); font: inherit; cursor: pointer;
  text-align: left; text-decoration: underline;
  text-decoration-color: var(--baseline); text-underline-offset: 3px;
}
.linkbtn:hover { text-decoration-color: currentColor; }

/* --- Bulk upload ---------------------------------------------------------- */

/* Numbered steps, because the order matters: the template has to be downloaded
   before there is anything to upload. */
.import-step {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--gridline);
}
.import-step .step-head { display: flex; gap: 11px; align-items: flex-start; }
.import-step .step-head strong { font-size: 14px; }
.import-step .step-head p { margin: 3px 0 0; font-size: 12.5px; }
.import-step .step-no {
  flex: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  font-size: 12px; font-weight: 650;
  color: var(--text-secondary);
}
.import-step .step-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 0 33px; }
.import-step .drop { margin: 12px 0 0 33px; }

/* The column reference — one row per column, so a hint can run long without
   squeezing the name. */
.import-columns {
  margin: 12px 0 0 33px;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.import-columns .col-row {
  display: grid;
  grid-template-columns: minmax(120px, 170px) 1fr;
  gap: 4px 14px;
  padding: 9px 12px;
  font-size: 12.5px;
}
.import-columns .col-row + .col-row { border-top: 1px solid var(--gridline); }
.import-columns .col-name {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 12px;
  color: var(--text-primary);
}
.import-columns .col-name .req { color: var(--status-critical); margin-left: 3px; }
.import-columns .col-hint { color: var(--text-secondary); }
.import-columns .col-example { color: var(--text-muted); }
@media (max-width: 560px) {
  .import-columns .col-row { grid-template-columns: 1fr; }
}

.import-paste { margin: 12px 0 0 33px; font-size: 12.5px; color: var(--text-muted); }
.import-paste summary { cursor: pointer; }
.import-paste textarea { margin-top: 8px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
.import-paste .btn { margin-top: 8px; }

/* The verdict on a checked file. */
.import-result {
  margin-top: 18px;
  padding: 14px 16px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 13.5px;
}
.import-result.bad { border-color: color-mix(in srgb, var(--status-critical) 45%, transparent); }
.import-result.good { border-color: color-mix(in srgb, var(--status-good) 45%, transparent); }
.import-result h4 { font-size: 13.5px; margin: 0 0 6px; }
.import-result .counts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.import-result ul { margin: 10px 0 0; padding-left: 18px; color: var(--text-secondary); }
.import-result li { margin-top: 3px; }
.import-result li b { color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   Version footer — appended to every page by /js/version-footer.js.
   Quiet by design: it is a fact to look up, not something to read.
   --------------------------------------------------------------------------- */
.version-bar {
  margin-top: 40px;
  padding: 18px 20px 24px;
  border-top: 1px solid var(--border);
  text-align: center;
  font-size: 12.5px;
  color: var(--text-muted);
}
.version-bar a { color: var(--text-muted); text-decoration: none; }
.version-bar a:hover { color: var(--text-secondary); text-decoration: underline; }
.version-bar-num { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   Version history — Configuration › Version.
   --------------------------------------------------------------------------- */
.release { display: grid; grid-template-columns: 92px 1fr; gap: 16px; padding: 16px 0; border-top: 1px solid var(--border); }
.release:first-child { border-top: 0; padding-top: 4px; }
.release .rel-mark { text-align: right; }
.release .rel-num { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.release .rel-date { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.release h4 { font-size: 14.5px; margin: 0 0 5px; }
.release p { font-size: 13.5px; margin: 0; color: var(--text-secondary); line-height: 1.6; }
.release .rel-pr { font-size: 12.5px; margin-top: 6px; display: inline-block; color: var(--text-muted); }
/* What one merge shipped, when it shipped more than one thing. */
.release .rel-changes { margin: 8px 0 0; padding: 0 0 0 14px; list-style: none; border-left: 2px solid var(--border); }
.release .rel-changes li { margin-top: 10px; }
.release .rel-changes li:first-child { margin-top: 0; }
.release .rel-changes strong { display: block; font-size: 13.5px; color: var(--text-primary); }
.release .rel-changes span { display: block; font-size: 13px; color: var(--text-secondary); line-height: 1.6; margin-top: 2px; }
@media (max-width: 560px) {
  .release { grid-template-columns: 1fr; gap: 4px; }
  .release .rel-mark { text-align: left; display: flex; gap: 8px; align-items: baseline; }
  .release .rel-date { margin-top: 0; }
}
