@import url("https://fonts.googleapis.com/css2?family=Urbanist:wght@400;500;600;700;800&display=swap");

/*
 * Portal/Admin design system — ported from klepon-marketing's confirmed
 * 2026 rebrand (see ../klepon-marketing/DESIGN.md and src/styles/global.css,
 * source: Klepon_2026_Huisstijl_v02A.pdf, confirmed 2026-08-28). This app
 * previously ran its own invented look (indigo/Inter, loosely modeled on a
 * third-party extension's UI); that's retired in favor of the real,
 * confirmed brand — navy ink + one signal green, Urbanist, pill buttons,
 * soft rounded cards. Token values below are copied from the marketing
 * repo's tokens, not re-derived — if that palette ever changes, re-copy
 * from there rather than hand-tuning here.
 *
 * The app-shell (sidebar/top bar) components at the bottom originate in
 * the licensing app's own dashboard — the marketing site has no dashboard
 * to draw that pattern from — but they read from the same tokens as
 * everything else in this file.
 *
 * COPIED VERBATIM from the licensing app's own klepon-theme.css into this
 * separate repo, deliberately — same confidentiality boundary that
 * justified the separate repo in the first place. If that file changes,
 * re-copy from there rather than hand-tuning here.
 */
:root {
  --color-bg: #f2f2f2;
  --color-surface: #e9e9ea;
  --color-text: #002e3a;
  --color-text-muted: color-mix(in srgb, var(--color-text) 55%, transparent);
  --color-divider: color-mix(in srgb, #002e3a 14%, transparent);

  --color-accent: #11a46e;
  --color-accent-100: #e6f8ef;
  --color-accent-200: #c2eeda;
  --color-accent-300: #8fdfb9;
  --color-accent-400: #55cb92;
  --color-accent-500: #2bb87a;
  --color-accent-600: #11a46e;
  --color-accent-700: #0c7d55;
  --color-accent-800: #095e40;
  --color-accent-900: #06432d;

  /* Not part of the brand palette — klepon-marketing's DESIGN.md is explicit that its secondary
     orange/amber are general-purpose accents, not semantic warning/error colors, so severity
     badges here use their own independent red/amber rather than borrowing those tokens. */
  --color-warning: #b45309;
  --color-warning-bg: #fef6e7;
  --color-danger: #dc2626;
  --color-danger-bg: #fdecec;

  --font-sans: "Urbanist", system-ui, sans-serif;
  --font-heading: "Urbanist", system-ui, sans-serif;

  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 7px;
  --radius-2xl: 16px;
  --radius-3xl: 22px;
  --radius-full: 9999px;

  /* Flat, hairline-bordered surfaces (data tables, the project-info sidebar panel) — a
     deliberately different composition from .blueprint's floating rounded/shadowed cards, adopted
     for data-management views. See the "Tables" and "Flat panel" sections below. */
  --radius-panel: 10px;

  --shadow-elev-sm: 0 1px 2px color-mix(in srgb, #002e3a 10%, transparent);
  --shadow-elev-md: 0 3px 10px color-mix(in srgb, #002e3a 12%, transparent);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: 16px;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -0.01em;
  margin: 0 0 0.5rem;
}

h1 { font-size: 1.875rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.0625rem; }

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

a:hover {
  color: var(--color-accent-900);
}

:focus {
  outline: none;
}

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

::selection {
  background: color-mix(in srgb, var(--color-accent) 30%, transparent);
}

/* Eyebrow — the one place uppercase survives in this system: a small kicker line preceding a
   heading, or naming a stat-card's category. */
.eyebrow {
  display: block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  margin-bottom: 0.35rem;
}

/* Card — white surface, generously rounded, resting shadow (not a hover-only state). Still
   named .blueprint so every page that already uses it picks up the new look with no markup
   changes; the old square-corner/hairline-border/corner-mark system it originally named is
   gone, same as on the marketing site. */
.blueprint {
  position: relative;
  border: none;
  border-radius: var(--radius-3xl);
  background: white;
  box-shadow: var(--shadow-elev-sm);
}

/* Corner registration marks — no equivalent in this system. Markup still emits the four .corner
   spans on every card (harmless, kept rather than touching every page) — this hides them. */
.corner {
  display: none;
}

/* Buttons — pill-shaped, always. .btn alone is the neutral/secondary action; .btn-primary is
   the one solid brand-green action; .btn-danger is reserved for the genuinely destructive one
   (Portal/DeleteAccount) — not part of the brand system, kept as this app's own addition. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  cursor: pointer;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.2;
  border-radius: var(--radius-full);
  border: 1px solid transparent;
  padding: 0.85rem 1.7rem;
  background: var(--color-surface);
  color: var(--color-text);
}

.btn:hover {
  background: color-mix(in srgb, var(--color-text) 7%, transparent);
  text-decoration: none;
}

/* Primary text is white, matching klepon-marketing's corrected convention (2026-08-31: an
   earlier version of that repo's DESIGN.md documented navy as the accessible default, but by
   then nearly every real button on the site already overrode it back to white to match the
   brand PDF's own swatch — white was the live convention, navy was the outlier. Ported here to
   match. The ~3.2:1 contrast at button-text size is a known, accepted tradeoff, not an
   oversight — see klepon-marketing/DESIGN.md's Buttons section before changing this back.) */
.btn-primary {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: white;
}

.btn-primary:hover {
  background: var(--color-accent-500);
  border-color: var(--color-accent-500);
  color: white;
}

.btn-primary:active {
  background: var(--color-accent-600);
  border-color: var(--color-accent-600);
}

.btn-sm {
  font-size: 0.875rem;
  padding: 0.6375rem 1.275rem;
}

.btn-danger {
  background: var(--color-danger);
  border-color: var(--color-danger);
  color: #fff;
}

.btn-danger:hover {
  background: color-mix(in srgb, var(--color-danger) 85%, black);
  border-color: color-mix(in srgb, var(--color-danger) 85%, black);
  color: #fff;
}

/* Inputs */
label {
  display: block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.8125rem;
  color: var(--color-text);
  margin-bottom: 0.35rem;
}

input[type="text"], input[type="email"], input[type="password"], input[type="date"], select {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  color: var(--color-text);
  background: white;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-lg);
  padding: 0.65rem 0.85rem;
}

input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus,
input[type="date"]:focus, select:focus {
  border-color: var(--color-accent);
}

input[type="checkbox"] {
  accent-color: var(--color-accent);
  margin-right: 0.35rem;
}

/* Notice bars — expiry warnings, pending-request status. Sit above the stat grid. */
.notice-bar {
  border-radius: var(--radius-3xl);
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
  font-size: 0.9375rem;
  background: var(--color-warning-bg);
}

.notice-bar-flat {
  border: none;
  background: var(--color-accent-100);
}

/* Stat cards (dashboard) */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.25rem;
  margin: 1.5rem 0 2rem;
}

.stat-card {
  padding: 1.5rem;
}

.stat-value {
  font-family: var(--font-heading);
  font-size: 2.25rem;
  font-weight: 800;
  color: var(--color-text);
  line-height: 1;
}

.stat-value-muted {
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--color-text-muted);
}

.stat-label {
  margin-top: 0.5rem;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* Tables — flat and dense, not a floating card: hairline outer border, small radius, no shadow,
   tight row padding. Deliberately NOT .blueprint's language (22px radius + shadow) — this is the
   composition for data-management views (Projects list, Members), borrowed from Autodesk Forma's
   Data Management UI (composition only — palette/type/button-shape are unchanged, see
   klepon-marketing's confirmed rebrand). border-collapse:separate is what lets
   border-radius/overflow clip the header and last row's corners. */
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: white;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-panel);
  overflow: hidden;
}

th, td {
  text-align: left;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--color-divider);
  font-size: 0.875rem;
}

th {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  background: var(--color-surface);
  white-space: nowrap;
}

tbody tr:last-child td {
  border-bottom: none;
}

tbody tr:hover td {
  background: var(--color-bg);
}

/* Flat panel — hairline-bordered, small radius, no shadow. Same surface language as tables,
   for non-tabular content that sits inside a data-management view (the sidebar's project-info
   card) rather than .blueprint's floating card look. */
.panel-flat {
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-panel);
  background: white;
}

/* Spool drill-down uses the existing flat table/panel surfaces and brand tokens. */
.spool-zone-picker { margin-top: 0; flex-wrap: wrap; }
.spool-zone-picker select { width: min(100%, 24rem); }
.spool-status-editor { margin: 0 0 0.75rem; flex-wrap: wrap; align-items: center; }
.spool-status-editor h3 { margin: 0; }
.spool-select { width: auto; }
.spool-select-all-wrap { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--color-text-muted); font-size: 0.9rem; font-weight: 700; }
.spool-select-all-wrap input { width: auto; }
.spool-status-editor select { width: auto; max-width: 100%; }
.spool-empty { padding: 2rem; text-align: center; color: var(--color-text-muted); }
.spool-caption { font-size: 0.8125rem; color: var(--color-text-muted); }
.spool-table-wrap { max-width: 100%; overflow-x: auto; }
.spool-register { table-layout: fixed; }
.spool-register > thead th:first-child { width: 40%; }
.spool-mark-row { cursor: pointer; scroll-margin-top: 1rem; }
.spool-mark-row a { display: block; color: var(--color-text); font-weight: 700; text-decoration: none; }
.spool-mark-row a span { margin-right: 0.5rem; }
.spool-mark-row.active > td { background: var(--color-accent-100); }
.spool-register .spool-expanded-row > td { padding: 0; background: white; }
.spool-expanded { padding: 1.25rem; }
.spool-expanded > section + section { margin-top: 1.5rem; padding-top: 1.25rem; border-top: 1px solid var(--color-divider); }
.spool-expanded h3 { font-size: 1rem; margin: 0 0 0.75rem; }
.spool-section-image { padding: 1rem; }
.spool-section-heading { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
.spool-outlet-orientation { display: block; width: 128px; height: auto; max-width: 100%; margin-left: auto; flex-shrink: 0; }
.spool-section-image img { display: block; width: 100%; height: auto; }
.spool-stations th, .spool-stations td { text-align: center; padding: 0.4rem 0.6rem; white-space: nowrap; }
.spool-stations th { text-transform: none; }
.spool-detail-fields { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 1rem; margin: 0; }
.spool-detail-fields dt { font-size: 0.8125rem; color: var(--color-text-muted); }
.spool-detail-fields dd { margin: 0.2rem 0 0; overflow-wrap: anywhere; }
.spool-qr-toggle { white-space: nowrap; }
.spool-qr-list { display: flex; flex-wrap: wrap; gap: 1rem; padding: 0.75rem 0; }
.spool-qr-card { display: flex; align-items: center; gap: 1rem; margin: 0; padding: 0.75rem; }
.spool-qr-card img { display: block; width: 132px; height: auto; background: white; }
.spool-qr-card figcaption { min-width: 0; }
.spool-qr-label { font-weight: 700; overflow-wrap: anywhere; }
.spool-qr-text { margin: 0.25rem 0 0; font-size: 0.75rem; line-height: 1.5; color: var(--color-text-muted); white-space: pre-wrap; overflow-wrap: anywhere; }
@media (max-width: 700px) {
  .spool-detail-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .spool-expanded { padding: 0.75rem; }
  .spool-register > thead th, .spool-mark-row > td { padding: 0.6rem 0.4rem; overflow-wrap: anywhere; }
  .spool-qr-card { flex-direction: column; align-items: flex-start; }
}

/* Toolbar — primary action (with its details/summary disclosure) + ghost utility actions + a
   view-toggle group, sitting directly above a data table. */
.toolbar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 1.5rem 0 1rem;
}

.btn-ghost {
  background: white;
  border-color: var(--color-divider);
}

.btn-ghost:hover {
  background: var(--color-bg);
}

.btn:disabled, .btn-ghost:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn:disabled:hover { background: var(--color-surface); }
.btn-ghost:disabled:hover { background: white; }
.btn-primary:disabled, .btn-primary:disabled:hover {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
}

.icon-btn:hover {
  background: var(--color-surface);
  color: var(--color-text);
}

.icon-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.icon-btn:disabled:hover {
  background: none;
  color: var(--color-text-muted);
}

.view-toggle {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.15rem;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-full);
  padding: 0.2rem;
  background: white;
}

.view-toggle .icon-btn.active {
  background: var(--color-accent-100);
  color: var(--color-accent-700);
}

/* Table row checkbox — plain and muted, distinct from the accent-colored checkboxes used in real
   forms elsewhere; disabled until bulk row actions exist. */
input.row-check {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  accent-color: var(--color-text-muted);
  margin: 0;
}

/* Underline tabs — thin 2px active underline, no pill background. A second nav convention
   alongside .app-nav-item's pill highlight, used for sub-views within one page (e.g. Members'
   All/Invited filter) rather than for the sidebar. */
.tabs {
  display: flex;
  gap: 1.5rem;
  border-bottom: 1px solid var(--color-divider);
  margin-bottom: 1.25rem;
}

.tab {
  display: inline-flex;
  align-items: center;
  padding: 0 0 0.7rem;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.9375rem;
  color: var(--color-text-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.tab:hover {
  color: var(--color-text);
}

.tab.active {
  color: var(--color-text);
  border-bottom-color: var(--color-accent);
}

/* Badges — small compact chips (16px rounding, per DESIGN.md's chip radius — distinct from the
   full-pill radius reserved for buttons), colored by severity/state. */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.7rem;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.75rem;
  border-radius: var(--radius-2xl);
  border: none;
}

.badge-active, .badge-ok { background: var(--color-accent-100); color: var(--color-accent-700); }
.badge-suspended { background: var(--color-warning-bg); color: var(--color-warning); }
.badge-revoked, .badge-locked { background: var(--color-danger-bg); color: var(--color-danger); }

/* .badge-role-* — this repo's own addition, not part of the ported source file. Roles are a
   category, not a severity — unlike .badge-suspended/.badge-revoked and the Prefab Status chips
   below, no role is more "wrong" than another, so this deliberately does NOT reuse
   warning/danger/accent: those are this file's severity scale (ok → warning → danger) and
   borrowing them here would make an Installer or Expeditor badge read as risky/problematic next
   to an actually-suspended Status badge in the same row. Each role instead gets its own
   same-weight categorical color (light wash background + solid-ish text, matching the existing
   badge recipe), all picked outside the warning/danger/accent hues. Member stays neutral gray —
   it is the unmarked/default role, which gray already conveys correctly.
   Note: .badge-role-* is a display-only label — it carries no authorization on its own. Actual
   role permissions live in Services/PrefabStatusPolicy.cs. */
.badge-role-admin { background: #eaeafc; color: #4338ca; }
.badge-role-member { background: var(--color-surface); color: var(--color-text-muted); }
.badge-role-fabricator { background: #f3e8fc; color: #7e22ce; }
.badge-role-installer { background: #e3f0fc; color: #0369a1; }
.badge-role-expeditor { background: #e1f5f2; color: #0f766e; }
.badge-role-modeller { background: #fce7f0; color: #be185d; }

/* .badge-prefab-* — Prefab Status chips (Models/PrefabStatuses.cs), this repo's own addition same
   as .badge-role-*: reuses existing tokens rather than inventing new colors. Not Set/Finish
   Prefab/Delivery on Site read as a progression (neutral → warning → light accent); Already
   Installed is the one state that gets the solid accent fill, so the completed state reads as
   visually "heavier" than the merely-in-transit one rather than reusing the same light green. */
.badge-prefab-not-set { background: var(--color-surface); color: var(--color-text-muted); }
.badge-prefab-finish { background: var(--color-warning-bg); color: var(--color-warning); }
.badge-prefab-delivery { background: var(--color-accent-100); color: var(--color-accent-700); }
.badge-prefab-installed { background: var(--color-accent); color: white; }

/* Utilization bar — seats in use vs total, for offering/stat cards. Fill color signals how close
   to capacity: brand green, amber warning, red once no seat is left at all. */
.util-bar {
  margin-top: 0.6rem;
  height: 8px;
  width: 100%;
  background: var(--color-surface);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.util-bar-fill {
  height: 100%;
  border-radius: var(--radius-full);
}

.util-bar-fill-ok { background: var(--color-accent); }
.util-bar-fill-warn { background: var(--color-warning); }
.util-bar-fill-full { background: var(--color-danger); }

/* Needs-attention panel (Admin dashboard) — a stack of compact, linkable rows grouped under a
   heading, each capped short with a "N more" link rather than repeating the full table. */
.attention-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.25rem;
  margin: 1.5rem 0 2rem;
}

.attention-panel {
  padding: 1.375rem;
}

.attention-panel h3 {
  font-size: 0.9375rem;
  margin: 0 0 0.7rem;
}

.attention-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.attention-list li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.875rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--color-divider);
}

.attention-list li:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.attention-more {
  display: block;
  margin-top: 0.7rem;
  font-size: 0.8125rem;
}

.error {
  color: var(--color-danger);
  font-size: 0.875rem;
}

/* ============================================================
   App shell — sidebar + top bar chrome. This app's own addition
   (the marketing site has no dashboard to draw the pattern from);
   reads from the same tokens as everything else above.
   ============================================================ */
.app-shell {
  display: flex;
  min-height: 100vh;
  background: var(--color-bg);
}

.app-sidebar {
  width: 260px;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 1.5rem 1rem;
  background: white;
  border-right: 1px solid var(--color-divider);
}

.app-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0 0.5rem;
  margin-bottom: 1.75rem;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.0625rem;
  color: var(--color-text);
}

.app-brand:hover {
  color: var(--color-text);
  text-decoration: none;
}

.app-brand img {
  width: 24px;
  height: 24px;
}

/* Distinguishes the internal Admin area from the customer-facing Portal at a glance — also used
   standalone on the Admin login/access-denied cards (outside the sidebar). */
.wordmark-tag {
  font-family: var(--font-heading);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  background: var(--color-accent-100);
  padding: 0.15rem 0.55rem;
  border-radius: var(--radius-2xl);
}

.app-nav {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.app-nav-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 0.7rem;
  border-radius: var(--radius-2xl);
  font-family: var(--font-sans);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.app-nav-item:hover {
  background: var(--color-bg);
  color: var(--color-text);
  text-decoration: none;
}

.app-nav-item.active {
  background: var(--color-accent-100);
  color: var(--color-accent-700);
}

.app-nav-item svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.app-nav-badge {
  margin-left: auto;
  font-family: var(--font-sans);
  font-size: 0.625rem;
  font-weight: 700;
  color: #fff;
  background: var(--color-accent);
  padding: 0.1rem 0.45rem;
  border-radius: var(--radius-full);
}

.app-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.app-topbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1rem;
  padding: 1rem 2rem;
  background: white;
  box-shadow: var(--shadow-elev-sm);
  position: sticky;
  top: 0;
  z-index: 20;
}

/* Breadcrumb — a project page's "where am I" trail in the top bar, replacing a sidebar back-link.
   margin-right:auto pushes it to the left edge while identity/sign-out stay right (.app-topbar is
   justify-content:flex-end). */
.breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-right: auto;
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 600;
}

.breadcrumb a {
  color: var(--color-text-muted);
}

.breadcrumb a:hover {
  color: var(--color-text);
}

.breadcrumb-sep {
  color: var(--color-text-muted);
  opacity: 0.5;
}

.breadcrumb > span:last-child {
  color: var(--color-text);
}

.app-identity {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.app-identity-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-full);
  background: var(--color-accent);
  color: var(--color-text);
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 0.8125rem;
  flex-shrink: 0;
}

.app-identity-value {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text);
}

/* Portal's identity menu — a native <details>/<summary> disclosure (identity-menu.js only
   handles closing it on outside click/Escape, since <details> doesn't do that natively). Needs
   its own positioning: .app-identity-dropdown is absolutely placed off the wrapping <details>,
   not inline in the topbar's flex flow, or it just falls into the page below the topbar as
   plain text — which is what it did before this rule existed. */
.app-identity-menu {
  position: relative;
}

.app-identity-menu summary {
  list-style: none;
  cursor: pointer;
}

.app-identity-menu summary::-webkit-details-marker {
  display: none;
}

.app-identity-dropdown {
  position: absolute;
  top: calc(100% + 0.75rem);
  right: 0;
  z-index: 20;
  min-width: 240px;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1rem;
  background: white;
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-elev-md);
}

.app-identity-dropdown-header {
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--color-divider);
}

.app-identity-dropdown-email {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--color-text);
  word-break: break-all;
}

.app-identity-dropdown-role {
  margin-top: 0.15rem;
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.app-identity-dropdown a {
  font-size: 0.875rem;
  font-weight: 600;
}

.app-identity-dropdown .app-logout {
  width: 100%;
}

/* Notification bell — same <details>/<summary> + .app-identity-dropdown pattern as the identity
   menu right next to it, just its own trigger icon and dropdown content. */
.app-notification-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-full);
  color: var(--color-text);
}

.app-notification-bell:hover,
.app-identity-menu[open] > summary.app-notification-bell {
  background: color-mix(in srgb, var(--color-text) 6%, transparent);
}

.app-notification-dot {
  position: absolute;
  top: 6px;
  right: 7px;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--color-danger);
  border: 1.5px solid white;
}

.app-notification-dropdown {
  width: 320px;
  max-height: 380px;
  overflow-y: auto;
  padding: 0;
  gap: 0;
}

.app-notification-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--color-divider);
}

.app-notification-header-title {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.app-notification-mark-read button {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-accent-700);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font-family: var(--font-sans);
}

.app-notification-empty {
  padding: 1.25rem 0.9rem;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

.app-notification-item {
  display: block;
  padding: 0.65rem 0.9rem;
  text-decoration: none;
  border-bottom: 1px solid var(--color-divider);
}

.app-notification-item:last-child {
  border-bottom: none;
}

.app-notification-item:hover {
  background: color-mix(in srgb, var(--color-text) 4%, transparent);
}

.app-notification-item.unread {
  background: var(--color-accent-100);
}

.app-notification-message {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 0.15rem;
}

.app-notification-time {
  display: block;
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.app-logout {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.8125rem;
  border-radius: var(--radius-full);
  border: 1px solid color-mix(in srgb, var(--color-text) 15%, transparent);
  background: transparent;
  color: var(--color-text);
  padding: 0.45rem 0.9rem;
  cursor: pointer;
}

.app-logout:hover {
  background: color-mix(in srgb, var(--color-text) 5%, transparent);
}

.app-main {
  flex: 1;
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  padding: 2.5rem 2rem;
}

/* Two-tier sidebar — a secondary/utility nav group pinned near the bottom via margin-top:auto,
   separated from the primary group by a hairline divider. */
.app-nav-secondary {
  margin-top: auto;
  padding-top: 1rem;
}

.app-nav-secondary-divider {
  height: 1px;
  background: var(--color-divider);
  margin-bottom: 0.6rem;
}

.app-nav-item.disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* The sidebar's project-info panel doubles as a link to Settings — a subtle hover state signals
   that without touching .panel-flat itself (also used for non-clickable panels elsewhere). */
.panel-flat-link:hover {
  border-color: color-mix(in srgb, var(--color-text) 25%, transparent);
}

.audit-log-entry { display:flex; gap:0.875rem; align-items:center; padding:1rem 1.15rem; border-bottom:1px solid var(--color-divider); }
.audit-log-entry:last-child { border-bottom:none; }
.audit-log-icon { width:2rem; height:2rem; border-radius:50%; display:grid; place-items:center; flex:0 0 auto; background:var(--color-accent-100); color:var(--color-accent-700); font-family:var(--font-heading); font-weight:800; font-size:0.8rem; }
.audit-log-meta, .audit-log-time { color:var(--color-text-muted); font-size:0.78rem; margin-top:0.18rem; }
.audit-log-time { text-align:right; white-space:nowrap; }

.spool-prefab-mark {
  margin-top: 0.3rem;
  color: var(--color-text);
  font-family: var(--font-heading);
  font-size: 1.75rem;
  font-weight: 900;
  letter-spacing: -0.025em;
  line-height: 1.1;
}

/* Dashboard fabrication-data tabs. Material Summary keeps the source desktop dashboard's four
   tables, but uses the Hub's underline-tab convention and responsive table wrapper. */
.material-tabs {
  display: flex;
  gap: 1.25rem;
  overflow-x: auto;
  border-bottom: 1px solid var(--color-divider);
  margin: 0.5rem 0 1rem;
}

.material-tab {
  flex: 0 0 auto;
  cursor: pointer;
  padding: 0 0 0.65rem;
  margin-bottom: -1px;
  border: none;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--color-text-muted);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 700;
}

.material-tab:hover,
.material-tab.active { color: var(--color-text); }
.material-tab.active { border-bottom-color: var(--color-accent); }
.material-panel[hidden] { display: none; }

/* Docs is a read-only view of generated files embedded in each zone folder of the imported
   snapshot. Native details/summary keeps even a very large QR folder cheap to scan. */
.docs-explorer { display: grid; grid-template-columns: 230px minmax(0, 1fr); min-height: 34rem; overflow: hidden; }
.docs-navigation { padding: 0.75rem 0; border-right: 1px solid var(--color-divider); background: var(--color-surface); }
.docs-nav-item {
  display: flex;
  width: 100%;
  align-items: center;
  padding-left: calc(0.5rem + var(--docs-depth) * 0.8rem);
  background: transparent;
  color: var(--color-text);
  font-size: 0.8125rem;
}
.docs-nav-item[hidden] { display: none; }
.docs-nav-item:hover { background: var(--color-bg); }
.docs-nav-item.active { background: var(--color-accent-100); color: var(--color-accent-700); font-weight: 700; }
.docs-tree-toggle,
.docs-tree-spacer { width: 1.45rem; height: 2rem; flex: 0 0 1.45rem; }
.docs-tree-toggle { display: grid; place-items: center; padding: 0; border: 0; background: transparent; color: var(--color-text-muted); font: inherit; cursor: pointer; }
.docs-tree-toggle:hover { color: var(--color-text); }
.docs-nav-open { min-width: 0; flex: 1; padding: 0.42rem 0.75rem 0.42rem 0; overflow: hidden; border: 0; background: transparent; color: inherit; font: inherit; text-align: left; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.docs-browser { min-width: 0; background: white; }
.docs-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 4rem; padding: 0.75rem 1rem; border-bottom: 1px solid var(--color-divider); }
.docs-navigation-tools { display: flex; min-width: 0; flex: 1; align-items: center; gap: 0.75rem; }
.docs-history { display: inline-flex; flex: 0 0 auto; align-items: center; }
.docs-history-button {
  display: inline-grid;
  width: 2rem;
  height: 2rem;
  place-items: center;
  border: 1px solid transparent;
  border-radius: 0.35rem;
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: 1.15rem;
  cursor: pointer;
}
.docs-history-button:hover:not(:disabled) { border-color: var(--color-divider); background: var(--color-bg); }
.docs-history-button:disabled { color: var(--color-text-muted); cursor: default; opacity: 0.4; }
.docs-location { display: flex; min-width: 0; align-items: center; overflow-x: auto; color: var(--color-text-muted); font-size: 0.8125rem; white-space: nowrap; }
.docs-path-segment { flex: 0 0 auto; padding: 0.35rem 0.45rem; border: 0; border-radius: 0.3rem; background: transparent; color: inherit; font: inherit; cursor: pointer; }
.docs-path-segment:hover { background: var(--color-bg); color: var(--color-text); }
.docs-path-segment:last-child { color: var(--color-text); font-weight: 600; }
.docs-path-separator { flex: 0 0 auto; color: var(--color-text-muted); font-size: 1rem; }
.docs-table { border: 0; border-radius: 0; }
.docs-table th, .docs-table td { padding: 0.58rem 0.75rem; }
.docs-table th:first-child, .docs-table td:first-child { width: 42px; }
.docs-table th:nth-child(2) { width: 42%; }
.docs-table td { color: var(--color-text-muted); }
.docs-table td:nth-child(2) { color: var(--color-text); }
.docs-check-cell { text-align: center; }
.docs-check-cell input { width: 16px; height: 16px; margin: 0; }
.docs-name { display: inline-flex; align-items: center; gap: 0.55rem; padding: 0; border: 0; background: transparent; color: var(--color-text); font: inherit; font-weight: 600; cursor: pointer; }
.docs-name:hover { color: var(--color-accent-700); }
.docs-name span { width: 1.1rem; text-align: center; }
.docs-row[hidden] { display: none; }

@media (max-width: 700px) {
  .docs-explorer { grid-template-columns: 1fr; }
  .docs-navigation { max-height: 15rem; overflow-y: auto; border-right: 0; border-bottom: 1px solid var(--color-divider); }
  .docs-toolbar { align-items: stretch; flex-direction: column; }
  .docs-download { align-self: flex-end; }
}

/* Login / signup / access-denied cards */
.auth-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg);
}

.auth-card {
  width: 340px;
  padding: 2.25rem 2rem;
}

.auth-card form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-top: 1.25rem;
}

.auth-card button[type="submit"] {
  margin-top: 0.5rem;
}
