/* Makerspace Project Tracker — "project traveler" design system.
   Palette: UIC brand colors (brand.uic.edu/visual-identity/color) — Navy
   Pier Blue ink, Expo White paper, Fire Engine Red accent, Chicago Brick
   danger, Chicago River Green success, UI Health Sky links.
   That's the default "uic" color scheme. Others (data-scheme on <html>, chosen
   on the user settings page) redefine every token below, each with a light and
   a dark variant — see the scheme blocks after the UIC dark block.
   All text meets WCAG AA (4.5:1) and form-control borders 3:1 — --steel and
   --input-border were darkened from the original brand tints to get there.
   Mono type is reserved for machine-readable things: project numbers, status
   stamps, process settings — the way a router tag reads on a shop floor. */

:root {
  --ink: #001E62;
  --ink-soft: #4a5c82;
  --paper: #f6f3ec;
  --card: #ffffff;
  --line: #dad5c8;
  --steel: #33768a;
  --amber: #d50032;
  --amber-ink: #ffffff;
  --red: #b10000;
  --green: #00966c;
  --purple: #7c3aed;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --display: "Avenir Next Condensed", "Arial Narrow", "Helvetica Neue", Arial, sans-serif;
  --body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* The topbar is a fixed navy surface in both themes — kept separate from
     --ink (body text), which flips light/dark, so buttons and the header
     don't go pale when --ink turns light for dark mode. */
  --navy: #001E62;
  --navy-hover: #26407a;
  --amber-hover: #db2651;
  --steel-ink: #ffffff;  /* text on a --steel background */

  /* Text on the topbar (a --navy surface in every scheme and mode). */
  --topbar-text: #eef1f4;
  --topbar-strong: #ffffff;
  --topbar-link: #cdd6de;
  --topbar-muted: #93a1ad;
  --topbar-tag: #b9c4cd;
  --topbar-border: #5a6673;

  /* Tinted badge/banner backgrounds (stamps, flashes) + the handful of text
     colors that were hand-picked as darker shades of an accent rather than
     the accent variable itself — both need their own light/dark pair since
     they don't track --ink or --paper automatically. */
  --tint-blue-bg: #ecf4f6;
  --tint-ink-bg: #e6e9ef;
  --tint-pink-bg: #fcebef;
  --tint-pink-text: #8a0020;
  --tint-red-bg: #f9ebeb;
  --tint-red-text: #8e0000;
  --tint-green-bg: #ebf7f3;
  --tint-green-text: #005a41;
  --tint-purple-bg: #f3ecfb;
  --tint-purple-text: #6b21a8;
  --tint-gray-bg: #f2f1ee;
  --tint-gray-text: #6e6a66;
  --tint-gray-border: #aca89f;
  --flash-ok-border: #a6dacc;
  --flash-error-border: #e4a6a6;
  --internal-flag-border: #e66684;
  --muted-warm: #6f6960;  /* darkened for WCAG AA (~4.9:1 on paper) */
  --table-head-bg: #f4f2ec;
  --table-row-border: #e8e4db;
  --filter-icon: #6f6960;  /* ≥4.5:1 on the table header (was #b9b2a2, 1.9:1) */
  --filter-hover-bg: #e8e4d8;
  --input-border: #98948b;
  --input-bg: #ffffff;
  --quiet-hover-bg: #e6e2d8;
  --overlay-bg: rgba(246, 243, 236, 0.85);

  color-scheme: light;
}

:root[data-theme="dark"] {
  --ink: #dbe3f5;
  --ink-soft: #94a1bd;
  --paper: #10131a;
  --card: #1a1f2b;
  --line: #2c3244;
  --steel: #6cc4de;
  --steel-ink: #10131a;
  --red: #ff6b6b;
  --green: #3ddba8;
  --purple: #c084fc;

  --tint-blue-bg: #142b36;
  --tint-ink-bg: #1e2536;
  --tint-pink-bg: #3a1420;
  --tint-pink-text: #ff8fa8;
  --tint-red-bg: #3a1414;
  --tint-red-text: #ff8f8f;
  --tint-green-bg: #123028;
  --tint-green-text: #6fe3bf;
  --tint-purple-bg: #2a1f3d;
  --tint-purple-text: #d8b4fe;
  --tint-gray-bg: #292a28;
  --tint-gray-text: #c9c5bc;
  --tint-gray-border: #57544c;
  --flash-ok-border: #2f6350;
  --flash-error-border: #6b3232;
  --internal-flag-border: #b34a63;
  --muted-warm: #9c968a;
  --table-head-bg: #232a3b;
  --table-row-border: #262c3c;
  --filter-icon: #9c968a;
  --filter-hover-bg: #232a3b;
  --input-border: #686c79;
  --input-bg: #1c212c;
  --quiet-hover-bg: #232838;
  --overlay-bg: rgba(20, 24, 33, 0.85);

  color-scheme: dark;
}

/* ---- Alternate color schemes -------------------------------------------
   Each block defines the full token set: a scheme's light block has the same
   specificity as the UIC dark block above and comes later, so a token left
   out of a scheme's dark block would silently fall back to its light value.
   Every text/background pair is checked for contrast — WCAG AA (4.5:1) for
   Solarized, AAA (7:1) for high contrast. Solarized keeps the stock base
   tones; accents are darkened (light) or lightened (dark) only where the
   stock value falls short as text. */
:root[data-scheme="solarized"] {
  --ink: #073642;
  --ink-soft: #4a5b62;
  --paper: #eee8d5;
  --card: #fdf6e3;
  --line: #d3cbb4;
  --steel: #1a6497;
  --steel-ink: #fdf6e3;
  --amber: #a63b0c;
  --amber-ink: #fdf6e3;
  --amber-hover: #b8430f;
  --red: #a82623;
  --green: #5f6e00;
  --purple: #5357a8;
  --navy: #073642;
  --navy-hover: #0f4c5c;
  --topbar-text: #eee8d5;
  --topbar-strong: #fdf6e3;
  --topbar-link: #d6dbd1;
  --topbar-muted: #a9b5b3;
  --topbar-tag: #bcc6c3;
  --topbar-border: #3e6470;
  --tint-blue-bg: #e3ecec;
  --tint-ink-bg: #e6e1cf;
  --tint-pink-bg: #f5e1d3;
  --tint-pink-text: #7d2d07;
  --tint-red-bg: #f5ded7;
  --tint-red-text: #8f1f1c;
  --tint-green-bg: #e8e9cc;
  --tint-green-text: #435000;
  --tint-purple-bg: #e6e4ef;
  --tint-purple-text: #44489a;
  --tint-gray-bg: #e6e0cd;
  --tint-gray-text: #4f5d61;
  --tint-gray-border: #a39f8c;
  --flash-ok-border: #b3bd73;
  --flash-error-border: #dba095;
  --internal-flag-border: #d2703f;
  --muted-warm: #56645f;
  --table-head-bg: #e8e2ce;
  --table-row-border: #e0dac6;
  --filter-icon: #56645f;
  --filter-hover-bg: #e0d9c4;
  --input-border: #857f6b;
  --input-bg: #fdf6e3;
  --quiet-hover-bg: #e0d9c4;
  --overlay-bg: rgba(238, 232, 213, 0.85);
  color-scheme: light;
}

:root[data-scheme="solarized"][data-theme="dark"] {
  --ink: #eee8d5;
  --ink-soft: #a3b0b0;
  --paper: #002b36;
  --card: #073642;
  --line: #16505e;
  --steel: #5eb0e8;
  --steel-ink: #002b36;
  --amber: #a63b0c;
  --amber-ink: #fdf6e3;
  --amber-hover: #b8430f;
  --red: #f4736f;
  --green: #a1bb1a;
  --purple: #a4a8ec;
  --navy: #001f27;
  --navy-hover: #0a3a47;
  --topbar-text: #eee8d5;
  --topbar-strong: #fdf6e3;
  --topbar-link: #cdd4cf;
  --topbar-muted: #93a1a1;
  --topbar-tag: #a9b6b3;
  --topbar-border: #2f5561;
  --tint-blue-bg: #08384a;
  --tint-ink-bg: #0d3b47;
  --tint-pink-bg: #3a2418;
  --tint-pink-text: #f4a57e;
  --tint-red-bg: #3d1d1f;
  --tint-red-text: #ff9d95;
  --tint-green-bg: #1f3514;
  --tint-green-text: #b9d24f;
  --tint-purple-bg: #22284a;
  --tint-purple-text: #c3c6f3;
  --tint-gray-bg: #0d3640;
  --tint-gray-text: #bcc5c3;
  --tint-gray-border: #3f6570;
  --flash-ok-border: #4f6a1a;
  --flash-error-border: #7a3432;
  --internal-flag-border: #b0543a;
  --muted-warm: #a5afab;
  --table-head-bg: #0a3a47;
  --table-row-border: #0f4351;
  --filter-icon: #a5afab;
  --filter-hover-bg: #0a3a47;
  --input-border: #5f8c96;
  --input-bg: #03313d;
  --quiet-hover-bg: #0a3a47;
  --overlay-bg: rgba(0, 43, 54, 0.85);
  color-scheme: dark;
}

:root[data-scheme="high-contrast"] {
  --ink: #000000;
  --ink-soft: #262626;
  --paper: #ffffff;
  --card: #ffffff;
  --line: #000000;
  --steel: #0000b3;
  --steel-ink: #ffffff;
  --amber: #ffd400;
  --amber-ink: #000000;
  --amber-hover: #ffe34d;
  --red: #a00000;
  --green: #005c00;
  --purple: #5a008f;
  --navy: #000000;
  --navy-hover: #333333;
  --topbar-text: #ffffff;
  --topbar-strong: #ffffff;
  --topbar-link: #ffffff;
  --topbar-muted: #ffffff;
  --topbar-tag: #ffffff;
  --topbar-border: #ffffff;
  --tint-blue-bg: #eef3ff;
  --tint-ink-bg: #ececec;
  --tint-pink-bg: #fff0f3;
  --tint-pink-text: #6b0020;
  --tint-red-bg: #fff0f0;
  --tint-red-text: #8a0000;
  --tint-green-bg: #eefbee;
  --tint-green-text: #004d00;
  --tint-purple-bg: #f6eeff;
  --tint-purple-text: #4b0082;
  --tint-gray-bg: #f0f0f0;
  --tint-gray-text: #262626;
  --tint-gray-border: #000000;
  --flash-ok-border: #004d00;
  --flash-error-border: #8a0000;
  --internal-flag-border: #6b0020;
  --muted-warm: #262626;
  --table-head-bg: #e8e8e8;
  --table-row-border: #595959;
  --filter-icon: #000000;
  --filter-hover-bg: #e0e0e0;
  --input-border: #000000;
  --input-bg: #ffffff;
  --quiet-hover-bg: #e0e0e0;
  --overlay-bg: rgba(255, 255, 255, 0.92);
  color-scheme: light;
}

:root[data-scheme="high-contrast"][data-theme="dark"] {
  --ink: #ffffff;
  --ink-soft: #e6e6e6;
  --paper: #000000;
  --card: #000000;
  --line: #ffffff;
  --steel: #8fd3ff;
  --steel-ink: #000000;
  --amber: #ffd400;
  --amber-ink: #000000;
  --amber-hover: #ffe34d;
  --red: #ff8a8a;
  --green: #6dff6d;
  --purple: #e0b3ff;
  --navy: #000000;
  --navy-hover: #333333;
  --topbar-text: #ffffff;
  --topbar-strong: #ffffff;
  --topbar-link: #ffffff;
  --topbar-muted: #ffffff;
  --topbar-tag: #ffffff;
  --topbar-border: #ffffff;
  --tint-blue-bg: #001a33;
  --tint-ink-bg: #1a1a1a;
  --tint-pink-bg: #2a0010;
  --tint-pink-text: #ffb3c6;
  --tint-red-bg: #2a0000;
  --tint-red-text: #ffb3b3;
  --tint-green-bg: #002a00;
  --tint-green-text: #b3ffb3;
  --tint-purple-bg: #1f0033;
  --tint-purple-text: #e6ccff;
  --tint-gray-bg: #1a1a1a;
  --tint-gray-text: #e6e6e6;
  --tint-gray-border: #ffffff;
  --flash-ok-border: #6dff6d;
  --flash-error-border: #ff8a8a;
  --internal-flag-border: #ffb3c6;
  --muted-warm: #e6e6e6;
  --table-head-bg: #1a1a1a;
  --table-row-border: #a6a6a6;
  --filter-icon: #ffffff;
  --filter-hover-bg: #333333;
  --input-border: #ffffff;
  --input-bg: #000000;
  --quiet-hover-bg: #333333;
  --overlay-bg: rgba(0, 0, 0, 0.92);
  color-scheme: dark;
}

/* Solarized dark's header color is barely darker than the page, so plain
   (header-colored) buttons need an outline to stand out. */
:root[data-scheme="solarized"][data-theme="dark"] .btn:not(.btn-amber):not(.btn-danger) {
  border-color: var(--input-border);
}

/* High contrast extras: underlined links, heavy focus rings, and outlines on
   things that otherwise rely on a fill color alone to stand out. */
:root[data-scheme="high-contrast"] a { text-decoration: underline; }
:root[data-scheme="high-contrast"] :focus-visible {
  outline: 3px solid var(--steel) !important; outline-offset: 2px;
}
:root[data-scheme="high-contrast"] .topbar :focus-visible { outline-color: var(--amber) !important; }
:root[data-scheme="high-contrast"] .btn { border-width: 2px; border-color: var(--ink); }
:root[data-scheme="high-contrast"] .topbar .btn,
:root[data-scheme="high-contrast"] .nav a.nav-cta { border: 2px solid var(--topbar-border); }
:root[data-scheme="high-contrast"] .admin-subnav a.active { border-bottom-color: var(--ink); }
:root[data-scheme="high-contrast"] .comment.internal { border-left-color: var(--ink); }
:root[data-scheme="high-contrast"][data-theme="dark"] .topbar { border-bottom: 2px solid var(--topbar-border); }

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 15px;
  line-height: 1.5;
}
.wrap { max-width: 1400px; margin: 0 auto; padding: 0 10px; }
a { color: var(--steel); }
h1, h2, h3 {
  font-family: var(--display);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.15;
}
h1 { font-size: 26px; margin: 22px 0 6px; }
h2 { font-size: 18px; margin: 26px 0 8px; }
h3 { font-size: 15px; margin: 18px 0 6px; color: var(--ink-soft); }
.sub { color: var(--ink-soft); margin: 0 0 18px; }

/* ---- Top bar ---- */
.topbar { background: var(--navy); color: var(--topbar-text); }
.topbar-inner { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; padding-top: 10px; padding-bottom: 10px; }
.brand {
  font-family: var(--display); text-transform: uppercase; letter-spacing: 0.08em;
  font-size: 17px; color: var(--topbar-strong); text-decoration: none; white-space: nowrap;
}
.brand-mark { color: var(--amber); }
.nav { display: flex; gap: 4px; flex-wrap: wrap; }
.nav a {
  color: var(--topbar-link); text-decoration: none; font-family: var(--display);
  text-transform: uppercase; letter-spacing: 0.06em; font-size: 13.5px;
  padding: 5px 9px; border-radius: 3px;
}
.nav a:hover { color: var(--topbar-strong); background: rgba(255,255,255,0.08); }
.nav a.nav-cta { background: var(--amber); color: var(--amber-ink); font-weight: 600; }
.nav a.nav-cta:hover { background: var(--amber-hover); }
.whoami { margin-left: auto; display: flex; align-items: center; gap: 10px; font-size: 13px; }
.whoami-name { color: var(--topbar-strong); text-decoration: none; }
.whoami-name:hover, .whoami-name:focus-visible { text-decoration: underline; }
.role-tag {
  font-family: var(--mono); font-size: 11px; text-transform: uppercase;
  border: 1px solid var(--topbar-border); padding: 1px 6px; border-radius: 2px; color: var(--topbar-tag);
}
.signout-form { display: inline; margin: 0; }
/* A POST form's button, dressed as the link it used to be. */
button.signout {
  color: var(--topbar-muted); background: none; border: none; padding: 0;
  font: inherit; text-decoration: underline; cursor: pointer;
}
.theme-toggle {
  background: transparent; border: 1px solid var(--topbar-border); color: var(--topbar-text);
  border-radius: 4px; font-size: 14px; line-height: 1; padding: 5px 8px;
  cursor: pointer;
}
.theme-toggle:hover { background: rgba(255,255,255,0.08); }
.theme-toggle-standalone { margin-left: auto; }

/* ---- Flashes ---- */
.flashes { margin-top: 14px; }
.flash { padding: 9px 12px; border-radius: 4px; margin-bottom: 6px; border: 1px solid; font-size: 14px; }
.flash-ok { background: var(--tint-green-bg); border-color: var(--flash-ok-border); color: var(--tint-green-text); }
.flash-error { background: var(--tint-red-bg); border-color: var(--flash-error-border); color: var(--tint-red-text); }

/* ---- Status stamps (the signature element) ---- */
.stamp {
  font-family: var(--mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: 0.05em; padding: 2px 8px; border: 1.5px solid; border-radius: 2px;
  white-space: nowrap; display: inline-block;
}
.stamp-submitted, .stamp-queued { color: var(--steel); border-color: var(--steel); background: var(--tint-blue-bg); }
.stamp-quality_check { color: var(--tint-purple-text); border-color: var(--purple); background: var(--tint-purple-bg); }
.stamp-pending_instructor_approval { color: var(--ink); border-color: var(--ink); background: var(--tint-ink-bg); }
.stamp-in_production { color: var(--tint-pink-text); border-color: var(--amber); background: var(--tint-pink-bg); }
.stamp-needs_changes { color: var(--tint-red-text); border-color: var(--red); background: var(--tint-red-bg); }
.stamp-ready_for_pickup, .stamp-completed, .stamp-approved { color: var(--tint-green-text); border-color: var(--green); background: var(--tint-green-bg); }
.stamp-rejected, .stamp-cancelled { color: var(--tint-gray-text); border-color: var(--tint-gray-border); background: var(--tint-gray-bg); }

/* ---- Status filter chips (My projects) — same palette as the stamps above ----
   "All" is a plain link (reset); the rest are checkbox labels so several can be
   active at once — the checkbox itself is visually hidden, the label is the chip. */
.status-filter-bar { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin: 0; }
.status-chip {
  font-family: var(--mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: 0.05em; padding: 4px 10px; border: 1.5px solid; border-radius: 2px;
  white-space: nowrap; text-decoration: none; cursor: pointer;
  display: inline-flex; align-items: center; position: relative;
}
.status-chip input[type="checkbox"] {
  position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0;
}
.status-chip:hover { filter: brightness(0.95); }
.status-chip:focus-within { outline: 2px solid var(--steel); outline-offset: 1px; }
.status-chip.active { font-weight: 700; box-shadow: 0 0 0 2px currentColor inset; }
.status-chip-all { color: var(--ink); border-color: var(--ink); background: var(--tint-ink-bg); }

/* ---- Status flowchart (project detail "Shop controls") — same stamp palette
   as everywhere else, laid out as a small state diagram: the main pipeline,
   the staff-only check/approve side loop, and the three exit outcomes.
   Current status is a plain highlighted node (never clickable, since it's
   not a transition target); reachable next states are chip-buttons wrapping
   a hidden radio; everything else shown dim, for context only. ---- */
.status-flow-field { display: block; margin-bottom: 12px; font-size: 14px; font-weight: 600; }
.status-flow { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; font-weight: 400; }
.status-flow-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.status-flow-row-sub { padding-left: 6px; }
.flow-row-label {
  font-size: 11px; font-weight: 600; color: var(--muted-warm); text-transform: uppercase;
  letter-spacing: 0.05em; margin-right: 2px; white-space: nowrap;
}
.flow-arrow { color: var(--muted-warm); font-size: 13px; }

.flow-node {
  font-family: var(--mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: 0.04em; padding: 5px 9px; border: 1.5px solid; border-radius: 3px;
  white-space: nowrap; display: inline-flex; flex-direction: column; align-items: center;
  gap: 3px; position: relative; line-height: 1.3;
}
.flow-node input[type="radio"] { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; }
.flow-node-caption {
  font-family: var(--body); text-transform: none; letter-spacing: normal;
  font-size: 11px; font-weight: 400; max-width: 130px; white-space: normal; text-align: center;
}
.flow-current { box-shadow: 0 0 0 2px currentColor inset; font-weight: 700; }
/* Statuses you can't move to from here. Muted with a dashed outline rather
   than faded out: opacity took the label below readable contrast. */
.flow-inert {
  color: var(--muted-warm); background: transparent; border-color: var(--line);
  border-style: dashed; cursor: default;
}
.flow-action { cursor: pointer; }
.flow-action:hover { filter: brightness(0.95); }
.flow-action:focus-within { outline: 2px solid var(--steel); outline-offset: 1px; }
.flow-action.flow-selected { box-shadow: 0 0 0 2px currentColor inset; font-weight: 700; }
.flow-clear-btn {
  font-family: var(--body); font-size: 11px; font-weight: 400; background: none; border: none;
  color: var(--steel); text-decoration: underline; cursor: pointer; padding: 0; margin-left: 6px;
}

/* Copies count on a file line — needs to catch a shop staffer's eye before the
   filename, so it borrows the status-stamp look (bordered, tinted) rather than
   blending in as another muted .notice like the file size next to it. */
.copies-badge {
  font-family: var(--mono); font-weight: 700; font-size: 12px;
  padding: 2px 7px; margin-right: 6px; border: 1.5px solid var(--amber); border-radius: 2px;
  background: var(--tint-pink-bg); color: var(--tint-pink-text);
  white-space: nowrap; display: inline-block;
}

.jobnum { font-family: var(--mono); font-weight: 600; letter-spacing: 0.02em; }
.prio { font-family: var(--mono); font-size: 11px; text-transform: uppercase; }
.prio-high { color: var(--red); font-weight: 700; }
.prio-low { color: var(--muted-warm); }

/* ---- Cards / traveler tags ---- */
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: 6px;
  padding: 14px 16px; margin-bottom: 12px;
}
.tag-card {
  position: relative; padding-left: 34px; display: block;
  text-decoration: none; color: inherit; transition: border-color 0.12s ease;
}
.tag-card:hover { border-color: var(--steel); }
.tag-card::before {           /* punched hole, like a hung shop tag */
  content: ""; position: absolute; left: 12px; top: 18px; width: 10px; height: 10px;
  border-radius: 50%; background: var(--paper); border: 2px solid var(--line);
}
.tag-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.tag-title { font-weight: 600; font-size: 15.5px; }
.tag-meta { color: var(--ink-soft); font-size: 13px; margin-top: 2px; }
.tag-row-right { margin-left: auto; }

/* ---- Disk usage bar (admin settings) ---- */
.usage-bar {
  display: flex; width: 100%; height: 20px; border-radius: 5px; overflow: hidden;
  border: 1px solid var(--line); background: var(--tint-gray-bg);
}
/* flex-shrink:0 so a tiny non-zero segment's min-width floor (set inline,
   only when its byte count is actually > 0) can't get squeezed back to
   nothing — on a real disk the app's footprint is usually well under 1% of
   total capacity, which would otherwise round to an invisible sliver. */
.usage-bar-seg { height: 100%; flex-shrink: 0; }
.usage-bar-seg.uploads { background: var(--steel); }
.usage-bar-seg.app-other { background: var(--ink-soft); }
.usage-legend {
  display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 8px; font-size: 13px; color: var(--ink-soft);
}
.usage-legend span { display: inline-flex; align-items: center; gap: 6px; }
.usage-legend .swatch { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.usage-legend .swatch.uploads { background: var(--steel); }
.usage-legend .swatch.app-other { background: var(--ink-soft); }
.usage-legend .swatch.other { background: var(--tint-gray-bg); border: 1px solid var(--line); }

/* ---- Traveler header on the detail page ---- */
.traveler {
  background: var(--card); border: 1px solid var(--line); border-left: 6px solid var(--amber);
  border-radius: 6px; padding: 16px 18px; margin: 18px 0;
}
.traveler-top { display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap; }
.traveler h1 { margin: 4px 0 2px; }
.traveler-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px 18px; margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--line);
}
.spec { font-size: 13px; }
.spec b { display: block; font-family: var(--mono); font-size: 11px; text-transform: uppercase;
  color: var(--ink-soft); font-weight: 600; letter-spacing: 0.05em; }
.spec span { font-family: var(--mono); font-size: 13px; }

/* ---- Tables ---- */
table.grid { width: 100%; border-collapse: collapse; background: var(--card);
  border: 1px solid var(--line); border-radius: 6px; overflow: hidden; font-size: 14px; }
.grid th {
  font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  text-align: left; color: var(--ink-soft); background: var(--table-head-bg);
  padding: 8px 10px; border-bottom: 1px solid var(--line);
}
.grid td { padding: 8px 10px; border-bottom: 1px solid var(--table-row-border); vertical-align: top; }
.grid tr:last-child td { border-bottom: none; }

/* ---- Per-column sort + filter (Queue / History table headers) ---- */
.th-inner { display: flex; align-items: center; gap: 3px; }
.th-label { flex: 0 0 auto; }
.sort-arrow {
  font-size: 11px; line-height: 1; color: var(--filter-icon); text-decoration: none; padding: 2px 1px;
}
.sort-arrow:hover { color: var(--ink-soft); }
.sort-arrow.active { color: var(--steel); }
.col-filter { position: relative; margin-left: 1px; }
.col-filter > summary {
  list-style: none; cursor: pointer; color: var(--filter-icon); font-size: 11px; padding: 2px 3px;
  border-radius: 2px;
}
.col-filter > summary::-webkit-details-marker { display: none; }
.col-filter[open] > summary, .col-filter > summary:hover { color: var(--ink-soft); background: var(--filter-hover-bg); }
.filter-badge {
  font-family: var(--mono); font-size: 11px; background: var(--steel); color: var(--steel-ink);
  border-radius: 8px; padding: 0 4px; margin-left: 2px;
}
.col-filter-panel {
  position: absolute; top: 100%; left: 0; z-index: 20; margin-top: 4px;
  background: var(--card); border: 1px solid var(--line); border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.14); padding: 8px 10px; min-width: 170px;
  max-height: 260px; overflow-y: auto;
  text-transform: none; letter-spacing: normal; font-family: var(--body); font-size: 13px;
}
.col-filter-opt {
  display: flex; align-items: center; gap: 6px; padding: 3px 0; font-weight: 400;
  white-space: nowrap; cursor: pointer;
}
.col-filter-opt input { width: auto; margin: 0; }
.col-filter-group-label {
  font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--ink-soft); margin: 6px 0 2px;
}
.col-filter-group-label:first-child { margin-top: 0; }
.col-filter-panel-search { display: flex; gap: 6px; min-width: 220px; }
.col-filter-panel-search input[type="text"] { margin: 0; width: 100%; padding: 5px 7px; font-size: 13px; }

.view-menu { position: relative; display: inline-block; }
.view-menu > summary { list-style: none; cursor: pointer; }
.view-menu > summary::-webkit-details-marker { display: none; }
.view-menu-panel { min-width: 240px; }
.saved-view-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 3px 0; font-weight: 400; white-space: nowrap;
}
.saved-view-row form { margin: 0; }
.saved-view-link { overflow: hidden; text-overflow: ellipsis; }
.save-view-form { display: flex; gap: 6px; margin-top: 4px; }
.save-view-form input[type="text"] { margin: 0; padding: 5px 7px; font-size: 13px; width: 140px; }

/* ---- Forms ---- */
label.f { display: block; margin-bottom: 12px; font-size: 14px; font-weight: 600; }
label.f small { display: block; font-weight: 400; color: var(--ink-soft); }
label.f-nested { padding-left: 12px; border-left: 2px solid var(--line); margin-left: 2px; }
/* "Other" free-text answer on a select field, and an admin-written per-choice
   warning (e.g. "1/2" plywood" -> "Increased lead time"): blue/steel like the
   cloud-link warning tint (not red) — a heads-up, not an error, so it doesn't
   read as something being wrong with the submission. */
.field-other-warning, .field-choice-warning {
  margin-top: 6px; padding: 6px 10px; font-size: 12.5px; font-weight: 400;
  color: var(--ink-soft); background: var(--tint-blue-bg); border: 1px solid var(--steel);
  border-radius: 4px;
}
input[type=text], input[type=email], input[type=number], input[type=date],
input[type=datetime-local], input[type=time], input[type=file], select, textarea {
  width: 100%; padding: 8px 10px; border: 1px solid var(--input-border); border-radius: 4px;
  font: inherit; background: var(--input-bg); color: var(--ink); margin-top: 4px;
}
textarea { min-height: 84px; resize: vertical; }
.comment-body-public { border: 2px solid var(--red); }
input:focus, select:focus, textarea:focus, button:focus, a:focus {
  outline: 2px solid var(--steel); outline-offset: 1px;
}
.btn {
  display: inline-block; border: 1px solid var(--navy); background: var(--navy); color: var(--topbar-strong);
  font-family: var(--display); text-transform: uppercase; letter-spacing: 0.06em;
  font-size: 13.5px; padding: 8px 16px; border-radius: 4px; cursor: pointer;
}
.btn:hover { background: var(--navy-hover); }
.btn-amber { background: var(--amber); border-color: var(--amber); color: var(--amber-ink); font-weight: 600; }
.btn-amber:hover { background: var(--amber-hover); }
.btn-quiet { background: transparent; color: var(--ink); }
.btn-quiet:hover { background: var(--quiet-hover-bg); }
.btn-danger { background: transparent; border-color: var(--red); color: var(--red); }
.btn-danger:hover { background: var(--tint-red-bg); }
.btn-sm { padding: 4px 10px; font-size: 12px; }

.form-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 22px; }
.form-cols > * { min-width: 0; }  /* let a wide table scroll instead of widening its column */
@media (max-width: 700px) { .form-cols { grid-template-columns: 1fr; } }
fieldset { border: 1px solid var(--line); border-radius: 6px; margin: 0 0 16px; padding: 12px 16px; background: var(--card);
  min-width: 0; }  /* browsers default fieldsets to min-content, which won't shrink on a phone */
legend { font-family: var(--display); text-transform: uppercase; letter-spacing: 0.05em; font-size: 13.5px; padding: 0 6px; }

/* !important because element rules like input[type=file] { width: 100% }
   out-rank a lone class, and a "hidden" input that's really full width
   pushes the page sideways on a phone. */
.visually-hidden {
  position: absolute !important; width: 1px !important; height: 1px !important;
  padding: 0 !important; margin: -1px !important; overflow: hidden !important;
  clip: rect(0,0,0,0) !important; white-space: nowrap !important; border: 0 !important;
}

/* Skip link: off-screen until it receives keyboard focus, then pinned top-left. */
.skip-link {
  position: absolute; left: 8px; top: -48px; z-index: 1000;
  background: var(--navy); color: var(--topbar-strong); padding: 8px 14px; border-radius: 0 0 4px 4px;
  text-decoration: none; transition: top 0.15s ease;
}
.skip-link:focus { top: 0; }
/* The main landmark takes focus from the skip link but shouldn't show an outline itself. */
main:focus { outline: none; }

/* ---- File upload dropzone + live-validated file list ---- */
.dropzone {
  border: 1.5px dashed var(--line); border-radius: 6px; padding: 16px; text-align: center;
  margin-top: 4px; transition: border-color 0.12s ease, background 0.12s ease;
}
.dropzone-active { border-color: var(--steel); background: var(--tint-blue-bg); }
/* The real file input is visually hidden inside the dropzone, so when keyboard
   focus lands on it, ring the whole zone — otherwise focus just disappears. */
.dropzone:focus-within { outline: 2px solid var(--steel); outline-offset: 2px; border-color: var(--steel); }
.dropzone-hint { margin: 0; font-size: 13px; color: var(--ink-soft); }
.dropzone-browse { color: var(--steel); text-decoration: underline; cursor: pointer; font-weight: 600; }
.file-upload-list { list-style: none; margin: 10px 0 0; padding: 0; }
.file-upload-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  padding: 7px 10px; border: 1px solid var(--line); border-radius: 4px; margin-bottom: 6px;
  font-size: 13px;
}
.file-upload-row-error { border-color: var(--red); background: var(--tint-red-bg); }
.file-upload-name { font-weight: 600; overflow-wrap: anywhere; }
.file-upload-size { color: var(--ink-soft); font-family: var(--mono); font-size: 12px; }
.file-upload-copies {
  font-family: var(--mono); font-size: 11px; text-transform: uppercase; color: var(--ink-soft);
  display: flex; align-items: center; gap: 4px; margin-left: auto;
}
.file-upload-copies input { width: 60px; margin: 0; padding: 3px 6px; }
.file-upload-remove { padding: 3px 8px; font-size: 11px; }
.file-upload-error { flex-basis: 100%; color: var(--tint-red-text); font-size: 12px; }

/* ---- Repeatable fabrication blocks (new-submission form) ---- */
.fab-block { position: relative; }
.fab-block-remove { position: absolute; top: 10px; right: 12px; padding: 3px 8px; font-size: 11px; }

/* ---- Live cloud-link check results ----
   This list is just early feedback and never itself blocks typing/adding
   more links — but -error rows mean the real, server-side submission check
   will reject that link as-is, while -warning rows (Box/Drive's "might need
   a sign-in" heuristic) are informational only and won't block submission. */
.link-check-list { list-style: none; margin: 8px 0 0; padding: 0; }
.link-check-row {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  padding: 5px 10px; border: 1px solid var(--line); border-radius: 4px; margin-bottom: 6px;
  font-size: 12.5px;
}
/* Warning uses the blue/steel tint (not red) so it reads as "heads up,
   informational" — clearly distinct from -error, which is red because that
   link really will block submission unchanged. */
.link-check-row-warning { border-color: var(--steel); background: var(--tint-blue-bg); }
.link-check-row-error { border-color: var(--red); background: var(--tint-red-bg); }
.link-check-url { font-family: var(--mono); font-size: 12px; overflow-wrap: anywhere; }
.link-check-msg { color: var(--ink-soft); }
.link-check-row-error .link-check-msg { color: var(--tint-red-text); }

/* ---- Filter bars ---- */
.filters { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end; margin: 12px 0 14px; }
.filters label { font-family: var(--mono); font-size: 11px; text-transform: uppercase; color: var(--ink-soft); }
.filters select, .filters input { margin-top: 2px; width: auto; min-width: 120px; padding: 5px 8px; font-size: 13px; }

/* ---- Admin sub-navigation (tabs across every admin-only page) ---- */
.admin-subnav {
  display: flex; gap: 2px; flex-wrap: wrap; align-items: center;
  margin: 4px 0 10px; padding-bottom: 0; border-bottom: 1px solid var(--line);
}
.admin-subnav a {
  font-family: var(--display); text-transform: uppercase; letter-spacing: 0.05em;
  font-size: 13px; color: var(--ink-soft); text-decoration: none;
  padding: 8px 12px; border-bottom: 3px solid transparent;
}
.admin-subnav a:hover { color: var(--ink); }
.admin-subnav a.active { color: var(--ink); font-weight: 700; border-bottom-color: var(--amber); }

/* ---- Comments & history ---- */
.comment { border-left: 3px solid var(--line); padding: 6px 12px; margin-bottom: 10px; }
.comment.internal { border-left-color: var(--amber); background: var(--tint-pink-bg); }
.comment-head { font-size: 12.5px; color: var(--ink-soft); }
.comment-head b { color: var(--ink); }
.internal-flag { font-family: var(--mono); font-size: 11px; text-transform: uppercase;
  color: var(--tint-pink-text); border: 1px solid var(--internal-flag-border); padding: 0 5px; border-radius: 2px; }
.comment-body { white-space: pre-wrap; }
.comment-image {
  display: block; max-width: 320px; max-height: 320px; margin-top: 6px;
  border: 1px solid var(--line); border-radius: 6px; cursor: zoom-in;
}
.history { list-style: none; padding: 0; margin: 0; font-size: 13px; }
.history li { padding: 5px 0; border-bottom: 1px dashed var(--line); }
.history .h-when { font-family: var(--mono); font-size: 11.5px; color: var(--ink-soft); }

/* ---- Two-column detail layout ---- */
.detail-cols { display: grid; grid-template-columns: 1.6fr 1fr; gap: 16px; align-items: start; }
/* Without this a column grows to fit a preview canvas's pixel width, so the
   previews (which resize to their box) never get the chance to shrink. */
.detail-cols > * { min-width: 0; }
@media (max-width: 820px) { .detail-cols { grid-template-columns: 1fr; } }

/* ---- Misc ---- */
.empty { color: var(--ink-soft); background: var(--card); border: 1px dashed var(--line);
  border-radius: 6px; padding: 22px; text-align: center; margin: 14px 0; }
.foot { padding: 26px 16px; color: var(--muted-warm); font-size: 12px; }
.foot-info { margin: 0 0 8px; }
.foot-info a { color: inherit; text-decoration: underline; }
.foot-links { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; }
.dev-banner { font-family: var(--mono); font-size: 11px; color: var(--tint-red-text);
  border: 1px dashed var(--red); padding: 3px 8px; border-radius: 3px; }
.pill-count { font-family: var(--mono); font-size: 11px; background: var(--navy); color: var(--topbar-strong);
  border-radius: 10px; padding: 1px 7px; }
.file-line { font-family: var(--mono); font-size: 12.5px; }
.carry-file-list { list-style: none; padding-left: 0; margin: 0 0 12px; }

/* Staff-only per-file "done" checklist — bookkeeping only, never gates a
   status change. Checking it off just dims/strikes the filename so a shop
   staffer can see at a glance what's left in a long file list. */
.file-done-toggle {
  font-family: var(--mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--ink-soft);
  display: inline-flex; align-items: center; gap: 4px; margin-left: 8px; cursor: pointer;
}
.file-done-toggle input { width: auto; margin: 0; }
.file-line-done .file-name-link,
.file-line-done .copies-badge {
  /* Muted color, not opacity: faded text drops below readable contrast. */
  text-decoration: line-through; color: var(--muted-warm);
}
details.rowdetail summary { cursor: pointer; color: var(--steel); font-size: 13px; }
.notice { font-size: 13px; color: var(--ink-soft); }
.process-info-text {
  white-space: pre-wrap; border-left: 3px solid var(--line); padding: 6px 12px; margin: 2px 0 14px;
}

/* ---- Collapsible process cards (Processes admin page) ---- */
.process-card > summary.process-card-summary { cursor: pointer; padding: 2px 0; }
.process-card-summary-inner {
  display: inline-flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-left: 6px;
}
.login-box { max-width: 420px; margin: 28px auto 60px; }
.login-box .card { padding: 26px; }
.login-title { margin-top: 0; }

/* ---- Sign-in page: feature overview (templates/login.html) ----
   The .feature-shot mocks are drawn from theme tokens only, so they follow
   dark mode and every color scheme. Decorative: aria-hidden in the markup. */
.landing-page { max-width: 1100px; margin: 0 auto; }
.landing { margin-top: 36px; text-align: center; }
.landing-kicker {
  font-family: var(--mono); font-size: 12px; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--ink-soft); margin: 0;
}
.landing-title { font-size: 30px; margin: 6px 0 8px; }
.landing-sub { max-width: 620px; margin: 0 auto 22px; font-size: 16px; }
.feature-grid {
  list-style: none; margin: 0; padding: 0; text-align: left;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px;
}
.feature { margin: 0; padding: 0; overflow: hidden; border-top: 4px solid var(--ws-projects); }
.feature-orgs { border-top-color: var(--ws-orgs); }
.feature-teams { border-top-color: var(--ws-teams); }
.feature-title { font-size: 16px; margin: 14px 16px 4px; }
.feature-text { margin: 0 16px 16px; font-size: 14px; color: var(--ink-soft); }
.feature-shot {
  height: 150px; display: flex; align-items: center; justify-content: center;
  background: var(--paper); border-bottom: 1px solid var(--line); padding: 14px;
}
.feature-shot img { width: 100%; height: 100%; object-fit: cover; object-position: top left; }
.mock-tag {
  width: 100%; max-width: 220px; background: var(--card); border: 1px solid var(--line);
  border-radius: 5px; padding: 10px 12px; display: flex; flex-direction: column; gap: 7px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
}
.mock-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.mock-row .stamp { font-size: 9.5px; padding: 1px 6px; }
.mock-num, .mock-file, .mock-meta { font-family: var(--mono); font-size: 11px; color: var(--ink-soft); }
.mock-title { font-weight: 600; font-size: 13.5px; }
.mock-steps { display: flex; gap: 4px; }
.mock-steps i { flex: 1; height: 5px; border-radius: 3px; background: var(--line); }
.mock-steps i.on { background: var(--ws-projects); }
.mock-avatars { display: flex; }
.mock-avatars span {
  width: 30px; height: 30px; border-radius: 50%; margin-right: -6px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  background: var(--navy); color: #fff; border: 2px solid var(--card);
}
.mock-avatars span:nth-child(2) { background: var(--steel); color: var(--steel-ink); }
.mock-avatars span:nth-child(3) { background: var(--amber); color: var(--amber-ink); }
.mock-avatars .mock-avatar-add {
  background: var(--card); color: var(--ink-soft); border: 2px dashed var(--input-border); font-size: 14px;
}
.mock-org { border-left: 4px solid var(--ws-orgs); }
.mock-line { display: flex; align-items: center; gap: 8px; }
.mock-dt { font-family: var(--mono); font-size: 9.5px; text-transform: uppercase; color: var(--ink-soft); width: 64px; }
.mock-bar { height: 6px; border-radius: 3px; background: var(--line); }
.mock-chips { display: flex; gap: 5px; flex-wrap: wrap; }
.mock-chips span {
  font-size: 10.5px; padding: 1px 7px; border-radius: 10px;
  background: var(--tint-green-bg); color: var(--tint-green-text); border: 1px solid var(--ws-orgs);
}
.mock-qr-wrap { display: flex; align-items: center; gap: 16px; }
.mock-qr { width: 104px; height: 104px; background: #fff; border-radius: 4px; fill: #001E62; }
.mock-count { display: flex; flex-direction: column; line-height: 1.1; }
.mock-count strong { font-family: var(--display); font-size: 34px; color: var(--ws-orgs); }
.mock-count span { font-family: var(--mono); font-size: 11px; text-transform: uppercase; color: var(--ink-soft); }
/* On a phone the four tiles are a long scroll, so sign-in moves up under
   the headline instead of waiting below them. */
@media (max-width: 700px) {
  .landing-page { display: flex; flex-direction: column; }
  .landing-page .login-box { order: 1; width: 100%; margin: 0 auto 24px; }
  .landing-page .feature-grid { order: 2; }
  .landing { margin-top: 20px; }
  .landing-title { font-size: 24px; }
}
hr.dashed { border: none; border-top: 1px dashed var(--line); margin: 14px 0; }

/* ---- File previews: STL 3D, DXF/SVG 2D, PDF ---- */
.stl-viewer, .vector-viewer, .pdf-viewer {
  position: relative; width: 100%; height: 320px; border: 1px solid var(--line);
  border-radius: 6px; overflow: hidden; background: var(--paper);
}
.stl-viewer canvas { display: block; }
.stl-viewer-status, .vector-viewer-status, .pdf-viewer-status {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: var(--ink-soft); font-size: 13px; text-align: center; padding: 0 12px;
}
.stl-viewer-dims, .vector-viewer-dims, .pdf-viewer-pager {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 4px 8px;
  font-family: var(--mono); font-size: 11px; color: var(--ink-soft);
  background: var(--overlay-bg); border-top: 1px solid var(--line);
}
.stl-viewer-hint, .vector-viewer-hint {
  position: absolute; right: 8px; top: 6px; font-size: 11px; color: var(--ink-soft);
  background: var(--overlay-bg); padding: 1px 6px; border-radius: 3px;
}

.vector-viewer { cursor: grab; touch-action: none; }
.vector-viewer:active { cursor: grabbing; }
.vector-viewer-svg {
  width: 100%; height: 100%; object-fit: contain; transform-origin: center center;
}
img.vector-viewer-svg { padding: 8px; box-sizing: border-box; }
svg.vector-viewer-svg .vector-viewer-marks {
  stroke: var(--ink); stroke-width: 1.2; fill: none; vector-effect: non-scaling-stroke;
}
svg.vector-viewer-svg .vector-viewer-marks line,
svg.vector-viewer-svg .vector-viewer-marks path,
svg.vector-viewer-svg .vector-viewer-marks polyline,
svg.vector-viewer-svg .vector-viewer-marks polygon {
  stroke: var(--ink); stroke-width: 1.2; fill: none; vector-effect: non-scaling-stroke;
}
svg.vector-viewer-svg .vector-viewer-point { fill: var(--steel); stroke: none; }

.media-viewer { text-align: center; }
.media-viewer img {
  max-width: 100%; max-height: 400px; border: 1px solid var(--line); border-radius: 6px;
}

.pdf-viewer { display: flex; align-items: center; justify-content: center; }
.pdf-viewer canvas { max-width: 100%; max-height: 100%; }
.pdf-viewer-pager {
  display: flex; align-items: center; gap: 8px; justify-content: center; background: var(--card);
}
.pdf-viewer-pager button {
  font-family: var(--mono); font-size: 11px; padding: 2px 8px; border: 1px solid var(--line);
  background: var(--card); border-radius: 3px; cursor: pointer;
}
.pdf-viewer-pager button:disabled { opacity: 0.4; cursor: default; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
@media (max-width: 700px) {
  /* Truncated, not hidden: it is the only link to Settings (color schemes). */
  .whoami-name { max-width: 9em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  h1 { font-size: 22px; }
  .grid th:nth-child(n+5), .grid td:nth-child(n+5) { display: none; } /* trim wide tables on phones */
  table.grid.keep-cols th, table.grid.keep-cols td { display: table-cell; }
  /* A table still wider than the screen scrolls on its own instead of dragging
     the whole page sideways (WCAG 1.4.10). Not the queue/history tables: their
     header filter pop-ups would be clipped inside a scroll box. */
  table.grid:not(:has(.col-filter)) { display: block; overflow-x: auto; }
  .col-filter-panel { max-width: calc(100vw - 32px); }
  /* The saved-views menu opens in place on a phone rather than floating off the right edge. */
  .view-menu-panel { position: static; min-width: 0; box-shadow: none; }
}

/* ---- Guided demo / tutorial mode ---- */
/* Topbar "Replay demo" button — sits next to the dark-mode toggle and borrows
   the same quiet-on-navy treatment. */
.tour-replay {
  background: transparent; border: 1px solid var(--topbar-border); color: var(--topbar-text);
  border-radius: 4px; font-size: 12px; line-height: 1; padding: 5px 9px; cursor: pointer;
  font-family: var(--display); text-transform: uppercase; letter-spacing: 0.05em;
}
.tour-replay:hover { background: rgba(255,255,255,0.08); }

/* The whole tour lives in a fixed layer above everything else. Children opt
   back into pointer events; the root itself is transparent to clicks. */
.tour-root { position: fixed; inset: 0; z-index: 10000; pointer-events: none; }
.tour-root > * { pointer-events: auto; }
body.tour-lock { overflow: hidden; }

/* Full-screen click trap so the real page underneath can't be interacted with
   mid-tour (fields are filled programmatically, so nothing is lost). */
.tour-blocker { position: fixed; inset: 0; background: transparent; }
/* Dark scrim for centered modal steps. */
.tour-dim { position: fixed; inset: 0; background: rgba(3, 8, 20, 0.62); }
/* Spotlight: a transparent hole with a huge box-shadow that dims everything
   around the highlighted control, plus a bright ring drawing the eye to it. */
.tour-spotlight {
  position: fixed; border-radius: 7px; display: none;
  box-shadow: 0 0 0 9999px rgba(3, 8, 20, 0.62);
  outline: 3px solid var(--amber); outline-offset: 2px;
  transition: top 0.2s ease, left 0.2s ease, width 0.2s ease, height 0.2s ease;
}

.tour-banner {
  position: fixed; top: 10px; left: 50%; transform: translateX(-50%);
  background: var(--amber); color: var(--amber-ink); font-weight: 600;
  font-size: 12.5px; padding: 6px 14px; border-radius: 999px; max-width: 92vw;
  text-align: center; box-shadow: 0 4px 14px rgba(0,0,0,0.28);
}

.tour-tooltip {
  position: fixed; width: 340px; max-width: calc(100vw - 24px);
  background: var(--card); color: var(--ink); border: 1px solid var(--line);
  border-radius: 10px; padding: 16px 16px 14px; box-shadow: 0 10px 34px rgba(0,0,0,0.34);
}
/* Focused programmatically on every step (see tour.js render()) so screen
   readers announce the updated title/body; keep that visible for sighted
   keyboard users too instead of falling back to the browser's default ring. */
.tour-tooltip:focus { outline: 2px solid var(--steel); outline-offset: 2px; }
.tour-tooltip-modal { top: 50%; left: 50%; transform: translate(-50%, -50%); width: 420px; }
.tour-tip-step { font-family: var(--mono); font-size: 11px; color: var(--muted-warm); text-transform: uppercase; letter-spacing: 0.05em; }
.tour-tip-title { margin: 4px 0 8px; }
.tour-tip-body { margin: 0 0 14px; font-size: 14px; line-height: 1.55; }
.tour-tip-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.tour-nav { display: flex; gap: 8px; }
.tour-exit {
  background: transparent; border: none; color: var(--muted-warm);
  font-size: 12.5px; text-decoration: underline; cursor: pointer; padding: 4px 2px;
}
.tour-exit:hover { color: var(--red); }

/* Little pointer from the tooltip toward the highlighted control. */
.tour-arrow { position: absolute; width: 0; height: 0; border-style: solid; }
.tour-arrow-up {
  top: -9px; border-width: 0 9px 9px 9px;
  border-color: transparent transparent var(--card) transparent;
  filter: drop-shadow(0 -1px 0 var(--line));
}
.tour-arrow-down {
  bottom: -9px; border-width: 9px 9px 0 9px;
  border-color: var(--card) transparent transparent transparent;
  filter: drop-shadow(0 1px 0 var(--line));
}

/* Simulated project-detail page shown in the final phase (no real project
   exists). Fixed, own scroll, sits just below the tour overlay. */
.tour-mock {
  position: fixed; inset: 0; overflow-y: auto; z-index: 9990;
  background: var(--paper); padding: 54px 16px 40px;
}
.tour-mock .traveler, .tour-mock .detail-cols { max-width: 1100px; margin-left: auto; margin-right: auto; }
.tour-mock-badge {
  max-width: 1100px; margin: 0 auto 12px; text-align: center;
  font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--tint-pink-text); background: var(--tint-pink-bg);
  border: 1px dashed var(--internal-flag-border); border-radius: 6px; padding: 6px 10px;
}
.tour-mock-preview {
  border: 1px dashed var(--line); border-radius: 6px; padding: 22px; text-align: center;
  color: var(--muted-warm); font-family: var(--mono); font-size: 12px; margin-top: 8px;
}
/* The mock's action "buttons" are inert spans styled to look like the real ones. */
.tour-mock .btn { cursor: default; }

@media (max-width: 700px) {
  .tour-tooltip, .tour-tooltip-modal { width: calc(100vw - 24px); }
}

/* ---- Cookie notice -------------------------------------------------------
   Bottom banner on first visit, plus the "About Cookies" panel it opens.
   Sits below the tour layer (z-index 10000) so a running tour still wins.
   app.js pads the body while the banner is up so it never covers the footer. */
.cookie-notice {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 9000;
  background: var(--card); color: var(--ink); border-top: 2px solid var(--navy);
  box-shadow: 0 -6px 22px rgba(0, 0, 0, 0.18);
}
.cookie-notice-inner {
  position: relative; max-width: 1400px; margin: 0 auto;
  padding: 16px 46px 16px 10px;
  display: grid; grid-template-columns: 1fr auto; gap: 6px 24px; align-items: center;
}
.cookie-notice-title { grid-column: 1; margin: 0; font-size: 17px; }
.cookie-notice-body { grid-column: 1; margin: 0; font-size: 13.5px; max-width: 115ch; }
.cookie-notice-actions {
  grid-column: 2; grid-row: 1 / span 2;
  display: flex; flex-direction: column; gap: 8px; white-space: nowrap;
}
.cookie-notice-actions .btn { text-align: center; }

/* Shared dismiss "×" for the banner and the panel. */
.cookie-x {
  position: absolute; top: 8px; right: 8px;
  background: transparent; border: none; color: var(--muted-warm);
  font-size: 24px; line-height: 1; padding: 2px 8px; border-radius: 4px; cursor: pointer;
}
.cookie-x:hover { color: var(--ink); background: var(--quiet-hover-bg); }

.cookie-panel { position: fixed; inset: 0; z-index: 9500; }
.cookie-panel-scrim { position: absolute; inset: 0; background: rgba(3, 8, 20, 0.62); }
.cookie-panel-box {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 760px; max-width: calc(100vw - 24px); max-height: calc(100vh - 48px);
  display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.4);
}
.cookie-panel-box:focus { outline: 2px solid var(--steel); outline-offset: 2px; }
.cookie-panel-head {
  position: relative; padding: 14px 46px 12px 18px; border-bottom: 1px solid var(--line);
}
.cookie-panel-head h2 { margin: 0; font-size: 18px; }
.cookie-panel-head .cookie-x { top: 10px; }
/* Only the body scrolls, so the heading and close button stay reachable. */
.cookie-panel-scroll { overflow-y: auto; padding: 14px 18px; font-size: 13.5px; line-height: 1.6; }
.cookie-panel-scroll > p { margin: 0 0 14px; }
.cookie-panel-foot {
  padding: 12px 18px; border-top: 1px solid var(--line); text-align: right;
}

/* One collapsible block per cookie category. */
.cookie-cat { border-top: 1px solid var(--line); padding: 10px 0 2px; }
.cookie-cat > summary {
  cursor: pointer; font-family: var(--display); text-transform: uppercase;
  letter-spacing: 0.04em; font-size: 14px; padding: 2px 0;
}
.cookie-cat > summary:hover { color: var(--steel); }
.cookie-cat > p { margin: 8px 0 12px; }

/* Footer entry point to reopen the panel after the banner is dismissed. */
.cookie-settings-link {
  background: none; border: none; padding: 0; font: inherit;
  color: inherit; text-decoration: underline; cursor: pointer;
}

@media (max-width: 700px) {
  .cookie-notice-inner { grid-template-columns: 1fr; padding-right: 10px; padding-top: 34px; }
  .cookie-notice-actions { grid-column: 1; grid-row: auto; flex-direction: row; flex-wrap: wrap; white-space: normal; }
  .cookie-notice-actions .btn { flex: 1 1 auto; }
  .cookie-panel-box { max-height: calc(100vh - 24px); }
}

/* ---- "View as" banner (admin testing aid) + personal settings page ---- */
.view-as-banner { background: var(--amber); color: var(--amber-ink); border-bottom: 2px solid var(--ink); }
.view-as-banner-inner { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; padding-top: 8px; padding-bottom: 8px; font-size: 14px; }
.view-as-banner form { margin: 0; }
.scheme-options { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  border: 0; padding: 0; margin: 0 0 14px; }
.scheme-option { display: flex; flex-direction: column; gap: 6px; border: 2px solid var(--line);
  border-radius: 6px; padding: 10px 12px; cursor: pointer; background: var(--card); }
.scheme-option:has(input:checked) { border-color: var(--steel); }
.scheme-option:focus-within { outline: 2px solid var(--steel); outline-offset: 2px; }
.scheme-option-head { display: flex; align-items: center; gap: 8px; font-weight: 600; }
.scheme-option-head input { width: auto; margin: 0; }
.scheme-swatches { display: flex; gap: 4px; }
.scheme-swatches span { width: 22px; height: 22px; border-radius: 3px; border: 1px solid var(--ink-soft); }
.mode-options { display: flex; gap: 16px; flex-wrap: wrap; border: 0; padding: 0; margin: 0; }
.mode-options label { display: flex; align-items: center; gap: 6px; }
.mode-options input { width: auto; margin: 0; }

/* ---- Workspaces: switcher + per-workspace accent (app/workspaces.py) ---- */
:root { --ws-projects: var(--amber); --ws-orgs: #1f8a70; --ws-teams: #6a4c9c; }
:root[data-theme="dark"] { --ws-orgs: #3fbf98; --ws-teams: #b39ddb; }
:root[data-scheme="high-contrast"] { --ws-orgs: #00e0a0; --ws-teams: #c9a0ff; }
.topbar { border-bottom: 4px solid transparent; }
.topbar.ws-projects { border-bottom-color: var(--ws-projects); }
.topbar.ws-orgs { border-bottom-color: var(--ws-orgs); }
.topbar.ws-teams { border-bottom-color: var(--ws-teams); }
.ws-switch { display: flex; border: 1px solid var(--topbar-border); border-radius: 4px; overflow: hidden; }
.ws-switch a {
  color: var(--topbar-link); text-decoration: none; font-family: var(--display); text-transform: uppercase;
  letter-spacing: 0.06em; font-size: 12.5px; padding: 4px 10px; border-left: 1px solid var(--topbar-border);
}
.ws-switch a:first-child { border-left: none; }
.ws-switch a:hover { color: var(--topbar-strong); background: rgba(255,255,255,0.08); }
.ws-switch a.active { color: var(--topbar-strong); font-weight: 700; box-shadow: inset 0 -3px 0 var(--ws-projects); }
.ws-switch a.ws-orgs.active { box-shadow: inset 0 -3px 0 var(--ws-orgs); }
.ws-switch a.ws-teams.active { box-shadow: inset 0 -3px 0 var(--ws-teams); }
.nav a.active { color: var(--topbar-strong); background: rgba(255,255,255,0.1); }

/* ---- Orgs workspace ---- */
.org-crumbs { margin: 14px 0 0; }
.org-title-link { color: inherit; text-decoration: none; }
.org-list, .app-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; margin-bottom: 16px; }
.org-card, .app-tile { display: flex; flex-direction: column; gap: 6px; text-decoration: none; color: var(--ink); }
.org-card:hover, .app-tile:hover { border-color: var(--ws-orgs); }
.org-card-name, .app-tile-name { font-family: var(--display); text-transform: uppercase; letter-spacing: 0.04em; font-size: 15px; }
.org-card-sub { border-left: 4px solid var(--ws-orgs); }
.info-list { display: grid; grid-template-columns: minmax(120px, 30%) 1fr; gap: 8px 16px; margin: 0; }
.info-list dt { font-family: var(--mono); font-size: 11px; text-transform: uppercase; color: var(--ink-soft); padding-top: 2px; }
.info-list dd { margin: 0; }
@media (max-width: 600px) { .info-list { grid-template-columns: 1fr; } .info-list dd { margin-bottom: 6px; } }
.table-scroll { overflow-x: auto; max-width: 100%; }
.perm-matrix th, .perm-matrix td { white-space: nowrap; }
.perm-matrix select { margin: 0; width: auto; font-size: 12.5px; padding: 3px 6px; }
.perm-matrix select.perm-0 { color: var(--ink-soft); }
.perm-matrix select.perm-2 { font-weight: 600; }
tr.row-muted td { color: var(--muted-warm); }  /* not opacity — see .file-line-done */

/* ---- User picker (typeahead; templates/_user_picker.html) ---- */
.user-picker { position: relative; display: block; min-width: 220px; }
.user-picker .user-picker-input { margin: 0; width: 100%; }
.user-picker-chosen .user-picker-input { border-color: var(--ink-soft); font-weight: 600; }
.user-picker-list {
  position: absolute; z-index: 30; left: 0; right: 0; top: 100%;
  margin: 2px 0 0; padding: 4px 0; list-style: none;
  background: var(--card); border: 1px solid var(--line); border-radius: 4px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.15); max-height: 280px; overflow-y: auto;
  font-size: 13px;
}
.user-picker-list li { padding: 6px 10px; cursor: pointer; }
.user-picker-list li[aria-selected="true"], .user-picker-list li:hover { background: var(--paper); }
.user-picker-list li.user-picker-new { font-weight: 600; border-top: 1px dashed var(--line); }
.user-picker-list li.user-picker-empty { color: var(--ink-soft); cursor: default; }

/* ---- Access chips (admin Users list, user access page) ---- */
.chips { display: flex; gap: 4px; flex-wrap: wrap; }
.chip {
  font-family: var(--mono); font-size: 11px; padding: 1px 7px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--paper); color: var(--ink); white-space: nowrap;
}
.chip-strong { border-color: var(--amber); }
.access-section { max-width: 820px; }
.access-section h2 { margin-top: 0; }
.access-list { list-style: none; padding: 0; margin: 0 0 10px; }
.access-list li { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 6px 0; border-bottom: 1px solid var(--line); }
.access-list li form { margin: 0; }
.inline-form { display: flex; gap: 6px; align-items: flex-end; flex-wrap: wrap; }
.inline-form .f { margin: 0; }
.pager { display: flex; gap: 10px; align-items: center; margin: 12px 0; font-size: 14px; }

/* ---- Profile ---- */
/* Settings "About you" form + the fill-in-your-profile banner. The [hidden]
   rule is needed because label.f and .form-cols set their own display. */
.profile-form [hidden] { display: none !important; }
.profile-form .mode-options { margin-bottom: 14px; }
.profile-prompt { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  flex-wrap: wrap; background: var(--tint-blue-bg); border-color: var(--steel); color: var(--ink); }
.profile-prompt-actions { display: flex; align-items: center; gap: 8px; }
.profile-prompt-actions form { margin: 0; }
.profile-line { margin: -10px 0 18px; }

/* ---- Attendance (Orgs workspace) and signing in ---- */
.mono { font-family: var(--mono); }
.nowrap { white-space: nowrap; }
.chip-ok { border-color: var(--green); color: var(--tint-green-text); background: var(--tint-green-bg); }
.att-section { max-width: 860px; }
.att-section h2 { margin-top: 0; }
.att-form [hidden], .profile-form [hidden], [data-kind][hidden], [data-qtype-options][hidden] { display: none !important; }
label.f small.hint-below { margin-top: 3px; }
.weekday-picks label { display: inline-flex; align-items: center; gap: 4px; margin-right: 12px; font-weight: 400; }
.qr-row { display: flex; gap: 14px; align-items: flex-start; padding: 10px 0; border-bottom: 1px solid var(--line); }
.qr-row.row-muted { color: var(--muted-warm); }
.qr-row.row-muted .qr-thumb { opacity: 0.5; }  /* a picture, so fading it is fine */
.qr-thumb { flex: none; display: block; width: 84px; height: 84px; background: #fff; border: 1px solid var(--line); border-radius: 4px; padding: 3px; }
.qr-thumb svg { width: 100%; height: 100%; display: block; }
.qr-info { flex: 1; min-width: 0; }
.qr-actions { margin-top: 6px; }
.qr-actions form { margin: 0; display: flex; gap: 6px; flex-wrap: wrap; }
.qr-add { margin-top: 14px; }
.qr-add h3 { margin: 0 0 8px; }
.qr-expiry label { display: inline-flex; align-items: center; gap: 6px; margin-right: 14px; font-weight: 400; }
.qr-expiry input[type=datetime-local] { width: auto; max-width: 100%; margin: 0; }
@media (max-width: 700px) {
  /* On a phone: thumbnail above its details, and the edit form's date field
     shrinks to fit (a percentage width lets an input compress). */
  .qr-row { flex-wrap: wrap; }
  .qr-info { flex-basis: 100%; }
  .qr-expiry label { flex-wrap: wrap; }
  .qr-expiry input[type=datetime-local] { width: 100%; }
}
.inline-edit { display: inline-block; }
.inline-edit[open] { display: block; flex-basis: 100%; }
.inline-edit > summary { list-style: none; }
.inline-edit > summary::-webkit-details-marker { display: none; }
.inline-edit > .card { margin-top: 8px; max-width: 640px; }
.question-row { padding: 8px 0; border-bottom: 1px solid var(--line); }
.question-row .inline-form { margin-top: 6px; }
.question-add { margin-top: 10px; }
.question-add > summary { list-style: none; display: inline-block; }
.question-add > .card { margin-top: 8px; max-width: 640px; }
.manual-add > summary { cursor: pointer; }
.filter-picks { display: flex; gap: 6px; flex-wrap: wrap; margin: 10px 0 0; }
.filter-pick { display: inline-flex; align-items: center; gap: 2px; font-family: var(--mono); font-size: 11px;
  text-transform: uppercase; color: var(--ink-soft); border: 1px solid var(--line); border-radius: 14px;
  padding: 2px 4px 2px 10px; background: var(--card); }
.filter-pick-on { border-color: var(--ws-orgs); color: var(--ink); }
.answer { font-size: 13px; margin-bottom: 4px; }
tr.row-private td { color: var(--ink-soft); }
tr.row-today td { background: var(--tint-green-bg); }
.checkin-box { max-width: 520px; margin: 24px auto; }
.checkin-event { border-top: 4px solid var(--ws-orgs); }
.checkin-event h1 { margin: 2px 0 6px; }
.checkin-unit { margin: 0; }
.checkin-when { margin: 0; }
.checkin-done h2 { color: var(--tint-green-text); margin-top: 0; }
.who-list { list-style: none; padding: 0; margin: 0 0 12px; }
.who-list li { padding: 8px 0; border-bottom: 1px solid var(--line); }
.share-box { margin: 12px 0 16px; border: 0; padding: 0; background: none; }
.share-box legend { padding: 0; margin-bottom: 8px; }
.share-choice { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; margin-bottom: 8px;
  border: 1px solid var(--line); border-radius: 6px; cursor: pointer; font-weight: 400; }
.share-choice:has(input:checked) { border-color: var(--ws-orgs); background: var(--tint-green-bg); }
.share-choice input { margin-top: 3px; }
.checkin-survey .f-label { display: block; font-weight: 600; margin-bottom: 4px; }
.check-line { display: flex; gap: 8px; align-items: center; font-weight: 400; padding: 3px 0; }
.rating { border: none; padding: 0; margin: 0 0 12px; background: none; }
.rating legend { font-family: inherit; text-transform: none; letter-spacing: 0; font-size: 14px; font-weight: 600; padding: 0; }
.rating label { display: inline-flex; align-items: center; gap: 4px; margin-right: 10px; }
.checkin-go { width: 100%; font-size: 16px; padding: 12px; }

/* Date/time picker with an Accept button (static/app.js datePickers) —
   desktop only; touch devices keep their native pickers. */
.dp-pop {
  position: absolute; z-index: 1000; width: 280px; padding: 10px;
  background: var(--card); color: var(--ink); border: 1px solid var(--line); border-radius: 6px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18); font-size: 14px; font-family: var(--body);
}
.dp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.dp-title { font-weight: 600; }
.dp-nav, .dp-day {
  border: 0; background: transparent; color: var(--ink); font: inherit; border-radius: 4px; cursor: pointer;
}
.dp-nav { width: 30px; height: 30px; font-size: 18px; line-height: 1; }
.dp-nav:hover, .dp-day:hover:not(:disabled) { background: var(--quiet-hover-bg); }
.dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dp-dow { text-align: center; font-size: 11px; font-weight: 600; color: var(--ink-soft); padding: 2px 0; }
.dp-day { height: 32px; }
.dp-day.is-today { box-shadow: inset 0 0 0 1px var(--steel); }
.dp-day[aria-pressed="true"], .dp-day[aria-pressed="true"]:hover { background: var(--steel); color: var(--steel-ink); font-weight: 600; }
.dp-day:disabled { opacity: 0.35; cursor: default; }
.dp-time { display: flex; align-items: center; gap: 4px; margin-top: 10px; }
.dp-time select { width: auto; margin: 0; padding: 4px 6px; }
.dp-foot { display: flex; align-items: center; gap: 6px; margin-top: 12px; }
.dp-spacer { flex: 1; }
.dp-foot .btn:disabled { opacity: 0.5; cursor: default; }

/* ---- Compact view for lists (templates/_density_toggle.html) ----
   Tighter rows everywhere; a table cell's secondary line (a <br> then a
   .notice) folds onto the line above instead of being hidden, and project
   cards collapse to a single line. */
.density-toggle { margin-left: auto; }
.density-toggle[aria-pressed="true"] { background: var(--tint-blue-bg); border-color: var(--steel); }
:root[data-density="compact"] .grid { font-size: 13px; }
:root[data-density="compact"] .grid th { padding: 5px 8px; }
:root[data-density="compact"] .grid td { padding: 3px 8px; line-height: 1.35; }
:root[data-density="compact"] .grid td br:has(+ .notice) { display: none; }
:root[data-density="compact"] .grid td br + .notice::before { content: " · "; }
:root[data-density="compact"] .grid td .btn-sm { padding: 2px 8px; }
:root[data-density="compact"] .tag-card { padding: 6px 12px 6px 30px; margin-bottom: 4px; }
:root[data-density="compact"] .tag-card::before { top: 11px; width: 8px; height: 8px; }
/* Link cards (My projects) go to one line: number, title, meta, status. */
:root[data-density="compact"] a.tag-card { display: flex; align-items: baseline; gap: 10px; }
:root[data-density="compact"] a.tag-card .tag-head { display: contents; }
:root[data-density="compact"] a.tag-card .jobnum { flex: none; }
:root[data-density="compact"] a.tag-card .tag-title { flex: 0 1 auto; min-width: 0; font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
:root[data-density="compact"] a.tag-card .tag-meta { order: 1; flex: 1 1 0; min-width: 0; margin: 0; font-size: 12.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
:root[data-density="compact"] a.tag-card .tag-row-right { order: 2; flex: none; }
:root[data-density="compact"] .qr-row { padding: 5px 0; }
@media (max-width: 640px) {
  :root[data-density="compact"] a.tag-card .tag-meta { display: none; }
}

/* ---- Teams workspace ---- */
.team-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; margin-bottom: 16px; }
.team-card { display: flex; flex-direction: column; gap: 6px; text-decoration: none; color: var(--ink); }
a.team-card:hover { border-color: var(--ws-teams); }
.team-card-name { font-family: var(--display); text-transform: uppercase; letter-spacing: 0.04em; font-size: 15px; color: var(--ink); }
.team-card-invite, .team-respond { border-left: 4px solid var(--ws-teams); }
.team-card-retired { opacity: 0.8; }
.team-card-actions { display: flex; gap: 8px; margin-top: 4px; }
.team-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 12px; margin-bottom: 12px; }
.team-manage .inline-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.teammate-picks { border: 0; padding: 0; margin: 0 0 10px; }
.teammate-pick { display: flex; gap: 8px; align-items: baseline; font-size: 14px; margin: 4px 0; }
/* "Submitting as" on the project form */
.team-choice-list { display: flex; flex-direction: column; gap: 6px; }
.team-choice { display: flex; gap: 10px; align-items: flex-start; padding: 8px 10px; border: 1px solid var(--line); border-radius: 4px; cursor: pointer; }
.team-choice input { width: auto; margin-top: 3px; }
.team-choice:has(input:checked) { border-color: var(--ws-teams); }
.team-on-project { border-left: 4px solid var(--ws-teams); }

/* ---- Custom themes (static/theme-derive.js; Settings page) ----
   While someone wears a custom theme (<html data-custom-theme>), their name in
   the topbar — the way back to Settings — is drawn in fixed UIC colors that no
   theme can touch, so it stays readable however garish the theme. The header
   light/dark toggle hides: a custom theme is one palette. */
:root[data-custom-theme] .whoami-name,
.theme-name-chip {
  background: #ffffff !important; color: #001E62 !important; font-weight: 600;
  padding: 2px 8px; border-radius: 3px; box-shadow: 0 0 0 2px #001E62;
  text-decoration: underline; opacity: 1 !important; visibility: visible !important;
}
:root[data-custom-theme] .theme-toggle { display: none; }

#custom-themes [hidden] { display: none !important; }
.theme-list { display: grid; gap: 8px; margin-bottom: 16px; }
.theme-item { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  border: 2px solid var(--line); border-radius: 6px; padding: 8px 12px; }
.theme-item.active { border-color: var(--steel); }
.theme-item-name { flex: 1 1 160px; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
.theme-item-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.theme-item-actions form { margin: 0; }
.theme-share-out { font-family: var(--mono); font-size: 12px; }

.theme-editor { display: grid; gap: 18px; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
@media (max-width: 760px) { .theme-editor { grid-template-columns: minmax(0, 1fr); } }
.color-fields { display: grid; gap: 8px 12px; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  border: 0; padding: 0; margin: 0 0 12px; background: none; }
.color-fields legend { font-weight: 600; font-size: 14px; padding: 0; margin-bottom: 6px; }
.color-field { display: flex; align-items: center; gap: 8px; font-size: 13.5px; }
.color-field input[type=color] { flex: none; width: 44px; height: 32px; padding: 2px; margin: 0; cursor: pointer;
  border: 1px solid var(--input-border); border-radius: 4px; background: var(--input-bg); }
.theme-row { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; }
.theme-row > label.f { flex: 1 1 200px; margin-bottom: 0; }
.theme-apply { display: flex; align-items: center; gap: 6px; margin: 12px 0; }
.theme-apply input { width: auto; margin: 0; }

/* Live preview: the editor sets the derived tokens on this box, and they
   cascade to the real components inside it. */
.theme-preview { border: 1px solid var(--line); border-radius: 6px; overflow: hidden;
  background: var(--paper); color: var(--ink); font-size: 14px; }
.theme-preview .topbar { display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-bottom-color: var(--amber); }
.theme-preview .topbar .brand { font-size: 14px; }
.theme-preview .theme-name-chip { margin-left: auto; font-size: 13px; }
.theme-preview-body { padding: 12px; display: grid; gap: 10px; }
.theme-preview-body .card { margin: 0; }
.theme-preview-body p { margin: 0 0 6px; }
.theme-preview-stamps { display: flex; gap: 6px; flex-wrap: wrap; }
