/* ==============================================================================================
   ENTROPIA WEB ADMIN — ENTROPIA.CSS
   Single authored stylesheet. Generated from the consolidation of fonts.css + site.css +
   grid.css + components.css (2026-09-04). Order inside this file IS the cascade — do not
   reorder layers without re-checking the FluentDataGrid overrides in L3 (they rely on
   following L1/L2).

   TABLE OF CONTENTS
     L0  Fonts                @font-face, variable fonts, font-display: swap
     L1  Shell & base         reset · elements · layout shell · legacy tables · utilities
     L2  Swiss page grid      .mb-grid container · overlay · bands · display type
    L3  Components           Fluent token bridge · controls · data-grid integration · cards
       (2026-09-04: `.layout` → `.app-layout` — `layout` is a Fluent-bundle class; the
        bare name collided with FluentLayout's scoped rules. Family renamed together:
        `.app-layout`, `.app-layout-rail-collapsed`, `.app-layout-modern`.)
   L4  Cross-browser compat  text inflation · tap highlight · coarse-pointer inputs ·
                            scrollbar parity · reduced motion · scroll containment
      (2026-09-04: page-local families moved to scoped css beside their pages:
       LabelDesignerStudio.razor.css (.label-*) and Operate.razor.css (.operate-*).
       Mixed-selector groups and !important override blocks stayed here — scoped
       files cannot win global cascades and must not carry !important.)
   RULES
     • Colors/spacing/type come from tokens.generated.css — never hardcode hex in new rules.
     • `.mb-grid` is the page grid. `.grid` belongs to FluentDataGrid (its own bundle class).
     • Data-grid row styling targets CELLS, not <tr> — Fluent rows are display: contents.
   ============================================================================================== */


/* ═════════════════════════════════════════════════════════════════════════════
   L0 — FONTS — self-hosted variable fonts (@font-face). Referenced by every font stack below.
   ═════════════════════════════════════════════════════════════════════════════ */

/*
 * Self-hosted variable fonts.
 *
 * Why this file exists:
 *   Inter and JetBrains Mono are referenced by `--display-font`, `--body-font`
 *   and `--mono-font` (grid.css) but the actual font files were never shipped,
 *   so on every machine the user agent fell back to whatever the platform's
 *   "Segoe UI" / monospace happened to be. That fallback drifted per OS and
 *   per locale, which is why grid columns snapped to a different width on
 *   every machine and the alignment audit (grid.js) only ever passed locally.
 *
 * Two variable fonts, weight axis only:
 *   • Inter Variable — 100-900, the grotesque used for display + body.
 *   • JetBrains Mono Variable — 100-800, the mono used for kickers / folios /
 *     numeric.
 *
 * font-display: swap lets the platform's local fallback paint immediately so
 * the page is never empty while the woff2 fetches; once the file lands the
 * text reflows in Inter, but the layout does not shift because Inter was
 * already accounted for in `tokens.generated.css` `--entropia-font-sans`.
 *
 * Load order matters — this file must come BEFORE tokens.generated.css so the
 * face is registered by the time any consumer resolves the stack.
 */

/* Inter — grotesque, weight axis 100..900 ---------------------------------- */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../fonts/inter-var.woff2') format('woff2');
}

/* JetBrains Mono — mono, weight axis 100..800 ------------------------------ */
@font-face {
    font-family: "JetBrains Mono";
    font-style: normal;
    font-weight: 100 800;
    font-display: swap;
    src: url('../fonts/jetbrains-mono-var.woff2') format('woff2');
}

/* ═════════════════════════════════════════════════════════════════════════════
   L1 — SHELL & BASE — reset, elements, app shell (rail/topbar/content), legacy .data-table tables, login, toasts/dialogs, utilities.
   ═════════════════════════════════════════════════════════════════════════════ */

/* ----------------------------------------------------------------------------
 * Legacy alias map — keeps the ~2,000 lines of pre-2026 CSS that reference
 * the old short variable names theme-aware by forwarding them to the new
 * generated tokens. A redesign may add new names; the legacy aliases must
 * stay so removing them silently turns every `var(--entropia-ink)` call site
 * into an empty string.
 * -------------------------------------------------------------------------- */
:root {
  --entropia-ink: var(--entropia-color-ink);
  --entropia-surface-raised: var(--entropia-color-surface-raised);
  --entropia-primary: var(--entropia-color-brand-primary);
}
/* ============================================================================
 * Entropia Admin — Pro/Industrial design system
 * ============================================================================
 *  · Light default + data-theme="dark" variant via root tokens
 *  · Layout shell: rail (256px) + topbar (56px) + canvas
 *  · Surfaces: pure white cards on a cool grey canvas; one-step shadows
 *  · Status semantics: success / warning / danger / info with paired soft tints
 *  · No fluff: zero animations > 160ms, no rounded >= 12px, no decorative gradients
 * ============================================================================ */

:root {
  font-size: calc(14px * var(--entropia-font-scale));
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink);
  font-family: Inter, "Segoe UI", system-ui, sans-serif;
  font-size: 1rem;
  line-height: var(--entropia-type-body-line-height);
  font-weight: var(--entropia-type-body-weight);
  min-height: 100vh;
  min-height: 100dvh;
}

*, *::before, *::after { box-sizing: border-box; }

/* Focus ring — single, blue, always visible */
:focus-visible {
  outline: 2px solid var(--entropia-color-brand-primary);
  outline-offset: 2px;
  border-radius: var(--entropia-radius-md);
}

a { color: var(--entropia-color-brand-primary); text-decoration: none; }
a:hover { color: var(--entropia-color-brand-primary-strong); text-decoration: underline; text-underline-offset: 2px; }

/* ───────── Skip link ───────── */
.skip-link {
  position: absolute; left: -9999px; top: 0;
  background: var(--entropia-color-brand-primary);
  color: var(--entropia-color-on-brand); padding: 8px 14px; border-radius: var(--entropia-radius-md);
  font-weight: 500; z-index: var(--entropia-z-modal);
}
.skip-link:focus { left: 8px; top: 8px; }

/* ───────── Typography ───────── */
h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: 600; color: var(--entropia-color-ink); letter-spacing: var(--entropia-type-display-tracking); }
h1 { font-size: var(--entropia-type-display-size); line-height: var(--entropia-type-display-line-height); }
h2 { font-size: var(--entropia-type-title-size); line-height: var(--entropia-type-title-line-height); }
h3 { font-size: var(--entropia-type-subtitle-size); line-height: var(--entropia-type-subtitle-line-height); }
p { margin: 0; }
.mono, code, kbd { font-family: var(--entropia-type-mono); font-size: 0.92em; }
.muted { color: var(--entropia-color-ink-muted); }
.soft { color: var(--entropia-color-ink-soft); }
.eyebrow {
  text-transform: uppercase;
  font-size: var(--entropia-type-caption-size);
  letter-spacing: var(--entropia-type-caption-tracking);
  font-weight: 600;
  color: var(--entropia-color-ink-soft);
}

/* ───────── Layout shell ───────── */
.app-layout,
.app-layout-rail-collapsed {
  --entropia-shell-header-height: calc(var(--entropia-dimen-topbar-height) + 52px);
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: var(--entropia-shell-header-height) auto 1fr;
  grid-template-areas:
    "topbar"
    "rail"
    "main";
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--entropia-color-surface);
}

@media (max-width: 900px) {
  .app-layout, .app-layout-rail-collapsed {
    grid-template-rows: var(--entropia-shell-header-height) 1fr;
    grid-template-areas:
      "topbar"
      "main";
  }
  .sidebar { display: none; }
  .sidebar.is-mobile-open {
    display: flex;
    position: fixed;
    inset: var(--entropia-shell-header-height) 0 0 0;
    z-index: var(--entropia-z-rail);
    flex-direction: column;
    background: var(--entropia-color-surface-raised);
    border-top: 1px solid rgba(15, 23, 42, 0.08);
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--entropia-color-line) transparent;
    padding: var(--entropia-space-lg);
  }
  .sidebar.is-mobile-open .sidebar-section-body,
  .sidebar.is-mobile-open .sidebar-footer {
    flex-direction: column;
    align-items: stretch;
  }
  .sidebar.is-mobile-open .sidebar-section-copy {
    flex: 1 1 auto;
  }
  .sidebar.is-mobile-open .nav-list {
    flex-direction: column;
  }
  .topbar-search { display: none; }
}

/* ───────── Topbar ───────── */
.topbar {
  grid-area: topbar;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  background: var(--entropia-color-surface-raised);
  border-bottom: 1px solid rgba(15, 23, 42, 0.08);
  position: sticky;
  top: 0;
  z-index: calc(var(--entropia-z-rail) + 1);
  height: var(--entropia-shell-header-height);
}
.topbar-main {
  display: flex;
  align-items: center;
  gap: var(--entropia-space-md);
  min-height: var(--entropia-dimen-topbar-height);
  padding: 0 var(--entropia-space-xl);
  background: var(--entropia-color-surface-raised);
  border-bottom: 1px solid rgba(15, 23, 42, 0.08);
}
.topbar-breadcrumb { color: var(--entropia-color-ink-muted); font-size: var(--entropia-type-body-size); }
.topbar-breadcrumb strong { color: var(--entropia-color-ink); font-weight: 600; }
.topbar-spacer { flex: 1; }
.topbar-search { width: 360px; }
.topbar-section-nav {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 52px;
  padding: 8px var(--entropia-space-xl);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  background: var(--entropia-color-surface-raised);
}
.topbar-section-tab {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 14px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink-muted);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--entropia-duration-fast) var(--entropia-ease),
              border-color var(--entropia-duration-fast) var(--entropia-ease),
              color var(--entropia-duration-fast) var(--entropia-ease);
}
.topbar-section-tab:hover {
  background: rgba(37, 99, 235, 0.08);
  border-color: rgba(37, 99, 235, 0.16);
  color: var(--entropia-color-ink);
}
.topbar-section-tab.is-active {
  background: var(--entropia-color-brand-primary);
  border-color: var(--entropia-color-brand-primary);
  color: var(--entropia-color-surface-raised);
}

/* ───────── Workspace navigation band ───────── */
.sidebar {
  grid-area: rail;
  background: var(--entropia-color-surface-raised);
  color: var(--entropia-color-ink);
  display: flex;
  flex-direction: column;
  gap: var(--entropia-space-md);
  border-bottom: 1px solid rgba(15, 23, 42, 0.08);
  padding: 12px var(--entropia-space-xl) 16px;
  position: sticky;
  top: var(--entropia-dimen-topbar-height);
  z-index: var(--entropia-z-rail);
}

.sidebar-rail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--entropia-space-lg);
}

.sidebar-brand {
  display: flex; align-items: center; gap: var(--entropia-space-md);
  padding: 0;
  border-bottom: 0;
  color: var(--entropia-color-ink);
  text-decoration: none;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.sidebar-brand:hover { color: var(--entropia-color-ink); text-decoration: none; }
.sidebar-brand-mark {
  width: 28px; height: 28px; border-radius: var(--entropia-radius-md);
  background: linear-gradient(135deg, var(--entropia-color-brand-primary), var(--entropia-color-brand-primary-strong));
  display: grid; place-items: center; color: var(--entropia-color-on-brand); font-size: 14px;
  box-shadow: 0 6px 18px rgba(37, 99, 235, 0.24);
}
.sidebar-brand-text strong { display: block; }
.sidebar-brand-text span { font-size: var(--entropia-type-caption-size); color: var(--entropia-color-ink-soft); display: block; font-weight: 400; }

.sidebar-section {
  padding: 0;
  min-width: 0;
}

.sidebar-section-shell {
  display: flex;
  flex-direction: column;
  gap: var(--entropia-space-md);
}

.sidebar-section-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.sidebar-section-tab {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink-muted);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  transition: background var(--entropia-duration-fast) var(--entropia-ease),
              border-color var(--entropia-duration-fast) var(--entropia-ease),
              color var(--entropia-duration-fast) var(--entropia-ease);
}

.sidebar-section-tab:hover {
  background: rgba(37, 99, 235, 0.08);
  border-color: rgba(37, 99, 235, 0.16);
  color: var(--entropia-color-ink);
}

.sidebar-section-tab.is-active {
  background: var(--entropia-color-brand-primary);
  border-color: var(--entropia-color-brand-primary);
  color: var(--entropia-color-surface-raised);
}

.sidebar-section-body {
  display: flex;
  align-items: flex-start;
  gap: var(--entropia-space-lg);
}

.sidebar-section-copy {
  flex: 0 0 220px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.sidebar-section-title {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--entropia-color-ink-soft);
  padding: 0;
  font-weight: 700;
  white-space: nowrap;
}

.sidebar-section-description {
  color: var(--entropia-color-ink-muted);
  font-size: 13px;
  line-height: 1.5;
  max-width: 34ch;
}

.nav-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  gap: 8px;
}
.nav-item a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  border-radius: 999px;
  color: var(--entropia-color-ink-muted);
  font-size: 13px; font-weight: 500;
  text-decoration: none;
  transition: background var(--entropia-duration-fast) var(--entropia-ease),
              color var(--entropia-duration-fast) var(--entropia-ease),
              border-color var(--entropia-duration-fast) var(--entropia-ease);
  border: 1px solid transparent;
  white-space: nowrap;
}
.nav-item a:hover {
  background: rgba(37, 99, 235, 0.08);
  border-color: rgba(37, 99, 235, 0.12);
  color: var(--entropia-color-ink);
  text-decoration: none;
}
.nav-item a.active {
  background: var(--entropia-color-brand-primary);
  color: var(--entropia-color-surface-raised);
}
.nav-item a.active .nav-icon { color: var(--entropia-color-surface-raised); }
.nav-icon {
  width: 18px; height: 18px; flex-shrink: 0; color: var(--entropia-color-ink-soft);
}
.nav-badge {
  margin-left: auto;
  font-size: 10px; font-weight: 700;
  background: rgba(37, 99, 235, 0.1);
  color: var(--entropia-color-brand-primary-strong);
  padding: 2px 6px; border-radius: 999px; min-width: 18px; text-align: center;
}
.nav-item a.active .nav-badge {
  background: rgba(255, 255, 255, 0.18);
  color: var(--entropia-color-on-brand);
}

.sidebar-footer {
  border-top: 1px solid rgba(15, 23, 42, 0.08);
  padding-top: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--entropia-space-md);
}
.sidebar-footer-controls {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 180px;
}
.sidebar-user {
  display: flex; align-items: center; gap: var(--entropia-space-md);
  padding: 0;
  border-radius: var(--entropia-radius-md);
}
.sidebar-user-avatar {
  width: 32px; height: 32px; border-radius: 999px;
  background: rgba(37, 99, 235, 0.12);
  color: var(--entropia-color-brand-primary-strong); display: grid; place-items: center;
  font-size: 12px; font-weight: 700;
}
.sidebar-user-info { display: flex; flex-direction: column; line-height: 1.2; }
.sidebar-user-info strong { color: var(--entropia-color-ink); font-size: 13px; font-weight: 600; }
.sidebar-user-info span { color: var(--entropia-color-ink-soft); font-size: 11px; }


/* ───────── Main content ───────── */
.content {
  grid-area: main;
  padding: var(--entropia-space-xl);
  min-width: 0;
  max-width: 1440px;
  width: 100%;
  margin: 0 auto;
}

.page-guide {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(220px, 1fr) minmax(220px, 1fr);
  gap: var(--entropia-space-md);
  margin: 0 0 var(--entropia-space-lg);
}

.page-guide-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
  border: 1px solid var(--entropia-color-line);
  background: var(--entropia-color-surface);
  min-width: 0;
}

.page-guide-kicker {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--entropia-color-ink-soft);
}

.page-guide-panel p {
  margin: 0;
  color: var(--entropia-color-ink-muted);
  line-height: 1.5;
  max-width: 64ch;
}

.page-guide-shortcuts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.page-guide-shortcut {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 12px;
  border: 1px solid var(--entropia-color-line);
  background: var(--entropia-color-surface-sunken);
  color: var(--entropia-color-ink-strong);
  text-decoration: none;
  font-size: 12px;
  font-weight: 600;
}

.page-guide-shortcut:hover {
  border-color: var(--entropia-color-brand-primary);
  color: var(--entropia-color-ink-strong);
  text-decoration: none;
}

@media (max-width: 1100px) {
  .page-guide {
    grid-template-columns: 1fr;
  }
}

/* ───────── Disclosures ─────────
 * Compact <details> blocks the shell uses to hide optional guidance by
 * default. Two flavours: page-guide-popover wraps the existing three
 * .page-guide-panel cards; lead-disclosure is a single muted kicker
 * inside GridPage. Both hide the default disclosure marker (cross-browser)
 * and tone the summary down to a clickable chip / link. The body keeps
 * the original .page-guide-* and inline styles untouched. */
.page-guide-popover > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 var(--entropia-space-sm);
  padding: 4px 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--entropia-color-ink-soft);
  background: var(--entropia-color-surface-sunken);
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-md);
  -webkit-user-select: none;
  user-select: none;
}
.page-guide-popover > summary::-webkit-details-marker { display: none; }
.page-guide-popover > summary::marker { content: ""; }
.page-guide-popover > summary:hover {
  color: var(--entropia-color-ink-strong);
  border-color: var(--entropia-color-line-strong);
}
.page-guide-popover > summary:focus-visible {
  outline: 2px solid var(--entropia-color-brand-primary);
  outline-offset: 2px;
}
.page-guide-popover[open] > summary { margin-bottom: var(--entropia-space-md); }

.lead-disclosure > summary {
  list-style: none;
  cursor: pointer;
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--entropia-color-ink-soft);
  margin: var(--bl) 0 0;
  -webkit-user-select: none;
  user-select: none;
}
.lead-disclosure > summary::-webkit-details-marker { display: none; }
.lead-disclosure > summary::marker { content: ""; }
.lead-disclosure > summary:hover { color: var(--entropia-color-ink-strong); }
.lead-disclosure > summary:focus-visible {
  outline: 2px solid var(--entropia-color-brand-primary);
  outline-offset: 2px;
}
.lead-disclosure-body {
  max-width: 72ch;
  padding-top: 8px;
}
.page-header {
  display: flex; align-items: center; gap: var(--entropia-space-md);
  margin-bottom: var(--entropia-space-lg);
  padding-bottom: var(--entropia-space-md);
  border-bottom: 1px solid var(--entropia-color-line);
}
.page-header-text { flex: 1; }
.page-header h1 { font-size: var(--entropia-type-display-size); line-height: var(--entropia-type-display-line-height); margin: 0; }
.page-header p { color: var(--entropia-color-ink-muted); margin-top: 4px; font-size: var(--entropia-type-body-size); }
.page-actions { display: flex; gap: var(--entropia-space-sm); }

/* ───────── Buttons ───────── */
.btn, button.btn, a.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--entropia-space-sm);
  height: var(--entropia-dimen-button-height);
  padding: 0 var(--entropia-space-lg);
  border-radius: var(--entropia-radius-md);
  border: 1px solid var(--entropia-color-line);
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink);
  font: inherit; font-weight: 500; font-size: 13px;
  cursor: pointer;
  transition: background var(--entropia-duration-fast) var(--entropia-ease),
              border-color var(--entropia-duration-fast) var(--entropia-ease);
  text-decoration: none;
}
.btn:hover { background: var(--entropia-color-surface); border-color: var(--entropia-color-line-strong); text-decoration: none; }
/* Routed through the token so dark mode follows. The literal that was here did
   not: the dark blocks move brand-primary, leaving the button stranded at the
   light value on a dark surface. */
.btn-primary, a.btn-primary {
  /* brand-action, not brand-primary: the resting fill has to carry label text, and
     #E8593C under white measures ~3.5:1. The old rule also had it backwards — the
     hover state used the darker shade, so the button was more legible while the
     pointer sat on it than at rest. Hover now shifts brightness instead, which keeps
     the contrast direction correct in both themes. */
  background: var(--entropia-color-brand-action);
  border-color: var(--entropia-color-brand-action);
  color: var(--entropia-color-on-brand);
}
.btn-primary:hover {
  background: var(--entropia-color-brand-action);
  border-color: var(--entropia-color-brand-action);
  color: var(--entropia-color-on-brand);
  filter: brightness(0.92);
}
.btn-ghost { background: transparent; border-color: transparent; }
.btn-ghost:hover { background: var(--entropia-color-surface-sunken); border-color: var(--entropia-color-line); }
.btn-danger { background: var(--entropia-color-danger); border-color: var(--entropia-color-danger); color: var(--entropia-color-on-brand); }
.btn-danger:hover { filter: brightness(0.94); }
.btn-sm { height: 30px; padding: 0 var(--entropia-space-md); font-size: 12px; }
.btn:disabled, .btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* ───────── Inputs ───────── */
.input, input.input, textarea.input, select.input {
  width: 100%;
  height: var(--entropia-dimen-button-height);
  padding: 0 var(--entropia-space-md);
  border-radius: var(--entropia-radius-md);
  border: 1px solid var(--entropia-color-line);
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink);
  font: inherit; font-size: 13px;
  transition: border-color var(--entropia-duration-fast) var(--entropia-ease),
              box-shadow var(--entropia-duration-fast) var(--entropia-ease);
}
.input:focus, input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--entropia-color-brand-primary);
  box-shadow: var(--entropia-shadow-focus);
}
/* Compact <select> variants used by the topbar (language picker, scope
   selects) where the default input height would crowd the bar. */
.input.input-sm, select.input.input-sm, input.input.input-sm {
  height: 32px;
  font-size: 12px;
  padding: 0 var(--entropia-space-sm);
}
.input.input-scope, select.input.input-scope {
  width: auto;
  min-width: 160px;
  height: 36px;
}
/* Breadcrumb current-page strong: same margin-left that was inline before
   so callers don't need a literal style attr. */
.breadcrumb-page { margin-left: 6px; }
/* First sidebar-section-title in a footer block sits flush against the
   previous element — the inline `padding-top:0` is hoisted here. */
.sidebar-section-title-flush { padding-top: 0; }
/* Desktop navigation collapse remains available; the mobile breakpoint
   hides this control in favor of the mobile navigation toggle. */
.rail-collapse-toggle { display: inline-flex; }
label.field, .field {
  display: flex; flex-direction: column; gap: var(--entropia-space-xs);
  font-size: var(--entropia-type-caption-size);
  color: var(--entropia-color-ink-muted);
  font-weight: 500;
}
label.field > .input, .field > .input { color: var(--entropia-color-ink); font-size: 13px; }

.checkbox { display: inline-flex; align-items: center; gap: var(--entropia-space-sm); cursor: pointer; }

/* ───────── Status chips ───────── */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 22px; padding: 0 8px;
  border-radius: 4px;
  font-size: 11px; font-weight: 600;
  background: var(--entropia-color-line); color: var(--entropia-color-ink);
  border: 1px solid transparent;
}
.chip-success { background: var(--entropia-color-success-soft); color: var(--entropia-color-success); }
.chip-warning { background: var(--entropia-color-warning-soft); color: var(--entropia-status-warning-fg); }
.chip-danger { background: var(--entropia-color-danger-soft); color: var(--entropia-color-danger); }
.chip-info { background: var(--entropia-color-info-soft); color: var(--entropia-color-info); }
.chip-brand { background: var(--entropia-color-brand-primary-soft); color: var(--entropia-color-brand-primary-strong); }
.chip-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* ───────── Cards / Panels ───────── */
.card, .panel-card {
  background: var(--entropia-color-surface);
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-lg);
  padding: var(--entropia-space-lg);
  box-shadow: var(--entropia-shadow-sm);
}
.card-tight { padding: var(--entropia-space-md); }
.card-header { display: flex; align-items: center; gap: var(--entropia-space-md); margin-bottom: var(--entropia-space-md); }
.card-header h3 { font-size: 13px; font-weight: 600; color: var(--entropia-color-ink-strong); margin: 0; }
.card-header p.eyebrow { margin-bottom: 2px; }
.card-body { color: var(--entropia-color-ink); }
.card-action { margin-left: auto; }

/* ───────── KPI tiles (dashboard) ───────── */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--entropia-space-md);
}
.kpi-tile {
  background: var(--entropia-color-surface);
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-lg);
  padding: var(--entropia-space-lg);
  box-shadow: var(--entropia-shadow-sm);
  display: flex; flex-direction: column; gap: 4px;
  position: relative;
  overflow: hidden;
}
.kpi-tile-label { font-size: var(--entropia-type-caption-size); color: var(--entropia-color-ink-muted); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 600; }
.kpi-tile-value { font-size: 28px; line-height: 1.1; color: var(--entropia-color-ink-strong); font-weight: 600; letter-spacing: -0.01em; }
.kpi-tile-sub { font-size: var(--entropia-type-caption-size); color: var(--entropia-color-ink-soft); }
.kpi-tile-trend { font-size: var(--entropia-type-caption-size); font-weight: 600; }
.kpi-tile-trend.up { color: var(--entropia-color-success); }
.kpi-tile-trend.down { color: var(--entropia-color-danger); }
.kpi-tile::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px; background: var(--entropia-color-brand-primary);
}

/* ───────── Tables ───────── */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.data-table th, .data-table td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--entropia-color-line);
}
.data-table th {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--entropia-color-ink-muted); font-weight: 600;
  background: var(--entropia-color-surface-sunken);
}
.data-table tbody tr:hover { background: var(--entropia-color-surface-sunken); }
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table td.numeric { font-family: var(--entropia-type-mono); text-align: right; font-variant-numeric: tabular-nums; }
.data-table td.actions { text-align: right; white-space: nowrap; }

/* ───────── Layout helpers ───────── */
.stack { display: flex; flex-direction: column; gap: var(--entropia-space-md); }
.stack-lg { display: flex; flex-direction: column; gap: var(--entropia-space-lg); }
.row { display: flex; align-items: center; gap: var(--entropia-space-md); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--entropia-space-md); }
.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--entropia-space-lg); }
.grid-3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--entropia-space-lg); }
.gap-sm { gap: var(--entropia-space-sm); }

/* ───────── Login shell ───────── */
.login-shell {
  display: grid;
  grid-template-columns: minmax(620px, 1.15fr) 440px;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--entropia-color-surface-raised);
}
@media (max-width: 900px) {
  .login-shell { grid-template-columns: 1fr; }
  .login-brand-panel { min-height: 340px; }
}
.login-brand-panel {
  color: var(--entropia-color-surface-raised);
  padding: clamp(28px, 4vw, 52px);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background:
    linear-gradient(90deg, rgba(7, 12, 22, 0.22) 0%, rgba(7, 12, 22, 0.08) 34%, rgba(7, 12, 22, 0.02) 100%),
    url('/brand/login-warehouse.webp') 50% center / cover no-repeat;
}
.login-brand-backdrop {
  display: none;
}
.login-brand-atmosphere {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 12% 16%, rgba(255, 237, 184, 0.72), transparent 20%),
    linear-gradient(112deg, rgba(255, 236, 188, 0.34) 10%, rgba(255, 236, 188, 0) 28%),
    linear-gradient(120deg, rgba(255, 248, 228, 0.20) 14%, rgba(255, 248, 228, 0) 40%),
    radial-gradient(circle at 58% 40%, rgba(255,255,255,0.08) 0%, rgba(255,255,255,0) 34%),
    radial-gradient(circle at 18% 22%, rgba(255,255,255,0.08) 0 1px, transparent 2px),
    radial-gradient(circle at 22% 28%, rgba(255,255,255,0.06) 0 1px, transparent 2px),
    radial-gradient(circle at 28% 32%, rgba(255,255,255,0.05) 0 1px, transparent 2px);
  background-size: auto, auto, auto, auto, 160px 160px, 210px 210px, 260px 260px;
  mix-blend-mode: screen;
  opacity: 1;
  pointer-events: none;
}
.login-brand-panel > * { position: relative; z-index: 1; }
.login-brand-lockup {
  display: flex;
  align-items: center;
}
.login-brand-logo {
  width: min(320px, 46vw);
  height: auto;
  display: block;
  filter: drop-shadow(0 2px 10px rgba(255, 255, 255, 0.18));
}
.login-story {
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: 54ch;
  margin-top: auto;
}
.login-story h1 {
  font-size: clamp(44px, 5vw, 72px);
  line-height: 0.94;
  font-weight: 700;
  letter-spacing: -0.04em;
  max-width: 9ch;
  margin: 0;
  text-wrap: balance;
  color: var(--entropia-color-surface-raised);
  text-shadow: 0 2px 16px rgba(7, 12, 22, 0.34);
}
.login-story p {
  color: rgba(255, 255, 255, 0.98);
  max-width: 46ch;
  margin: 0;
  font-size: 16px;
  line-height: 1.6;
  text-shadow: 0 1px 10px rgba(7, 12, 22, 0.28);
}
.login-story h1:focus {
  outline: none;
  box-shadow: none;
  background: transparent;
  border-radius: 0;
  padding: 0;
  margin: 0;
}
.login-card {
  background: var(--entropia-color-surface-raised);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(28px, 4vw, 52px);
  border-left: 1px solid var(--entropia-color-line);
}
.login-card-inner { max-width: 380px; margin: 0 auto; width: 100%; }
.login-card h2 { font-size: var(--entropia-type-title-size); margin-bottom: var(--entropia-space-xs); }
.login-card p { color: var(--entropia-color-ink-muted); font-size: 13px; margin-bottom: var(--entropia-space-xl); }
.login-form { display: flex; flex-direction: column; gap: var(--entropia-space-md); }
.login-form .btn-primary { width: 100%; height: 44px; }
.login-form .error {
  background: var(--entropia-color-danger-soft); color: var(--entropia-color-danger);
  padding: 10px 14px; border-radius: 0;
  font-size: 13px;
}

/* Fluent-skinned login fields — each field wraps a FluentTextField + its
   validation message. The label is rendered by FluentTextField itself. */
.login-field { display: flex; flex-direction: column; gap: 4px; }
.login-form fluent-button::part(control) {
  width: 100%;
  height: 44px;
  justify-content: center;
}
.login-form fluent-text-field::part(root) { width: 100%; }

/* ───────── Toasts / dialogs (existing patterns preserved) ───────── */
.toast-container { position: fixed; right: 24px; bottom: 24px; display: flex; flex-direction: column; gap: 8px; z-index: var(--entropia-z-toast); }
.toast { background: var(--entropia-color-surface); border: 1px solid var(--entropia-color-line); padding: 12px 14px; border-radius: var(--entropia-radius-md); box-shadow: var(--entropia-shadow-lg); display: flex; align-items: center; gap: 10px; font-size: 13px; }
.toast-success { border-color: var(--entropia-color-success); }
.toast-danger { border-color: var(--entropia-color-danger); }
.confirm-backdrop { position: fixed; inset: 0; background: rgba(15, 23, 42, 0.4); z-index: var(--entropia-z-modal); display: grid; place-items: center; }
.confirm-card { background: var(--entropia-color-surface); border-radius: var(--entropia-radius-lg); padding: var(--entropia-space-xl); max-width: 420px; box-shadow: var(--entropia-shadow-lg); }

/* ───────── Empty / Loading ───────── */
.empty-state { display: flex; flex-direction: column; align-items: center; gap: var(--entropia-space-md); padding: var(--entropia-space-xxl) var(--entropia-space-xl); text-align: center; color: var(--entropia-color-ink-muted); }
.empty-state h3 { color: var(--entropia-color-ink-strong); }
.empty-state-cta { display: flex; gap: var(--entropia-space-sm); }
.skeleton { background: linear-gradient(90deg, var(--entropia-color-line) 0%, var(--entropia-color-surface-sunken) 50%, var(--entropia-color-line) 100%); background-size: 200% 100%; animation: entropia-shimmer 1.6s infinite; border-radius: var(--entropia-radius-md); height: 14px; }
@keyframes entropia-shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

/* ───────── Sidebar toggle (mobile + desktop) ───────── */
.sidebar-toggle {
  display: none;
  width: 36px; height: 36px; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-md); cursor: pointer;
}
.sidebar-toggle-bar { display: block; width: 16px; height: 2px; background: var(--entropia-color-ink-strong); border-radius: 2px; position: relative; }
.sidebar-toggle-bar::before, .sidebar-toggle-bar::after {
  content: ""; position: absolute; left: 0; width: 100%; height: 2px; background: inherit; border-radius: inherit;
}
.sidebar-toggle-bar::before { top: -5px; }
.sidebar-toggle-bar::after { top: 5px; }
@media (max-width: 900px) { .sidebar-toggle { display: inline-flex; } }

/* ───────── Layout-modern shims (preserve class names from prior layout) ───────── */
.app-layout-modern { display: grid; grid-template-columns: 1fr; grid-template-rows: var(--entropia-dimen-topbar-height) auto 1fr; }
.content-modern { grid-area: main; padding: var(--entropia-space-xl); }
.sidebar-modern { background: var(--entropia-color-surface-raised); }
.brand-lockup, .brand-lockup-full { color: var(--entropia-color-ink); }
.brand-mark, .brand-mark-sidebar { display: none; }
.sidebar-modern .sidebar-brand-mark { display: grid; }
.nav-list-modern { gap: 6px; }
.scope-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; background: rgba(37, 99, 235, 0.08); color: var(--entropia-color-brand-primary-strong); font-size: 11px; font-weight: 600; }
.scope-chip-light { background: var(--entropia-color-surface); color: var(--entropia-color-ink); border: 1px solid rgba(15, 23, 42, 0.08); }
.session-expired-overlay { position: fixed; inset: 0; background: rgba(15, 23, 42, 0.6); z-index: var(--entropia-z-modal); display: grid; place-items: center; }
.session-expired-card { background: var(--entropia-color-surface); padding: var(--entropia-space-xl); border-radius: var(--entropia-radius-lg); max-width: 360px; box-shadow: var(--entropia-shadow-lg); }

/* Compatibility with prior CSS rules still referenced by individual pages */
.scope-header { display: flex; align-items: center; justify-content: space-between; gap: var(--entropia-space-sm); padding: 0 var(--entropia-space-sm); margin-bottom: var(--entropia-space-sm); }
.scope-header h3 { font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--entropia-color-rail-text-muted); margin: 0; }
.dashboard-eyebrow { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--entropia-color-ink-soft); font-weight: 600; margin: 0 0 4px; }
.dashboard-panel-header { display: flex; align-items: flex-start; gap: var(--entropia-space-md); margin-bottom: var(--entropia-space-md); }
.dashboard-action-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  border-radius: var(--entropia-radius-md);
  border: 1px solid var(--entropia-color-line);
  background: var(--entropia-color-surface);
}
.dashboard-action-card:hover { background: var(--entropia-color-surface-sunken); border-color: var(--entropia-color-line-strong); text-decoration: none; }
.dashboard-action-card strong { font-size: 13px; color: var(--entropia-color-ink-strong); font-weight: 600; }
.dashboard-action-card span { font-size: 12px; color: var(--entropia-color-ink-muted); }
.dashboard-command-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--entropia-space-md);
}
.dashboard-command-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 164px;
  padding: 18px;
  border-radius: var(--entropia-radius-lg);
  border: 1px solid rgba(37, 99, 235, 0.14);
  background: linear-gradient(180deg, rgba(37, 99, 235, 0.08), rgba(37, 99, 235, 0.02));
  box-shadow: 0 10px 24px rgba(15, 23, 42, 0.06);
}
.dashboard-command-card:hover {
  border-color: rgba(37, 99, 235, 0.24);
  background: linear-gradient(180deg, rgba(37, 99, 235, 0.12), rgba(37, 99, 235, 0.03));
  text-decoration: none;
}
.dashboard-command-kicker {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--entropia-color-brand-primary-strong);
}
.dashboard-command-card strong {
  font-size: 1.1rem;
  color: var(--entropia-color-ink-strong);
}
.dashboard-command-card span {
  color: var(--entropia-color-ink-muted);
}
.dashboard-aside-stack {
  display: grid;
  gap: var(--entropia-space-md);
}
.dashboard-ready-note {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  border-radius: var(--entropia-radius-md);
  background: var(--entropia-color-surface-sunken);
  border: 1px solid var(--entropia-color-line);
}
.dashboard-ready-note strong {
  color: var(--entropia-color-ink-strong);
  font-size: 13px;
}
.dashboard-ready-note span {
  color: var(--entropia-color-ink-muted);
  font-size: 12px;
}
.dashboard-checklist-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.dashboard-checklist-list li { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: var(--entropia-radius-md); background: var(--entropia-color-surface-sunken); font-size: 13px; }
.dashboard-checklist-list li.check-done { color: var(--entropia-color-ink-soft); }
.dashboard-checklist-list li.check-done a { color: var(--entropia-color-ink-soft); text-decoration: line-through; }
.dashboard-checklist-list li.check-todo a { color: var(--entropia-color-brand-primary); }
.dashboard-checklist-list li span { margin-left: auto; font-size: 11px; font-weight: 600; color: var(--entropia-color-ink-muted); }
.dashboard-checklist-list li.check-done span { color: var(--entropia-color-success); }
.dashboard-flow-grid {
  display: grid;
  gap: 10px;
}
.dashboard-flow-card {
  min-height: 84px;
}
.dashboard-empty-card { padding: var(--entropia-space-xl); border: 1px dashed var(--entropia-color-line); border-radius: var(--entropia-radius-md); color: var(--entropia-color-ink-muted); text-align: center; }
.dashboard-bar-chart { width: 100%; height: 240px; }
.dashboard-bar-value { font-size: 12px; fill: var(--entropia-color-ink-strong); font-weight: 600; }
.dashboard-bar-label { font-size: 11px; fill: var(--entropia-color-ink-muted); }
.dashboard-bar { fill: var(--entropia-color-brand-primary); }

/* ───────── Dashboard / ribbon polish ───────── */
.page-toolbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--entropia-space-sm);
  margin-bottom: var(--entropia-space-lg);
}
.page-toolbar-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--entropia-space-sm);
  padding: 8px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 999px;
  background: var(--entropia-color-surface-raised);
  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.06);
}

.workflow-ribbon {
  margin-bottom: var(--entropia-space-lg);
  padding: 10px 14px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 16px;
  background: var(--entropia-color-surface-raised);
  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.05);
}
.workflow-steps {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.workflow-steps li {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.workflow-steps li:not(:last-child)::after {
  content: "→";
  color: var(--entropia-color-ink-soft);
  font-size: 12px;
  font-weight: 700;
}
.workflow-steps a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 12px;
  border-radius: 999px;
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink-muted);
  border: 1px solid rgba(15, 23, 42, 0.08);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
}
.workflow-step-current a,
.workflow-step-terminal a {
  background: rgba(37, 99, 235, 0.10);
  color: var(--entropia-color-brand-primary-strong);
  border-color: rgba(37, 99, 235, 0.18);
}

.metric-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--entropia-space-md);
}
.metric-tile {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 120px;
  padding: 18px 18px 20px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 18px;
  background: linear-gradient(180deg, var(--entropia-color-surface-raised) 0%, var(--entropia-color-surface) 100%);
  box-shadow: 0 8px 22px rgba(15, 23, 42, 0.06);
}
.metric-tile::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--entropia-color-brand-primary);
}
.metric-tile-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--entropia-color-ink-soft);
}
.metric-tile strong {
  font-size: 34px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: -0.04em;
  color: var(--entropia-color-ink);
}
.metric-tile-sub {
  font-size: 13px;
  line-height: 1.5;
  color: var(--entropia-color-ink-muted);
}

.feedback-banner {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 18px;
  border-radius: 16px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  background: var(--entropia-color-surface-raised);
  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.05);
}
.feedback-banner.error {
  border-color: rgba(220, 38, 38, 0.18);
  background: var(--entropia-color-danger-soft);
}

.empty-state-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 32px 24px;
  border: 1px dashed rgba(15, 23, 42, 0.12);
  border-radius: 18px;
  background: var(--entropia-color-surface);
  text-align: center;
}
.empty-state-icon {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 16px;
  background: rgba(37, 99, 235, 0.08);
  color: var(--entropia-color-brand-primary-strong);
  font-size: 18px;
  font-weight: 700;
}

/* ───────── Shared admin surface polish ───────── */
.lead {
  max-width: 72ch;
  font-size: 15px;
  line-height: 1.7;
  color: var(--entropia-color-ink-muted);
}

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  padding: 14px 16px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 16px;
  background: var(--entropia-color-surface-raised);
  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.05);
}
.filter-search {
  min-width: 240px;
  flex: 1 1 260px;
}
.filter-select {
  min-width: 160px;
}
.filter-active-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 28px;
  padding: 0 8px;
  border-radius: 999px;
  background: rgba(37, 99, 235, 0.1);
  color: var(--entropia-color-brand-primary-strong);
  font-size: 12px;
  font-weight: 700;
}
.filter-clear {
  border-color: rgba(15, 23, 42, 0.12);
}

.form-section {
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 18px;
  background: var(--entropia-color-surface-raised);
  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.05);
  overflow: hidden;
}
.form-section + .form-section {
  margin-top: 16px;
}
.form-section-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--entropia-color-ink);
  margin: 0;
}
.form-section-body {
  padding: 16px 18px 18px;
}
.form-section > .form-section-title {
  display: block;
  padding: 14px 18px 0;
}
.form-section-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 18px;
  background: var(--entropia-color-surface-raised);
  border: 0;
  cursor: pointer;
  text-align: left;
}
.form-section-chevron {
  color: var(--entropia-color-ink-soft);
  font-size: 15px;
  font-weight: 700;
  transition: transform 120ms ease;
}
.form-section-chevron.expanded {
  transform: rotate(90deg);
}

.sticky-form-actions {
  position: sticky;
  bottom: 0;
  padding-top: 14px;
  margin-top: 20px;
  background: linear-gradient(180deg, rgba(247, 249, 252, 0), var(--entropia-color-surface) 32%);
}
.sticky-form-actions-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 18px;
  background: var(--entropia-color-surface-raised);
  box-shadow: 0 10px 24px rgba(15, 23, 42, 0.06);
}
.sticky-form-commands {
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.settings-layout {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.settings-nav {
  position: sticky;
  top: 136px;
  padding: 14px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 20px;
  background: var(--entropia-color-surface-raised);
  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.05);
}
.settings-nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.settings-nav-item {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 14px;
  border: 1px solid transparent;
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink-muted);
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  text-align: left;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.settings-nav-item:hover {
  background: rgba(37, 99, 235, 0.08);
  border-color: rgba(37, 99, 235, 0.12);
}
.settings-nav-item.active {
  background: var(--entropia-color-brand-primary);
  color: var(--entropia-color-surface-raised);
}
.settings-nav-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  font-size: 11px;
  font-weight: 700;
}
.settings-form {
  min-width: 0;
  padding: 18px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 20px;
  background: var(--entropia-color-surface-raised);
  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.05);
}
.settings-form fluent-tabs {
  width: 100%;
}

.legacy-report-list {
  list-style: none;
  padding: 0;
  margin: 14px 0 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.legacy-report-list li {
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--entropia-color-surface);
  border: 1px solid rgba(15, 23, 42, 0.06);
}

.row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px;
}
.g-2 {
  gap: 12px;
}
.col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7 {
  min-width: 0;
  flex: 1 1 280px;
}
.col-md-3 { max-width: 320px; }
.col-md-4 { max-width: 420px; }
.col-md-5 { flex-basis: 380px; }
.col-md-6 { flex-basis: 460px; }
.col-md-7 { flex-basis: 520px; }

.modal-content {
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 20px;
  background: var(--entropia-color-surface-raised);
  box-shadow: 0 18px 42px rgba(15, 23, 42, 0.12);
}
.modal-header,
.modal-body,
.modal-footer {
  padding: 18px 20px;
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  border-bottom: 1px solid rgba(15, 23, 42, 0.08);
}
.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  border-top: 1px solid rgba(15, 23, 42, 0.08);
}

@media (max-width: 1080px) {
  .settings-layout {
    grid-template-columns: 1fr;
  }
  .settings-nav {
    position: static;
  }
}

/* ───────── Dark-mode contrast boost ─────────
 * The warm dark palette lifts surfaces and brightens lines so every card, input,
 * dropdown and border reads clearly against the espresso canvas. These rules
 * only apply in dark mode (both explicit data-theme and OS preference) and
 * strengthen the borders on form controls and cards beyond what the token
 * values alone produce, because native <select> and <input> borders can still
 * look faint even with a brighter --entropia-color-line.
 * ─────────────────────────────────────────── */
[data-theme="dark"] .input,
[data-theme="dark"] input.input,
[data-theme="dark"] textarea.input,
[data-theme="dark"] select.input,
[data-theme="dark"] .card,
[data-theme="dark"] .panel-card,
[data-theme="dark"] .dashboard-action-card {
  border-width: 1px;
  border-color: var(--entropia-color-line-strong);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .input,
  :root:not([data-theme="light"]) input.input,
  :root:not([data-theme="light"]) textarea.input,
  :root:not([data-theme="light"]) select.input,
  :root:not([data-theme="light"]) .card,
  :root:not([data-theme="light"]) .panel-card,
  :root:not([data-theme="light"]) .dashboard-action-card {
    border-width: 1px;
    border-color: var(--entropia-color-line-strong);
  }
}

/* ───────── Theme toggle button ─────────
 * A visible, always-reachable light/dark switch in the topbar. Not a ghost
 * button — it has its own surface, border and icon so the operator can find
 * it without scanning. The icon swaps between a sun (light mode active) and
 * a moon (dark mode active) via CSS only; the markup carries both and hides
 * the irrelevant one per theme.
 * ─────────────────────────────────────── */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  min-width: 36px;
  padding: 0 10px;
  border-radius: var(--entropia-radius-md);
  border: 1px solid var(--entropia-color-line-strong);
  background: var(--entropia-color-surface-raised);
  color: var(--entropia-color-ink);
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--entropia-duration-fast) var(--entropia-ease),
              border-color var(--entropia-duration-fast) var(--entropia-ease);
}
.theme-toggle:hover {
  background: var(--entropia-color-surface-sunken);
  border-color: var(--entropia-color-brand-primary);
}
.theme-toggle:focus-visible {
  outline: 2px solid var(--entropia-color-brand-primary);
  outline-offset: 2px;
}
.theme-toggle .theme-icon-sun { display: none; }
.theme-toggle .theme-icon-moon { display: inline; }

/* In dark mode, show the sun (action: switch to light) and hide the moon. */
[data-theme="dark"] .theme-toggle .theme-icon-sun { display: inline; }
[data-theme="dark"] .theme-toggle .theme-icon-moon { display: none; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .theme-icon-sun { display: inline; }
  :root:not([data-theme="light"]) .theme-toggle .theme-icon-moon { display: none; }
}

/* ----------------------------------------------------------------------------
 * Industrial override pass — strict white / black / blue, square everywhere.
 * -------------------------------------------------------------------------- */
.skip-link,
.sidebar-brand-mark,
.sidebar-section-tab,
.topbar-section-tab,
.nav-item a,
.nav-badge,
.sidebar-user,
.sidebar-user-avatar,
.btn,
.btn-sm,
.chip,
.card,
.panel-card,
.kpi-tile,
.page-toolbar-actions,
.workflow-ribbon,
.dashboard-action-card,
.dashboard-command-card,
.dashboard-ready-note,
.dashboard-checklist-list li,
.scope-chip,
.theme-toggle,
.topbar,
.sidebar {
  border-radius: 0 !important;
}

.sidebar-brand-mark {
  background: var(--entropia-color-brand-primary) !important;
  box-shadow: none !important;
}

.sidebar,
.topbar {
  background: var(--entropia-color-surface-raised) !important;
}

.sidebar {
  background: var(--entropia-color-rail-bg) !important;
}

.sidebar-section-tab,
.topbar-section-tab {
  background: var(--entropia-color-surface-sunken) !important;
  color: var(--entropia-color-ink) !important;
}

.sidebar-section-tab.is-active,
.topbar-section-tab.is-active,
.nav-item a.active,
.btn-primary,
a.btn-primary {
  background: var(--entropia-color-brand-primary) !important;
  border-color: var(--entropia-color-brand-primary) !important;
  color: var(--entropia-color-on-brand) !important;
  filter: none !important;
}

.nav-item a,
.page-toolbar-actions,
.workflow-ribbon,
.dashboard-action-card,
.dashboard-command-card,
.dashboard-ready-note {
  box-shadow: none !important;
}

.dashboard-command-card {
  background: var(--entropia-color-surface-raised) !important;
  border-color: var(--entropia-color-line-strong) !important;
}

.page-toolbar-actions {
  background: var(--entropia-color-surface) !important;
}

.chip-brand,
.scope-chip {
  background: var(--entropia-color-info-soft) !important;
  color: var(--entropia-color-info) !important;
}

.kpi-tile::before {
  width: 2px !important;
  background: var(--entropia-color-brand-primary) !important;
}

.login-brand-panel::after {
  background:
    radial-gradient(circle at 78% 18%, rgba(37, 99, 235, 0.16), transparent 34%),
    radial-gradient(circle at 24% 76%, rgba(255, 255, 255, 0.05), transparent 40%) !important;
}

.sidebar {
  padding-top: 12px !important;
}

.sidebar-section-shell {
  gap: 12px !important;
}

.sidebar-section-tabs {
  display: flex !important;
  flex-direction: column !important;
  align-items: stretch !important;
  gap: 6px !important;
  width: 180px !important;
  flex: 0 0 180px !important;
}

.sidebar-section-tab {
  width: 100% !important;
  justify-content: flex-start !important;
  text-align: left !important;
}

.sidebar-section-body {
  align-items: flex-start !important;
}

.sidebar-section-copy {
  flex: 0 0 220px !important;
}

.nav-list {
  flex-direction: column !important;
  align-items: stretch !important;
}

.nav-item a {
  width: 100% !important;
  justify-content: flex-start !important;
}

/* ----------------------------------------------------------------------------
 * Post-login shell repair — compact true left rail, content-first.
 * -------------------------------------------------------------------------- */
@media (min-width: 901px) {
  .app-layout,
  .app-layout-rail-collapsed {
    grid-template-columns: 248px minmax(0, 1fr);
    grid-template-rows: var(--entropia-shell-header-height) minmax(0, 1fr);
    grid-template-areas:
      "rail topbar"
      "rail main";
  }

  .sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100dvh;
    border-right: 1px solid rgba(15, 23, 42, 0.08);
    border-bottom: 0;
    padding: 16px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--entropia-color-line) transparent;
    gap: 16px;
  }

  .sidebar-rail-header {
    justify-content: flex-start;
    min-height: 36px;
  }

  .sidebar-brand {
    min-width: 0;
  }

  .sidebar-brand-text span {
    margin-top: 2px;
  }

  .sidebar-section-shell {
    gap: 14px;
    min-width: 0;
  }

  .sidebar-section-body {
    flex-direction: column;
    gap: 10px;
    align-items: stretch;
  }

  .sidebar-section-copy {
    flex: 0 0 auto;
    width: 100%;
    gap: 6px;
  }

  .sidebar-section-description {
    max-width: none;
    font-size: 12px;
    line-height: 1.45;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
  }

  .nav-list {
    width: 100%;
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 4px;
  }

  .nav-item a {
    width: 100%;
    min-height: 38px;
    justify-content: flex-start;
    padding: 8px 10px;
  }

  .nav-badge {
    margin-left: auto;
  }

  .sidebar-footer {
    margin-top: auto;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
  }

  .sidebar-footer-controls {
    min-width: 0;
  }

  .sidebar-user {
    padding: 8px 0;
  }

  .topbar {
    height: var(--entropia-shell-header-height);
  }

  .topbar-main {
    padding: 0 24px;
  }

  .topbar-section-nav {
    padding: 8px 24px;
  }

  .topbar-search {
    width: min(320px, 34vw);
  }

  .content,
  .content-modern {
    max-width: none;
    margin: 0;
    padding: 20px 24px 32px;
  }
}

/* ═════════════════════════════════════════════════════════════════════════════
   L2 — SWISS PAGE GRID — Müller-Brockmann page grid (mb-grid), overlay, bands, display type. Container class is mb-grid (NOT .grid — FluentDataGrid owns .grid).
   ═════════════════════════════════════════════════════════════════════════════ */

/*
 * Müller-Brockmann grid tokens — single source of truth for the admin surface.
 *
 * Why this file exists:
 *   The admin UI must read as International Typographic Style (Swiss): one
 *   grotesque, flush-left, big numerals, restrained palette (white / ink / one
 *   red). To prove the grid is real (and not decorative), every variable here
 *   drives both the content and the overlay. The overlay lives inside the same
 *   content box, and every element snaps to a column line via subgrid bands.
 *
 * Authoring rules (apply these or the verification will fail):
 *   • All spacing is a multiple of `--bl` (baseline = 8px).
 *   • All line-heights for display type are px (not unitless) so 180px headlines
 *     stay ink-on-grid.
 *   • Never hand-author an overlay column width. Read `--cols`, `--gutter`.
 *   • If you change `--cols` here, every `.band > *` snaps automatically.
 *
 * The overlay (`body.grid-on .guides`) and ink-alignment (`grid.js`) are
 * verification tools. Press `G` to toggle; the page should not visually change
 * except for translucent columns and the baseline lattice.
 *
 * The page-grid container class is `.mb-grid` (not `.grid`). FluentDataGrid
 * emits its own class="grid" on its root element, so any `.grid` selector in
 * this file would have leaked onto every data grid on the page (clipped rows
 * was the symptom). The wrapper that pages render is therefore `<div
 * class="mb-grid">` (and the outer `<div class="grid-page">` plus `<div
 * class="grid-wrap">` which host the paper base and the shared column track
 * respectively). Class names `.grid-page`, `.grid-wrap`, `.band`, `.data-band`,
 * `.data-row`, `.data-cell`, `.numeral`, `.kicker`, `.rule`, `.guides`, and
 * `.grid-toggle` are kept — only the bare utility class was renamed.
 */

:root {
    /* Single source of truth */
    --cols: 12;
    --gutter: 24px;          /* 3 × --bl */
    --margin: 48px;          /* 6 × --bl */
    --bl: 8px;
    --lh: 24px;              /* line-height unit = 3 × --bl, used as `lh` for everything */
    --maxw: 1440px;
    --accent: #e4002b;       /* Swiss red */

    /* Font aliases — point at tokens so loading Inter / JetBrains Mono from fonts.css
       (and theme swaps in dark mode) is one hop from every rule in this file. */
    --display-font: var(--entropia-font-sans);
    --body-font: var(--entropia-font-sans);
    --mono-font: var(--entropia-font-mono);

    /* Type scale (large jumps; restraint is the point) */
    --type-display: 56px;
    --type-h1: 36px;
    --type-h2: 24px;
    --type-body: 15px;
    --type-caption: 12px;

    /* Palette — white / ink / one accent.
       Forwarded to the design tokens rather than held as literals: this file has
       no dark block of its own, so hardcoding them left all 60 GridPage adopters
       painting white paper and near-black ink in dark mode — white-on-white
       buttons and unreadable numerals. Forwarding costs nothing in light mode
       (the tokens resolve to the same near-white/near-black) and makes the grid
       follow whichever theme is active. */
    --grid-paper: var(--entropia-color-surface);
    --grid-ink: var(--entropia-color-ink);
    --grid-muted: var(--entropia-color-ink-muted);
    --grid-rule: var(--entropia-color-line);
    --grid-overlay-col: rgba(228, 0, 43, 0.10);
    --grid-overlay-baseline-major: rgba(17, 17, 17, 0.06);
    --grid-overlay-baseline-minor: rgba(17, 17, 17, 0.025);
    --grid-overlay-margin: rgba(228, 0, 43, 0.35);
}

/* Paper.
   Selector is `.grid-page`, not `body.grid-page`: every consumer puts the class
   on a div (GridPage.razor:12, AdminSettings.razor:7, Modules.razor:10), so the
   body-qualified form never matched and this typographic base never applied,
   while the descendant `.mb-grid *` rules did. */
.grid-page {
    background: var(--grid-paper);
    color: var(--grid-ink);
    font-family: var(--body-font);
    font-size: var(--type-body);
    line-height: var(--lh);
    margin: 0;
}

/*
 * The wrap hosts BOTH the content and the overlay so they share column
 * positions at every viewport width. See skill §2.2 — if the overlay were a
 * sibling of the wrap it would drift from the columns the moment the page
 * exceeded --maxw.
 */
.grid-wrap {
    box-sizing: border-box;
    width: 100%;
    max-width: var(--maxw);
    margin: 0 auto;
    padding-left: var(--margin);
    padding-right: var(--margin);
    position: relative;
}

/*
 * Each section / band exposes the full column field as a 12-column track.
 * Children place with `grid-column: <startline> / <endline>` so every element
 * snaps to a column line. Subgrid is preferred; we fall back to a regular
 * repeat() if the browser hasn't shipped subgrid yet.
 *
 * Class `mb-grid`, not the bare utility-class name, to avoid colliding with FluentDataGrid's own
 * root class — the Fluent bundle paints `.fluent-data-grid` with `display:grid`, and sharing the
 * name here meant its row-gap / column-gap silently leaked onto every data grid on the page.
 */
.mb-grid {
    display: grid;
    grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
    column-gap: var(--gutter);
    row-gap: calc(var(--bl) * 3);
    align-items: start;
}

/*
 * Auto-band: any direct child of .mb-grid gets band layout without needing an
 * explicit <section class="band"> wrapper. This is the consumable-library
 * optimization — pages swap <div class="page-stack"> for <GridPage> and
 * their existing top-level sections automatically get grid-column placement.
 */
.mb-grid > section,
.mb-grid > .band,
.mb-grid > fluent-tabs {
    grid-column: 1 / -1;
}

.mb-grid > section,
.mb-grid > .band {
    display: grid;
    grid-template-columns: subgrid;
    column-gap: var(--gutter);
    align-items: start;
}

.mb-grid > fluent-tabs {
    display: block;
    width: 100%;
    min-width: 0;
}

@supports not (grid-template-columns: subgrid) {
    .mb-grid > section,
    .mb-grid > .band {
        grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
    }
}

.mb-grid > section > *,
.mb-grid > .band > * {
    grid-column: 1 / -1;
}

/* Display type — flush-left, ragged-right. Line-height in px keeps big glyphs
 * ink-on-grid; unitless line-heights push large display off the baseline. */
.mb-grid .display,
.mb-grid h1.grid-h1,
.mb-grid h2.grid-h2 {
    font-family: var(--display-font);
    line-height: calc(var(--lh) * 2);   /* 48px for h1; mutable per element */
    margin: 0;
    letter-spacing: -0.01em;
}

.mb-grid .display { font-size: var(--type-display); line-height: calc(var(--lh) * 3); font-weight: 700; letter-spacing: -0.02em; }
.mb-grid h1.grid-h1 { font-size: var(--type-h1); line-height: calc(var(--lh) * 2); font-weight: 700; }
.mb-grid h2.grid-h2 { font-size: var(--type-h2); line-height: var(--lh); font-weight: 600; }

/* Kicker / folio — mono, caps, ink-muted */
.mb-grid .kicker {
    font-family: var(--mono-font);
    font-size: var(--type-caption);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--grid-muted);
}

/* Hairlines sit inside a baseline-height band; never free-floating. */
.mb-grid .rule {
    border: 0;
    border-top: 1px solid var(--grid-rule);
    height: var(--lh);
    margin: 0;
}

.mb-grid .rule--accent {
    border-top: 2px solid var(--accent);
    height: var(--lh);
}

/* Data table on the grid — 12 cols, cells snap to column lines */
.mb-grid .data-band {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
    column-gap: var(--gutter);
    row-gap: 0;
    border-top: 1px solid var(--grid-ink);
    border-bottom: 1px solid var(--grid-ink);
}

@supports not (grid-template-columns: subgrid) {
    .mb-grid .data-band {
        grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
    }
}

.mb-grid .data-row {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
    column-gap: var(--gutter);
    align-items: baseline;
    min-height: calc(var(--lh) * 2);
    padding-top: var(--bl);
    padding-bottom: var(--bl);
    border-bottom: 1px solid var(--grid-rule);
}

@supports not (grid-template-columns: subgrid) {
    .mb-grid .data-row {
        grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
    }
}

.mb-grid .data-row:last-child { border-bottom: 0; }

.mb-grid .data-cell {
    font-family: var(--body-font);
    font-size: var(--type-body);
    line-height: var(--lh);
    min-width: 0;
}

.mb-grid .data-cell.head {
    font-family: var(--mono-font);
    font-size: var(--type-caption);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--grid-muted);
    align-self: end;
    padding-bottom: var(--bl);
}

/* Big numerals — Müller-Brockmann signature. Optical alignment applied by JS. */
.mb-grid .numeral {
    font-family: var(--display-font);
    font-weight: 700;
    font-size: var(--type-h1);
    line-height: calc(var(--lh) * 2);
    letter-spacing: -0.02em;
    color: var(--grid-ink);
    font-variant-numeric: tabular-nums;
}

/* Status pills on the grid — restraint, restrained palette */
.mb-grid .badge {
    display: inline-block;
    font-family: var(--mono-font);
    font-size: var(--type-caption);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0 var(--bl);
    line-height: calc(var(--lh) - var(--bl));
    border: 1px solid currentColor;
}

.mb-grid .badge.on { color: var(--grid-ink); }
.mb-grid .badge.off { color: var(--accent); }

/* Feedback banner */
.mb-grid .feedback {
    grid-column: 1 / -1;
    font-family: var(--mono-font);
    font-size: var(--type-caption);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: var(--bl) calc(var(--bl) * 2);
    border-left: 2px solid var(--grid-ink);
    background: transparent;
}

.mb-grid .feedback.error { border-left-color: var(--accent); color: var(--accent); }

/* ──────────────────────────────────────────────────────────────────────────────
 * OVERLAY — must live inside the same content box. See skill §2.2.
 * Pressing G toggles `body.grid-on`; overlay fades 0→1.
 * ────────────────────────────────────────────────────────────────────────── */

.guides {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity 120ms ease-out;
    z-index: 9999;
}

body.grid-on .guides { opacity: 1; }

/* Columns share the same content track — drawn from the same variables */
.guides .cols {
    position: absolute;
    inset: 0 var(--margin);
    display: grid;
    grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
    column-gap: var(--gutter);
}

.guides .col {
    background: var(--grid-overlay-col);
    border-left: 1px dashed rgba(228, 0, 43, 0.35);
    border-right: 1px dashed rgba(228, 0, 43, 0.35);
}

.guides .col:first-child { border-left: 0; }
.guides .col:last-child  { border-right: 0; }

/* Margin guides */
.guides .margin {
    position: absolute;
    top: 0; bottom: 0;
    width: 0;
    border-left: 2px solid var(--grid-overlay-margin);
}

.guides .margin.left  { left: var(--margin); }
.guides .margin.right { right: var(--margin); }

/* Baseline lattice — major every --lh, faint minor every --bl */
.guides .baselines {
    position: absolute;
    inset: 0;
    background-image:
        repeating-linear-gradient(
            to bottom,
            transparent 0,
            transparent calc(var(--bl) - 1px),
            var(--grid-overlay-baseline-minor) calc(var(--bl) - 1px),
            var(--grid-overlay-baseline-minor) var(--bl)
        ),
        repeating-linear-gradient(
            to bottom,
            transparent 0,
            transparent calc(var(--lh) - 1px),
            var(--grid-overlay-baseline-major) calc(var(--lh) - 1px),
            var(--grid-overlay-baseline-major) var(--lh)
        );
}

/* Toggle chip */
.grid-toggle {
    position: fixed;
    bottom: var(--bl);
    right: var(--bl);
    z-index: 10000;
    font-family: var(--mono-font);
    font-size: var(--type-caption);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    background: var(--grid-ink);
    color: var(--grid-paper);
    border: 0;
    padding: var(--bl) calc(var(--bl) * 2);
    cursor: pointer;
}

.grid-toggle:hover { background: var(--accent); }

/*
 * A <Lead> handed to a page as ordinary content — rather than through GridPage's
 * Lead slot — lands here as a direct child of .mb-grid. Auto-placement then gives it
 * a single 1-of-12 track and the intro paragraph wraps at roughly ten characters,
 * a tall grey ribbon down the left of the page. Twenty-one pages do this, so the
 * span is granted here instead of being re-typed in each of them; it matches what
 * the Lead slot itself uses.
 */
.mb-grid > .lead {
    grid-column: 1 / 7;
    max-width: 56ch;
}

/* ═════════════════════════════════════════════════════════════════════════════
   L3 — COMPONENTS & FLUENT BRIDGE — FAST token bridge, buttons, inputs, chips, panels, workspaces, FluentDataGrid integration, drawers, AdminSettings cards, printing.
   ═════════════════════════════════════════════════════════════════════════════ */

/* ============================================================================
 * Entropia Admin — restored component layer
 * ============================================================================
 * WHY THIS FILE EXISTS
 *
 * Commit 6ab7439 ("Redesign Admin Web: palette slate/indigo") rewrote site.css
 * from 2808 lines down to 516. The rewrite kept the shell, the cards and the
 * grid, but dropped the rules for 111 classes that the markup still emits —
 * every shared component (ConfirmDialog, DetailDrawer, ToastContainer,
 * DataTable, EntityPicker, FieldHelp, ScanInput, EmptyState) plus the
 * `metric-tile` / `field-grid` / `page-toolbar` vocabulary used across the app.
 * Those classes had no rules at all afterwards, so they fell back to raw
 * browser defaults: confirm dialogs rendered with no overlay, drawers as
 * inline blocks, checkboxes as 13px native controls.
 *
 * grid.css:125 still refers to `.field-grid` as though it were styled, which is
 * how the deletion was spotted. The rules below are recovered from a9eec23
 * (the commit before the redesign) and re-themed onto the current tokens.
 *
 * WHAT WAS DELIBERATELY *NOT* RESTORED
 *
 * The old sheet styled bare `input, select, textarea` globally. The redesign
 * owns those through `.input`, so restoring them verbatim would have undone the
 * new field styling app-wide. Every selector part that targeted a bare element
 * was dropped; only class-scoped parts survive. That keeps this file additive:
 * it supplies rules for classes that currently have none, and overrides nothing
 * the redesign intentionally set.
 *
 * Load order matters — this file must come after tokens.generated.css and
 * site.css so the token overrides below win.
 * ========================================================================== */

/* ----------------------------------------------------------------------------
 * 1. Brand palette — coral (Warm Earth + Coral)
 *
 * Chosen for operators reading this screen for a full shift. Red is reserved
 * exclusively for the danger/alarm channel; spending it on the primary action
 * would cost the alarm colour its meaning. Coral leans orange, so it sits a
 * clear hue step away from the crimson danger channel while still reading as
 * warm and human against the parchment surfaces. It stays legible at the
 * saturation chosen here and carries the "primary action" intent without
 * competing with alarms.
 *
 * These override tokens.generated.css. The dark values are repeated under both
 * the media query and the explicit attribute because the generated file defines
 * dark twice with `:root[data-theme="dark"]` (0,1,1) outranking a bare `:root`;
 * matching its specificity is the only way an override lands in both modes.
 * -------------------------------------------------------------------------- */
:root {
  --entropia-color-brand-primary: #2563EB;
  --entropia-color-brand-primary-strong: #1D4ED8;
  --entropia-color-brand-primary-soft: #DBEAFE;
  --entropia-color-brand-primary-border: #93C5FD;
  --entropia-shadow-focus: 0 0 0 2px rgba(37, 99, 235, 0.22);
  --entropia-color-on-brand: #FFFFFF;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --entropia-color-brand-primary: #60A5FA;
    --entropia-color-brand-primary-strong: #93C5FD;
    --entropia-color-brand-primary-soft: #10233F;
    --entropia-color-brand-primary-border: #1D4ED8;
    --entropia-shadow-focus: 0 0 0 2px rgba(96, 165, 250, 0.28);
    --entropia-color-on-brand: #FFFFFF;

    --entropia-color-canvas: #0B1220;
    --entropia-color-surface-sunken: #0D1523;
    --entropia-color-line-strong: #334155;
    --entropia-color-ink-strong: #F8FAFC;
    --entropia-color-ink-inverse: #0B1220;
    --entropia-color-danger: #F87171;
    --entropia-color-danger-soft: #311313;
    --entropia-color-success: #4ADE80;
    --entropia-color-success-soft: #0F2217;
    --entropia-color-warning: #F59E0B;
    --entropia-color-warning-soft: #2A1B05;
    --entropia-color-info: #60A5FA;
    --entropia-color-info-soft: #0E223F;
    --entropia-color-rail-bg: #0A0F18;
    --entropia-color-rail-bg-hover: #131C2A;
    --entropia-color-rail-divider: #1E293B;
    --entropia-color-rail-text: #CBD5E1;
    --entropia-color-rail-text-muted: #94A3B8;
    --entropia-color-rail-text-strong: #F8FAFC;
    --entropia-color-rail-active-bg: #2563EB;
    --entropia-color-rail-active-text: #FFFFFF;
  }
}

:root[data-theme="dark"] {
  --entropia-color-brand-primary: #60A5FA;
  --entropia-color-brand-primary-strong: #93C5FD;
  --entropia-color-brand-primary-soft: #10233F;
  --entropia-color-brand-primary-border: #1D4ED8;
  --entropia-shadow-focus: 0 0 0 2px rgba(96, 165, 250, 0.28);
  --entropia-color-on-brand: #FFFFFF;
}

/* ----------------------------------------------------------------------------
 * Fluent UI Blazor token bridge
 *
 * The Fluent Web Components runtime looks for FAST design tokens on the host
 * element. Bridge our Entropia palette into the tokens Fluent respects so
 * Accent-colored buttons, links and focus rings carry the brand.
 * -------------------------------------------------------------------------- */
:root {
  /* Accent base — drives Accent buttons, links, active tab underlines. */
  --accent-base-color: var(--entropia-color-brand-primary);

  /* Neutral base — surfaces, text, borders. */
  --neutral-base-color: var(--entropia-color-canvas);
  --neutral-foreground-rest: var(--entropia-color-ink-strong);
  --neutral-foreground-hint: var(--entropia-color-ink-muted);
  --neutral-layer-1: var(--entropia-color-canvas);
  --neutral-layer-2: var(--entropia-color-surface-sunken);
  --neutral-layer-3: var(--entropia-color-surface-sunken);
  --neutral-stroke-rest: var(--entropia-color-line);
  --neutral-stroke-strong-rest: var(--entropia-color-line-strong);
  --neutral-fill-rest: var(--entropia-color-canvas);
  --neutral-fill-hover: var(--entropia-color-surface-sunken);
  --neutral-fill-active: var(--entropia-color-brand-primary-soft);

  /* Focus ring. */
  --focus-stroke-outer: var(--entropia-color-brand-primary);

  /* Typography ramp (Fluent 2 scale). */
  --font-family-base: var(--entropia-font-sans);
  --type-ramp-base-font-size: 0.875rem;
  --type-ramp-base-line-height: 1.25rem;
}

/* ----------------------------------------------------------------------------
 * 2. Status tones for light mode
 *
 * tokens.generated.css defines --entropia-status-* ONLY inside its two dark
 * blocks, even though design-system/entropia-tokens.json carries a full light
 * set and CssTokensGenerator emits one. The committed file has been hand-edited
 * away from what the generator produces, so the light values were lost.
 *
 * Consequence before this block: `.tone-danger` and friends resolved to
 * invalid-at-computed-value-time in light mode, so every status chip on the
 * operations cockpit and recall workbench lost its colour while still printing
 * the "!" glyph. Values below are copied verbatim from the token JSON so the
 * Web matches the PDA and Desktop.
 *
 * Regenerating was rejected deliberately: the committed file carries 31 colour
 * tokens, shadows and font-scale that the JSON cannot express (it defines 9
 * colours and no shadows), so running the generator would delete them.
 *
 * Values below mirror the Warm Earth + Coral light set now restored in
 * tokens.generated.css :root (and in design-system/entropia-tokens.json), kept
 * here so the override order this file relies on stays intact.
 * -------------------------------------------------------------------------- */
:root {
  --entropia-status-neutral-fg: #6B5D4F;
  --entropia-status-neutral-bg: #F5EFE3;
  --entropia-status-neutral-border: #E8DECC;

  --entropia-status-info-fg: #2563EB;
  --entropia-status-info-bg: #E8EEF7;
  --entropia-status-info-border: #C2D0EE;

  --entropia-status-success-fg: #16A34A;
  --entropia-status-success-bg: #E6F4EA;
  --entropia-status-success-border: #B8E0C5;

  --entropia-status-pending-fg: #0E7490;
  --entropia-status-pending-bg: #E0F2F4;
  --entropia-status-pending-border: #A6DEE6;

  --entropia-status-warning-fg: #D97706;
  --entropia-status-warning-bg: #FEF3C7;
  --entropia-status-warning-border: #FBDE9C;

  --entropia-status-danger-fg: #C62828;
  --entropia-status-danger-bg: #FBE9E9;
  --entropia-status-danger-border: #F2C2C2;

  --entropia-status-blocked-fg: #7E4A6B;
  --entropia-status-blocked-bg: #F1E4EC;
  --entropia-status-blocked-border: #E0C9D6;
}

/* ----------------------------------------------------------------------------
 * 3. Legacy alias map (extension)
 *
 * site.css already carries three of these with a comment warning that removing
 * them turns every `var(--entropia-ink)` call site into an empty string. The
 * recovered rules below reference sixteen more short names that the redesign
 * renamed. Forwarding them keeps the restored CSS theme-aware instead of
 * hard-coding a second palette.
 * -------------------------------------------------------------------------- */
:root {
  --entropia-surface: var(--entropia-color-surface);
  --entropia-surface-alt: var(--entropia-color-surface-sunken);
  --entropia-line: var(--entropia-color-line);
  --entropia-line-strong: var(--entropia-color-line-strong);
  --entropia-ink-muted: var(--entropia-color-ink-muted);
  --entropia-radius: var(--entropia-radius-md);
  --entropia-shadow-soft: var(--entropia-shadow-md);
  --entropia-shadow-hard: var(--entropia-shadow-lg);
  --entropia-primary-strong: var(--entropia-color-brand-primary-strong);

  /* Work-type accents. The four operator task families read as distinct at a
     glance on the task board; they are tinted from the status tones rather than
     given a fifth private palette. */
  --entropia-work-receive-bg: var(--entropia-status-info-bg);
  --entropia-work-receive-fg: var(--entropia-status-info-fg);
  --entropia-work-putaway-bg: var(--entropia-status-pending-bg);
  --entropia-work-putaway-fg: var(--entropia-status-pending-fg);
  --entropia-work-pick-bg: var(--entropia-status-success-bg);
  --entropia-work-pick-fg: var(--entropia-status-success-fg);
  --entropia-work-pack-bg: var(--entropia-status-blocked-bg);
  --entropia-work-pack-fg: var(--entropia-status-blocked-fg);
}

/* ----------------------------------------------------------------------------
 * 4. Native control theming
 *
 * Checkboxes and radios had no rule anywhere, so they rendered as 13px OS
 * widgets in the default blue next to a token-styled field. accent-color is the
 * one-property fix and keeps the native control's built-in accessibility.
 * -------------------------------------------------------------------------- */
input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--entropia-color-brand-primary);
  width: 16px;
  height: 16px;
  cursor: pointer;
}

input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
  outline: 2px solid var(--entropia-color-brand-primary);
  outline-offset: 2px;
}

input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

/* ----------------------------------------------------------------------------
 * 5. Recovered component rules
 *
 * Everything below is from a9eec23, filtered to class-scoped selectors and
 * re-pointed at the current tokens.
 * -------------------------------------------------------------------------- */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.scan-glyph {
  flex: none;
  vertical-align: middle;
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px 24px;
  margin: 12px 0 0;
}

.detail-grid dt {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--entropia-ink-muted);
  margin-bottom: 2px;
}

.detail-grid dd {
  margin: 0;
  font-size: var(--entropia-type-body-strong-size);
  font-weight: var(--entropia-type-body-strong-weight);
}

.object-search {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.object-search .scan-input-wrapper {
  flex: 1;
  min-width: 260px;
}

/* In the 56px topbar the status span must not wrap to a second line. */
.topbar-search .object-search {
  flex-wrap: nowrap;
}
.topbar-search .object-search .scan-input-wrapper {
  min-width: 0;
}
.topbar-search .object-search-status {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
}

.object-search-status {
  font-size: 0.86rem;
  padding: 4px 10px;
  border-radius: var(--entropia-radius);
}

.ops-section-heading {
  margin: 0 0 4px;
  font-size: var(--entropia-type-subtitle-size);
  font-weight: var(--entropia-type-subtitle-weight);
}

.ops-exception-panel {
  border-left: 3px solid var(--entropia-status-blocked-border);
}

.ops-live-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border: 1px solid;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
}

.ops-live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}

.ops-tally .metric-tile {
  border: 1px solid;
}

.exception-list {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.exception-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--entropia-line);
  border-radius: var(--entropia-radius);
  background: var(--entropia-surface-raised);
}

.exception-tone {
  flex: none;
  min-width: 92px;
  text-align: center;
}

.exception-body {
  flex: 1;
  min-width: 0;
}

.exception-headline {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}

.exception-reference {
  font-size: 0.86rem;
  color: var(--entropia-ink-muted);
}

.exception-detail {
  margin: 4px 0 0;
  font-size: 0.86rem;
}

.exception-meta {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.82rem;
  color: var(--entropia-ink-muted);
}

@media (max-width: 768px) {
  .exception-row {
    flex-direction: column;
  }

  .exception-meta {
    width: 100%;
    justify-content: space-between;
  }
}

.entity-picker-option,
.drawer-close,
.toast-close {
  min-height: var(--entropia-dimen-touch-min);
}

.entity-picker-option {
  display: flex;
  align-items: center;
}

.app-shell-root {
  background:
  radial-gradient(circle at top left, rgba(11,95,255,0.11), transparent 30%),
  linear-gradient(180deg, var(--entropia-surface-alt) 0%, var(--entropia-surface) 100%);
  color: var(--entropia-ink);
  font-family: var(--entropia-font-sans);
}

.page-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: start;
  gap: 18px;
  flex-wrap: wrap;
}

.page-toolbar h1 {
  margin: 0;
  font-size: clamp(2rem, 2.6vw, 2.7rem);
  letter-spacing: -0.03em;
  line-height: 0.98;
}

.page-toolbar p,
.panel-card p {
  max-width: 68ch;
}

.list-search-toolbar {
  align-items: center;
  padding-bottom: 4px;
}

.list-search-input {
  flex: 1 1 320px;
}

.pager-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.pager-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.form-control {
  box-sizing: border-box;
  width: 100%;
  margin-top: 8px;
  border: 1px solid var(--entropia-line-strong);
  background: var(--entropia-surface-raised);
  color: var(--entropia-ink);
  border-radius: var(--entropia-radius);
  padding: 12px 14px;
  font: inherit;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.7);
}

.error {
  margin-top: 12px;
  color: var(--entropia-color-danger);
}

.text-muted {
  color: var(--entropia-ink-muted) !important;
}

.not-found-card {
  max-width: 560px;
  margin: 48px auto;
  text-align: left;
}

.page-stack {
  display: grid;
  gap: 16px;
}

.panel-card {
  background: linear-gradient(180deg, var(--entropia-surface-raised) 0%, var(--entropia-surface-alt) 100%);
  border: 1px solid var(--entropia-line);
  border-radius: 3px;
  box-shadow: var(--entropia-shadow-soft);
  padding: 18px;
}

.panel-card h3 {
  margin: 0 0 8px;
  font-size: 1.15rem;
  letter-spacing: -0.02em;
}

.page-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.feedback-banner {
  padding: 12px 14px;
  border-radius: 6px;
  border: 1px solid var(--entropia-line);
  background: var(--entropia-color-brand-primary-soft);
  color: var(--entropia-ink);
}

.feedback-banner.error {
  background: var(--entropia-status-danger-bg);
  border-color: var(--entropia-status-danger-border);
  color: var(--entropia-status-danger-fg);
}

.empty-state-card {
  background: linear-gradient(180deg, var(--entropia-surface-raised) 0%, var(--entropia-surface-alt) 100%);
  border: 1px dashed var(--entropia-line-strong);
  border-radius: 3px;
  padding: 24px;
  text-align: center;
  color: var(--entropia-ink-muted);
}

.table {
  width: 100%;
  border-collapse: collapse;
  background: var(--entropia-surface-raised);
  overflow: hidden;
}

.table thead th {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--entropia-ink-muted);
  background: var(--entropia-color-brand-primary-soft);
  padding: 12px 14px;
  border-bottom: 1px solid var(--entropia-line);
}

.table tbody td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--entropia-color-line);
  vertical-align: top;
}

.table tbody tr:hover {
  /* Brand primary tinted at ~4% strength — softer than the solid soft token, which is
     designed as a chip background, not a row-hover wash. */
  background: rgba(37, 99, 235, 0.04);
}

.table-sm thead th,
.table-sm tbody td {
  padding-top: 10px;
  padding-bottom: 10px;
}

.table-bordered,
.table-bordered th,
.table-bordered td {
  border: 1px solid var(--entropia-line);
}

.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px 10px;
  border-radius: 3px;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.nav-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 6px;
  margin: 0;
  list-style: none;
  border: 1px solid var(--entropia-line);
  border-radius: var(--entropia-radius);
  background: linear-gradient(180deg, var(--entropia-color-brand-primary-soft) 0%, var(--entropia-color-surface-sunken) 100%);
}

.nav-tabs .nav-item {
  list-style: none;
}

.nav-tabs .nav-link {
  border: 1px solid transparent;
  border-radius: var(--entropia-radius);
  background: transparent;
  color: var(--entropia-ink-muted);
  padding: 10px 14px;
  font-weight: 600;
}

.nav-tabs .nav-link.active {
  background: var(--entropia-surface-raised);
  border-color: var(--entropia-line);
  color: var(--entropia-ink);
  box-shadow: var(--entropia-shadow-soft);
}

.modal-content {
  border: 1px solid var(--entropia-line);
  border-radius: var(--entropia-radius);
  box-shadow: var(--entropia-shadow-hard);
}

.modal-header,
.modal-footer {
  border-color: var(--entropia-line);
}

.btn-close {
  border: 0;
  background: transparent;
}

.bg-danger {
  background: var(--entropia-status-danger-bg);
  color: var(--entropia-status-danger-fg);
  border-color: var(--entropia-status-danger-border);
}

.bg-warning {
  background: var(--entropia-status-warning-bg);
  color: var(--entropia-status-warning-fg);
  border-color: var(--entropia-status-warning-border);
}

.bg-info {
  background: var(--entropia-status-info-bg);
  color: var(--entropia-status-info-fg);
  border-color: var(--entropia-status-info-border);
}

.bg-success {
  background: var(--entropia-status-success-bg);
  color: var(--entropia-status-success-fg);
  border-color: var(--entropia-status-success-border);
}

.bg-blocked {
  background: var(--entropia-status-blocked-bg);
  color: var(--entropia-status-blocked-fg);
  border-color: var(--entropia-status-blocked-border);
}

.bg-secondary {
  background: var(--entropia-status-neutral-bg);
  color: var(--entropia-status-neutral-fg);
  border-color: var(--entropia-status-neutral-border);
}

.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-danger {
  background: transparent;
  box-shadow: none;
}

.btn-outline-primary {
  border: 1px solid var(--entropia-color-brand-primary-border);
  color: var(--entropia-primary);
}

.btn-outline-secondary {
  border: 1px solid var(--entropia-line);
  color: var(--entropia-ink);
}

.btn-outline-danger {
  border: 1px solid var(--entropia-status-danger-border);
  color: var(--entropia-status-danger-fg);
}

.inline-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

.field-grid {
  display: grid;
  gap: 12px;
}

.field-grid.two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.form-check {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--entropia-line);
  border-radius: var(--entropia-radius);
  background: var(--entropia-surface-raised);
}

.metric-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
}

/* Reconciliation wizard step indicator — a horizontal numbered list of the four
   steps (Review -> Direction -> Preview -> Confirm). The active step is
   highlighted; the rest are muted so the operator can see where they are. */
.step-indicator {
  list-style: none;
  display: flex;
  gap: 8px;
  padding: 0;
  margin: 0 0 16px;
  counter-reset: step;
}
.step-indicator li {
  counter-increment: step;
  font-size: 0.85rem;
  color: var(--entropia-muted, #6b7280);
  padding: 4px 10px 4px 28px;
  position: relative;
  border-radius: 999px;
  background: var(--entropia-surface-alt, #f3f4f6);
}
.step-indicator li::before {
  content: counter(step);
  position: absolute;
  left: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  line-height: 16px;
  text-align: center;
  border-radius: 50%;
  background: var(--entropia-line, #d1d5db);
  color: var(--entropia-color-on-brand);
  font-size: 0.7rem;
}
.step-indicator li.active {
  color: var(--entropia-text, var(--entropia-color-ink));
  background: var(--entropia-accent-soft, #dbeafe);
  font-weight: 600;
}
.step-indicator li.active::before {
  background: var(--entropia-accent, var(--entropia-color-brand-primary));
}

.metric-tile {
  background: linear-gradient(180deg, var(--entropia-surface-raised) 0%, var(--entropia-surface-alt) 100%);
  border: 1px solid var(--entropia-line);
  border-radius: 6px;
  padding: 14px;
}

.metric-tile span {
  display: block;
  color: var(--entropia-ink-muted);
  font-size: 0.78rem;
}

.metric-tile strong {
  display: block;
  margin-top: 8px;
  font-size: 1.5rem;
}

.alert {
  padding: 12px 14px;
  border-radius: 6px;
  border: 1px solid var(--entropia-line);
}

.alert-info {
  background: var(--entropia-color-brand-primary-soft);
  color: var(--entropia-color-brand-primary-strong);
}

.form-select {
  box-sizing: border-box;
  width: 100%;
  margin-top: 8px;
  border: 1px solid var(--entropia-line-strong);
  background: var(--entropia-surface-raised);
  color: var(--entropia-ink);
  border-radius: var(--entropia-radius);
  padding: 12px 14px;
  font: inherit;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.7);
}

.lead {
  color: var(--entropia-ink-muted);
  font-size: 1rem;
  line-height: 1.6;
}

.toast-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  cursor: pointer;
  pointer-events: auto;
  animation: toast-slide-in 0.25s ease-out;
  font-size: 0.875rem;
  line-height: 1.4;
}

.toast-icon {
  flex-shrink: 0;
  font-size: 1.1rem;
  line-height: 1;
  margin-top: 1px;
}

.toast-message {
  flex: 1;
  word-break: break-word;
}

.toast-close {
  flex-shrink: 0;
  background: none;
  border: none;
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0.5;
  padding: 0;
  margin-top: 1px;
}

.toast-close:hover {
  opacity: 1;
}

.skeleton-row {
  display: flex;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--entropia-line);
}

.skeleton-cell {
  height: 16px;
  border-radius: 4px;
  background: linear-gradient(90deg, var(--entropia-color-surface-sunken) 25%, var(--entropia-color-line) 50%, var(--entropia-color-surface-sunken) 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.5s infinite;
  flex: 1;
}

.drawer-backdrop {
  position: fixed;
  inset: 0;
  /* Slightly cooler and denser than pure black: over a light admin surface a neutral
     scrim reads as a rendering glitch, a tinted one reads as depth. */
  background: rgba(15, 23, 42, 0.45);
  /* -webkit- prefix kept for Safari, which still ships the filter unprefixed-unsupported.
     Browsers without either simply get the scrim, which is why the alpha above is high
     enough to stand on its own. */
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  z-index: 8000;
  animation: drawer-fade-in 0.2s ease-out;
}

/* ── Card variant ──────────────────────────────────────────────────────────
   A record editor that carries every field of an entity does not fit a 45%-wide
   drawer: it forces one cramped column and a long scroll. Centred, the same form
   holds two or three columns at a readable width.

   Every geometric property of .drawer-panel is overridden explicitly rather than
   relying on the cascade — the drawer pins top/right/bottom and sets a width, and
   a half-overridden pin leaves the card anchored to one edge. */
.drawer-panel.as-card {
  top: 50%;
  left: 50%;
  right: auto;
  bottom: auto;
  transform: translate(-50%, -50%);
  width: min(var(--drawer-card-width, 1040px), calc(100vw - 48px));
  max-width: none;
  max-height: min(88vh, 940px);
  border-radius: 14px;
  box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);
  animation: drawer-card-in 0.18s ease-out;
  /* The panel is the flex column; the body inside it scrolls, not the panel, so the
     header and footer stay put while a long form moves under them. */
  overflow: hidden;
}

.drawer-panel.as-card > .drawer-header {
  position: sticky;
  top: 0;
  z-index: 1;
}

.drawer-panel.as-card > .drawer-body {
  flex: 1 1 auto;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--entropia-color-line) transparent;
  min-height: 0;          /* without this a flex child refuses to shrink and the panel grows */
}

.drawer-inline-host {
  min-width: 0;
}

.drawer-panel.inline-panel {
  position: relative;
  top: auto;
  right: auto;
  bottom: auto;
  left: auto;
  transform: none;
  width: 100%;
  max-width: none;
  max-height: none;
  min-height: 100%;
  border-radius: 18px;
  border: 1px solid var(--entropia-color-line);
  box-shadow: var(--entropia-shadow-md);
  background: linear-gradient(180deg, var(--entropia-color-surface-raised) 0%, var(--entropia-color-surface) 100%);
  overflow: hidden;
  animation: none;
}

.drawer-panel.inline-panel > .drawer-header {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 18px 20px;
  /* Keep the sticky header opaque and legible in both themes. */
  background: var(--entropia-color-surface-raised);
  color: var(--entropia-color-ink-strong);
  border-bottom: 1px solid var(--entropia-color-line);
}

.drawer-panel.inline-panel > .drawer-body {
  padding: 20px;
}
.drawer-panel.inline-panel > .drawer-footer {
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink-strong);
}

@media (min-width: 1200px) {
  .drawer-panel.inline-panel {
    max-height: calc(100vh - 32px);
    max-height: calc(100dvh - 32px);
  }

  .drawer-panel.inline-panel > .drawer-body {
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--entropia-color-line) transparent;
    min-height: 0;
  }
}

.drawer-footer {
  flex: 0 0 auto;
  padding: 12px 20px;
  border-top: 1px solid var(--entropia-color-line);
  background: var(--entropia-surface);
}
/* Below this width a centred card is worse than a full screen: the margins eat the
   form and the columns collapse anyway. */
@media (max-width: 720px) {
  .drawer-panel.as-card {
    top: 0;
    left: 0;
    transform: none;
    width: 100vw;
    max-height: 100vh;
    max-height: 100dvh;
    height: 100vh;
    height: 100dvh;
    border-radius: 0;
  }
}

@keyframes drawer-card-in {
  from { opacity: 0; transform: translate(-50%, -50%) scale(0.97); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* Motion is decoration here; the dialog is fully usable without it. */
@media (prefers-reduced-motion: reduce) {
  .drawer-backdrop,
  .drawer-panel,
  .drawer-panel.as-card {
    animation: none;
  }
}

.drawer-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 45%;
  max-width: 640px;
  background: var(--entropia-surface);
  box-shadow: -4px 0 16px rgba(0, 0, 0, 0.12);
  z-index: 8001;
  display: flex;
  flex-direction: column;
  animation: drawer-slide-in 0.25s ease-out;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--entropia-color-line) transparent;
}

.drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--entropia-line);
  position: sticky;
  top: 0;
  background: var(--entropia-surface);
  z-index: 1;
}

.drawer-body {
  padding: 20px;
  flex: 1;
}

.drawer-close {
  background: none;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
  opacity: 0.5;
  padding: 0;
  line-height: 1;
}

.drawer-close:hover {
  opacity: 1;
}

@media (max-width: 768px) {
  .drawer-panel {
    width: 100%; max-width: none;
  }
}

.entity-picker {
  position: relative;
}

.entity-picker-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 100;
  max-height: 260px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--entropia-color-line) transparent;
  background: var(--entropia-surface);
  border: 1px solid var(--entropia-line);
  border-radius: 0 0 6px 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.entity-picker-option {
  padding: 8px 12px;
  cursor: pointer;
  font-size: 0.875rem;
  border-bottom: 1px solid var(--entropia-line);
}

.entity-picker-option:hover,
.entity-picker-option.active {
  background: var(--entropia-surface-raised);
}

.entity-picker-option.selected {
  background: var(--entropia-color-brand-primary-soft);
}

.entity-picker-empty {
  padding: 12px;
  color: var(--entropia-ink-muted);
  font-size: 0.875rem;
  text-align: center;
}

.entity-picker-error {
  color: var(--entropia-danger, #dc3545);
}

.filter-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 0;
}

.filter-bar .filter-search {
  flex: 1;
  min-width: 200px;
}

.filter-bar .filter-select {
  width: auto;
  min-width: 140px;
}

.filter-bar .filter-clear {
  white-space: nowrap;
}

.filter-active-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  border-radius: 10px;
  background: var(--entropia-primary);
  color: var(--entropia-color-on-brand);
  font-size: 0.7rem;
  font-weight: 600;
  padding: 0 6px;
}


.field-help-label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.875rem;
  font-weight: 500;
  margin-bottom: 4px;
}

.field-help-tooltip {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--entropia-color-ink-muted);
  color: var(--entropia-color-surface);
  font-size: 0.65rem;
  cursor: help;
}

.field-help-tooltip:hover .field-help-tooltip-text {
  display: block;
}

.field-help-tooltip-text {
  display: none;
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  /* Inverted against the page in both themes. `ink-strong` was wrong here: it is
     #14100B in light but var(--entropia-color-surface-raised) in dark, which made this white-on-white. */
  background: var(--entropia-color-ink);
  color: var(--entropia-color-surface);
  padding: 6px 10px;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 400;
  white-space: nowrap;
  z-index: 200;
  margin-bottom: 4px;
}

.field-help-hint {
  font-size: 0.75rem;
  color: var(--entropia-ink-muted);
  margin-top: 3px;
}

.scan-input-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.scan-input-wrapper .form-control {
  padding-left: 36px;
}

.scan-input-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 1rem;
  opacity: 0.4;
  pointer-events: none;
}

.scan-input-wrapper.scanning .scan-input-icon {
  opacity: 1;
  color: var(--entropia-primary);
  animation: scan-pulse 0.6s infinite;
}

.confirm-dialog-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: drawer-fade-in 0.2s ease-out;
}

.confirm-dialog {
  background: var(--entropia-surface);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
  max-width: 440px;
  width: 90%;
  padding: 24px;
}

.confirm-dialog-title {
  font-size: 1.1rem;
  font-weight: 600;
  margin-bottom: 8px;
}

.confirm-dialog-message {
  color: var(--entropia-ink-muted);
  margin-bottom: 20px;
  line-height: 1.5;
}

.confirm-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
@media (max-width: 768px) {
}

#components-reconnect-modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  align-items: center;
  justify-content: center;
  background: rgba(9, 28, 56, 0.45);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
  display: flex;
}

#components-reconnect-modal .reconnect-card {
  max-width: 26rem;
  padding: 1.5rem 1.75rem;
  border: 1px solid var(--entropia-line);
  border-radius: var(--entropia-radius-lg);
  background: var(--entropia-surface-raised);
  box-shadow: var(--entropia-shadow-hard);
  color: var(--entropia-ink);
  text-align: center;
}

#components-reconnect-modal .reconnect-card p {
  display: none;
  margin: 0;
  line-height: 1.5;
}

#components-reconnect-modal.components-reconnect-show .reconnect-retrying,
#components-reconnect-modal.components-reconnect-failed .reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected .reconnect-rejected {
  display: block;
}

#components-reconnect-modal button {
  margin-top: 0.85rem;
  padding: 0.5rem 1.1rem;
  border: 0;
  border-radius: var(--entropia-radius);
  background: var(--entropia-primary);
  color: var(--entropia-color-on-brand);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

#components-reconnect-modal button:hover,
#components-reconnect-modal button:focus-visible {
  background: var(--entropia-primary-strong);
}

.field-warning {
  margin: -0.35rem 0 0.85rem;
  padding: 0.6rem 0.75rem;
  border-left: 3px solid var(--entropia-status-warning-fg);
  border-radius: 0 var(--entropia-radius) var(--entropia-radius) 0;
  background: var(--entropia-status-warning-bg);
  color: var(--entropia-status-warning-fg);
  font-size: 0.85rem;
  line-height: 1.45;
}

.field-warning code {
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
  background: var(--entropia-status-warning-bg);
  font-size: 0.82rem;
}

@media (max-width: 1024px) and (min-width: 769px) {
}

.field-grid .btn {
  min-height: 44px;
  min-width: 44px;
}

.field-help-hint,
.lead,
.operate-task-progress,
.confirm-dialog-message,
.object-search-status {
  color: var(--entropia-ink);
}

@media (prefers-reduced-motion: reduce) {
  .toast-item,
  .drawer-panel,
  .confirm-dialog-backdrop,
  .skeleton-cell {
    animation: none !important;
    transition: none !important;
  }
}

.drawer-panel:focus-visible,
.confirm-dialog:focus-visible {
  outline: 3px solid var(--entropia-primary);
  outline-offset: 2px;
}

.form-control,
.form-select,
.pager-actions button {
  min-height: var(--entropia-dimen-touch-min);
}

.toast-close,

/* ----------------------------------------------------------------------------
 * Industrial override pass — square, flat, white/black/blue only.
 * -------------------------------------------------------------------------- */
.panel-card,
.empty-state-card,
.table,
.nav-tabs,
.modal-content,
.drawer-panel,
.confirm-card,
.confirm-dialog,
.toast,
.status-chip,
.workflow-ribbon,
.operate-column,
.operate-task-card,
.operate-scan-hint,
#components-reconnect-modal .reconnect-card,
#components-reconnect-modal button,
.field-warning,
.field-warning code {
  border-radius: 0 !important;
}

.panel-card,
.empty-state-card {
  background: var(--entropia-color-surface-raised) !important;
  box-shadow: var(--entropia-shadow-sm) !important;
}

.feedback-banner {
  border-radius: 0 !important;
  background: var(--entropia-color-info-soft) !important;
  border-color: var(--entropia-status-info-border) !important;
  color: var(--entropia-status-info-fg) !important;
}

.table thead th {
  background: var(--entropia-color-surface-sunken) !important;
}

.nav-tabs {
  background: var(--entropia-color-surface-sunken) !important;
}

.nav-tabs .nav-link.active {
  background: var(--entropia-color-surface-raised) !important;
  box-shadow: none !important;
}

.operate-scan-bar {
  background: linear-gradient(90deg, #1E293B 0%, #334155 100%) !important;
  box-shadow: none !important;
  border-radius: 0 !important;
}

.operate-column {
  background: var(--entropia-color-surface-raised) !important;
}

.operate-task-card {
  background: var(--entropia-color-surface-raised) !important;
  box-shadow: none !important;
}

.operate-task-card.is-active {
  background: var(--entropia-color-info-soft) !important;
}

.operate-task-card.is-high {
  border-left-width: 2px !important;
}

.operate-scan-hint {
  background: var(--entropia-color-info-soft) !important;
  color: var(--entropia-color-info) !important;
}
.drawer-close,
.pager-actions button {
  min-width: var(--entropia-dimen-touch-min);
}
/* ----------------------------------------------------------------------------
 * 6. User menu and modal shell
 *
 * These never had rules in either the old or the new sheet. UserMenu was
 * unreachable until now (only Topbar.razor referenced it, and nothing renders
 * Topbar), so nobody saw that its popover was an unstyled inline block that
 * pushed the header around instead of floating over the page.
 *
 * The .modal family is Bootstrap's vocabulary, but Bootstrap is not shipped, so
 * the layout properties it normally supplies are supplied here. Both consumers
 * (UserMenu, Reports) render the element only while open, so a permanently
 * visible overlay is correct — there is no hidden default state to preserve.
 * -------------------------------------------------------------------------- */

.user-menu {
  position: relative;
  display: inline-flex;
}

.user-menu-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--entropia-space-sm);
  height: 32px;
  padding: 0 var(--entropia-space-md);
  border: 1px solid transparent;
  border-radius: var(--entropia-radius-md);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

.user-menu-trigger:hover {
  background: var(--entropia-color-surface-sunken);
  border-color: var(--entropia-color-line);
}

.user-menu-trigger:focus-visible {
  outline: none;
  border-color: var(--entropia-color-brand-primary);
  box-shadow: var(--entropia-shadow-focus);
}

.user-menu-name {
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-menu-chevron {
  font-size: 10px;
  color: var(--entropia-color-ink-soft);
}

/* Anchored to the trigger's right edge: the menu sits at the end of the topbar,
   so opening it leftward keeps it on screen at narrow widths. */
.user-menu-popover {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: var(--entropia-z-dropdown);
  min-width: 220px;
  padding: var(--entropia-space-xs);
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-lg);
  background: var(--entropia-color-surface-raised);
  box-shadow: var(--entropia-shadow-lg);
}

.user-menu-item {
  display: block;
  width: 100%;
  padding: var(--entropia-space-sm) var(--entropia-space-md);
  border: 0;
  border-radius: var(--entropia-radius-md);
  background: transparent;
  color: var(--entropia-color-ink);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}

.user-menu-item:hover {
  background: var(--entropia-color-brand-primary-soft);
  color: var(--entropia-color-brand-primary);
}

.user-menu-item:focus-visible {
  outline: 2px solid var(--entropia-color-brand-primary);
  outline-offset: -2px;
}

/* ── Modal shell ── */

.modal {
  position: fixed;
  inset: 0;
  z-index: var(--entropia-z-modal);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--entropia-space-xl);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--entropia-color-line) transparent;
  background: rgba(15, 23, 42, 0.45);
}

/* `d-block` is Bootstrap's and has no rule here; both call sites pair it with
   .modal. Pinned so adding a real d-block utility later cannot un-centre these. */
.modal.d-block {
  display: flex;
}

.modal-dialog {
  width: 100%;
  max-width: 480px;
  margin: auto;
}

.modal-content {
  display: flex;
  flex-direction: column;
  background: var(--entropia-color-surface-raised);
  color: var(--entropia-color-ink);
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--entropia-space-md);
  padding: var(--entropia-space-lg) var(--entropia-space-xl);
  border-bottom: 1px solid var(--entropia-color-line);
}

.modal-title {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}

.modal-body {
  padding: var(--entropia-space-xl);
}

.modal-body label {
  display: block;
  margin-bottom: var(--entropia-space-xs);
  font-size: var(--entropia-type-caption-size);
  font-weight: 500;
  color: var(--entropia-color-ink-muted);
}

.modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--entropia-space-sm);
  padding: var(--entropia-space-lg) var(--entropia-space-xl);
  border-top: 1px solid var(--entropia-color-line);
}

/* The markup renders this button empty — Bootstrap draws the glyph with a
   background image it no longer has, so supply the mark here or it is a
   zero-content button the operator cannot see. */
.btn-close {
  width: 28px;
  height: 28px;
  padding: 0;
  border-radius: var(--entropia-radius-md);
  color: var(--entropia-color-ink-muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.btn-close::before {
  content: "\00D7";
}

.btn-close:hover {
  background: var(--entropia-color-surface-sunken);
  color: var(--entropia-color-ink);
}

.btn-close:focus-visible {
  outline: 2px solid var(--entropia-color-brand-primary);
  outline-offset: 2px;
}

/* Enrolment secret — monospace so an operator transcribing it into an
   authenticator can tell 0 from O and 1 from l. */
.mfa-secret {
  margin: 0 0 var(--entropia-space-md);
  padding: var(--entropia-space-md);
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-md);
  background: var(--entropia-color-surface-sunken);
  color: var(--entropia-color-ink);
  font-family: var(--entropia-font-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  white-space: pre-wrap;
  word-break: break-all;
}

/* ----------------------------------------------------------------------------
 * 7. Bootstrap utility subset
 *
 * The markup uses Bootstrap's utility vocabulary in 69 of 107 components, but
 * Bootstrap has never been shipped and the pre-redesign sheet did not define
 * these either (verified against a9eec23: zero hits for mt-2, d-flex, col-sm-5,
 * form-control-sm and the rest). So unlike section 5 this is not restoration —
 * these have been inert since the markup was written, which is why spacing
 * collapsed and every d-flex row stacked vertically.
 *
 * Only the classes the markup actually uses are defined, on the token scale
 * rather than Bootstrap's rem values, so spacing matches the rest of the system.
 * Bootstrap step to token: 1=xs(4) 2=sm(8) 3=lg(16) 4=xl(24).
 * -------------------------------------------------------------------------- */

.m-0  { margin: 0; }
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: var(--entropia-space-xs); }
.mt-2 { margin-top: var(--entropia-space-sm); }
.mt-3 { margin-top: var(--entropia-space-lg); }
.mt-4 { margin-top: var(--entropia-space-xl); }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: var(--entropia-space-xs); }
.mb-2 { margin-bottom: var(--entropia-space-sm); }
.mb-3 { margin-bottom: var(--entropia-space-lg); }
.mb-4 { margin-bottom: var(--entropia-space-xl); }
.ms-1 { margin-left: var(--entropia-space-xs); }
.ms-2 { margin-left: var(--entropia-space-sm); }
.me-1 { margin-right: var(--entropia-space-xs); }
.me-2 { margin-right: var(--entropia-space-sm); }
.my-3 { margin-top: var(--entropia-space-lg); margin-bottom: var(--entropia-space-lg); }
.p-2  { padding: var(--entropia-space-sm); }
.p-3  { padding: var(--entropia-space-lg); }

.d-flex   { display: flex; }
.d-none   { display: none; }
.gap-2, .g-2 { gap: var(--entropia-space-sm); }
.g-1      { gap: var(--entropia-space-xs); }
.align-items-start  { align-items: flex-start; }
.align-items-center { align-items: center; }
.align-items-end    { align-items: flex-end; }
.justify-content-between { justify-content: space-between; }
.w-100 { width: 100%; }
.h-100 { height: 100%; }
.position-relative { position: relative; }
.position-absolute { position: absolute; }
.align-middle { vertical-align: middle; }

/* Columns. site.css:391 already makes .row a flex container with a gap, so each
   basis subtracts that gap to keep twelve columns on one line; wrapping is
   enabled because a fixed-basis child in a nowrap flex row overflows instead. */
.row { flex-wrap: wrap; }

[class*="col-sm-"], [class*="col-md-"], [class*="col-lg-"] {
  flex: 0 1 auto;
  box-sizing: border-box;
}

.col-md-1  { flex-basis: calc(8.3333% - var(--entropia-space-md)); }
.col-md-2  { flex-basis: calc(16.6667% - var(--entropia-space-md)); }
.col-md-3  { flex-basis: calc(25% - var(--entropia-space-md)); }
.col-md-4, .col-sm-4 { flex-basis: calc(33.3333% - var(--entropia-space-md)); }
.col-sm-5, .col-md-5 { flex-basis: calc(41.6667% - var(--entropia-space-md)); }
.col-md-6  { flex-basis: calc(50% - var(--entropia-space-md)); }
.col-sm-7, .col-md-7 { flex-basis: calc(58.3333% - var(--entropia-space-md)); }

.row-cols-1    { display: grid; grid-template-columns: 1fr; gap: var(--entropia-space-lg); }
.row-cols-md-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--entropia-space-lg); }
.row-cols-lg-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--entropia-space-lg); }

@media (max-width: 900px) {
  .row-cols-md-2, .row-cols-lg-3 { grid-template-columns: 1fr; }
  [class*="col-sm-"], [class*="col-md-"] { flex-basis: 100%; }
}

/* ── Text and semantic colour ── */

.small, small { font-size: 0.875em; }
.text-center  { text-align: center; }
.text-muted   { color: var(--entropia-color-ink-muted); }
.text-dark    { color: var(--entropia-color-ink-strong); }
.text-danger  { color: var(--entropia-status-danger-fg); }
.text-warning { color: var(--entropia-status-warning-fg); }
.text-info    { color: var(--entropia-status-info-fg); }
.font-mono {
  font-family: var(--entropia-font-mono);
}

.bg-light { background: var(--entropia-color-surface-sunken); }
.border   { border: 1px solid var(--entropia-color-line); }
.rounded  { border-radius: var(--entropia-radius-md); }

/* ── Remaining button variants ──
   These fell through to the bare .btn, so a destructive outline button was
   pixel-identical to a neutral one. */

.btn-secondary {
  background: var(--entropia-color-ink-muted);
  border-color: var(--entropia-color-ink-muted);
  color: var(--entropia-color-surface);
}
.btn-success {
  background: var(--entropia-color-success);
  border-color: var(--entropia-color-success);
  color: var(--entropia-color-surface-raised);
}
.btn-warning {
  background: var(--entropia-status-warning-bg);
  border-color: var(--entropia-status-warning-border);
  color: var(--entropia-status-warning-fg);
}
.btn-outline-success {
  background: transparent;
  border-color: var(--entropia-status-success-border);
  color: var(--entropia-status-success-fg);
}
.btn-outline-info {
  background: transparent;
  border-color: var(--entropia-status-info-border);
  color: var(--entropia-status-info-fg);
}
.btn-outline-success:hover { background: var(--entropia-status-success-bg); }
.btn-outline-info:hover    { background: var(--entropia-status-info-bg); }

.alert-warning {
  border-color: var(--entropia-status-warning-border);
  background: var(--entropia-status-warning-bg);
  color: var(--entropia-status-warning-fg);
}

/* ── Form controls Bootstrap was expected to supply ──
   .form-control-sm is the most-used unstyled class in the app (88 uses across
   24 files) and rendered as a raw OS box beside token-styled fields. */

.form-control-sm,
.form-select-sm {
  box-sizing: border-box;
  width: 100%;
  height: 30px;
  padding: 0 var(--entropia-space-sm);
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-md);
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink);
  font: inherit;
  font-size: 12px;
}

.form-control-sm:focus,
.form-select-sm:focus {
  outline: none;
  border-color: var(--entropia-color-brand-primary);
  box-shadow: var(--entropia-shadow-focus);
}

.form-label {
  display: block;
  margin-bottom: var(--entropia-space-xs);
  font-size: var(--entropia-type-caption-size);
  font-weight: 500;
  color: var(--entropia-color-ink-muted);
}

.form-check-input { margin: 0; flex: 0 0 auto; }
.form-check-label { cursor: pointer; font-size: 13px; }

.form-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--entropia-space-md);
  align-items: flex-end;
}

.form-input {
  box-sizing: border-box;
  width: 100%;
  height: var(--entropia-dimen-button-height);
  padding: 0 var(--entropia-space-md);
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-md);
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink);
  font: inherit;
  font-size: 13px;
}

.form-input:focus {
  outline: none;
  border-color: var(--entropia-color-brand-primary);
  box-shadow: var(--entropia-shadow-focus);
}

/* Three-column variant of the restored .field-grid, and its span modifier. */
.field-grid.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.field-span-2 { grid-column: span 2; }

/* Selection column in DataTable. Missed by the section-5 restore because its
   old rule was `.data-table .row-checkbox` — a nested selector, so the
   top-level scan that built the restore list never saw the class. */
.row-checkbox { width: 36px; text-align: center; }

/* ── Toast severities ──
   ToastContainer emits toast-@Severity, so three of the four variants had no
   rule and every toast rendered identically regardless of outcome. */
.toast-error {
  border-left: 3px solid var(--entropia-status-danger-fg);
  background: var(--entropia-status-danger-bg);
  color: var(--entropia-status-danger-fg);
}
.toast-warning {
  border-left: 3px solid var(--entropia-status-warning-fg);
  background: var(--entropia-status-warning-bg);
  color: var(--entropia-status-warning-fg);
}
.toast-info {
  border-left: 3px solid var(--entropia-status-info-fg);
  background: var(--entropia-status-info-bg);
  color: var(--entropia-status-info-fg);
}

/* ── Nav / list-group ── */

.nav { display: flex; gap: var(--entropia-space-xs); list-style: none; margin: 0; padding: 0; }
.nav-pills .nav-link { border-radius: var(--entropia-radius-md); }

.list-group {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-md);
  overflow: hidden;
}
.list-group-item {
  padding: var(--entropia-space-md);
  background: var(--entropia-color-surface);
  border-bottom: 1px solid var(--entropia-color-line);
}
.list-group-item:last-child { border-bottom: 0; }
.list-group-item-action { cursor: pointer; }
.list-group-item-action:hover { background: var(--entropia-color-surface-sunken); }

.card-title { margin: 0 0 var(--entropia-space-xs); font-size: 14px; font-weight: 600; }
.card-text  { margin: 0; color: var(--entropia-color-ink-muted); font-size: 13px; }

/* ── Remaining page-local classes ── */

.deploy-actions,
.qr-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--entropia-space-sm);
  align-items: center;
}

.code-block,
.enrollment-code,
.license-details {
  padding: var(--entropia-space-md);
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-md);
  background: var(--entropia-color-surface-sunken);
  font-family: var(--entropia-font-mono);
  font-size: 13px;
  white-space: pre-wrap;
  word-break: break-word;
}

.checklist, .legacy-report-list { margin: 0; padding-left: var(--entropia-space-lg); }
.checklist li, .legacy-report-list li { margin-bottom: var(--entropia-space-xs); }

.scan-note { font-size: 12px; color: var(--entropia-color-ink-soft); }

.pda-limit-badge {
  display: inline-block;
  padding: 0 var(--entropia-space-sm);
  border: 1px solid var(--entropia-status-warning-border);
  border-radius: 999px;
  background: var(--entropia-status-warning-bg);
  color: var(--entropia-status-warning-fg);
  font-size: 11px;
}

.empty-state-icon { font-size: 28px; color: var(--entropia-color-ink-soft); }
.entity-picker-scan-message { font-size: 12px; color: var(--entropia-color-ink-muted); }
.confirm-body { padding: var(--entropia-space-md) 0; }

.stepper { display: flex; flex-wrap: wrap; gap: var(--entropia-space-sm); align-items: center; }

.error-shell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--entropia-space-md);
  min-height: 60vh;
  text-align: center;
}
.error-mark { font-size: 40px; color: var(--entropia-status-danger-fg); }

/* Printable workstation setup sheet. */
.setup-sheet {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--entropia-space-xl);
  border: 1px solid var(--entropia-color-line);
  border-radius: var(--entropia-radius-lg);
  background: var(--entropia-color-surface);
}
.setup-sheet-steps { padding-left: var(--entropia-space-lg); }
.setup-sheet-facts { display: grid; gap: var(--entropia-space-sm); margin: var(--entropia-space-lg) 0; }
.setup-sheet-code {
  font-family: var(--entropia-font-mono);
  font-size: 15px;
  letter-spacing: 0.12em;
}

@media print {
  .no-print, .setup-sheet-hide-on-print { display: none !important; }
}

/* ----------------------------------------------------------------------------
 * 8. Toast stack
 *
 * ToastContainer renders two live regions (assertive for errors, polite for the
 * rest) and site.css pins `.toast-container` to `position: fixed; right: 24px;
 * bottom: 24px`. Both therefore occupied the same coordinates, so an error and a
 * success toast on screen together rendered on top of one another.
 *
 * The regions are now nested in a single positioned stack; they keep their
 * separate aria-live semantics and simply flow, errors nearest the bottom.
 * -------------------------------------------------------------------------- */

.toast-stack {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: var(--entropia-z-toast);
  display: flex;
  flex-direction: column-reverse;
  gap: var(--entropia-space-sm);
  pointer-events: none;
}

.toast-stack .toast-container {
  position: static;
  right: auto;
  bottom: auto;
}

.toast-stack .toast-item {
  pointer-events: auto;
}

/* Success variant of the card primitive. License.razor marks its confirmation
   panel `card success`; the rule used to live in that page's unscoped <style>
   block, which also re-skinned the global .card for every page that happened to
   be mounted. Scoped to the compound selector here instead. */
.card.success {
  border-color: var(--entropia-status-success-border);
  background: var(--entropia-status-success-bg);
  color: var(--entropia-status-success-fg);
}

/* ----------------------------------------------------------------------------
 * 9. Navigation rail — collapsed state, and readability over a long shift
 *
 * COLLAPSE WAS BROKEN. `.app-layout-rail-collapsed` only narrowed the grid column
 * from 256px to 64px; nothing hid the labels. The text simply reflowed into a
 * 64px column and clipped, so the "collapsed" rail read as a stack of broken
 * fragments — "Co Ce", "W qu", "Ex", "Cr do" — with the brand, the user footer
 * and the language select squashed alongside. Collapsing has to actually reduce
 * the rail to icons, which is what the rules below do.
 *
 * READABILITY. The section headings ran at 11px in rail-text-muted (#8A7A6A) on
 * the #241B14 rail — roughly 3.1:1, under the 4.5:1 needed for text that small.
 * They are the only thing grouping 46 links, so the one element responsible for
 * making the list scannable was the hardest thing in it to read. Muted is lifted
 * to #B5A28C (~5.3:1) and each group gets a hairline rule, so the eye can find
 * a section by its break rather than by decoding tiny low-contrast type.
 * -------------------------------------------------------------------------- */

/* ── Collapsed: icons only ── */

.app-layout-rail-collapsed .sidebar-brand-text,
.app-layout-rail-collapsed .sidebar-section-title,
.app-layout-rail-collapsed .nav-label,
.app-layout-rail-collapsed .nav-badge,
.app-layout-rail-collapsed .sidebar-user-info,
.app-layout-rail-collapsed .sidebar-footer select,
.app-layout-rail-collapsed .sidebar-footer .input {
  display: none;
}

.app-layout-rail-collapsed .sidebar-brand,
.app-layout-rail-collapsed .sidebar-user {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
  gap: 0;
}

.app-layout-rail-collapsed .nav-item a {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
  gap: 0;
}

/* The icon is the only affordance left, so give it a real target and keep the
   row height identical to the expanded state — collapsing should not make the
   list jump. */
.app-layout-rail-collapsed .nav-icon {
  width: 20px;
  height: 20px;
}

.app-layout-rail-collapsed .sidebar-section {
  padding-left: var(--entropia-space-xs);
  padding-right: var(--entropia-space-xs);
}

/* Section boundaries survive collapse as a rule, since the headings are gone. */
.app-layout-rail-collapsed .nav-list + .sidebar-section-title,
.app-layout-rail-collapsed .nav-list {
  position: relative;
}

.app-layout-rail-collapsed .nav-list:not(:first-of-type)::before {
  content: "";
  display: block;
  height: 1px;
  margin: var(--entropia-space-sm) var(--entropia-space-sm);
  background: var(--entropia-color-rail-divider);
}

/* ── Readability in both states ── */

/* Was #A89580 on #160F0A (~3.1:1) at 11px. */
.sidebar-section-title {
  color: #C9B9A0;
  font-size: 11px;
  letter-spacing: 0.08em;
}

/* A rule above each group gives the eye a boundary that does not depend on
   reading 11px uppercase text. */
.nav-list + .sidebar-section-title {
  margin-top: var(--entropia-space-md);
  padding-top: var(--entropia-space-md);
  border-top: 1px solid var(--entropia-color-rail-divider);
}

/* Idle rows sit slightly back so the active row and hover carry the emphasis,
   instead of 46 rows all competing at full strength. */
.nav-item a {
  color: #D9C9B0;
}

.nav-item a:hover {
  color: var(--entropia-color-rail-text-strong);
}

/* The active row is the anchor: a coral fill with a brighter leading edge, so it
   is findable in peripheral vision without scanning the whole list. */
.nav-item a.active {
  box-shadow: inset 3px 0 0 var(--entropia-color-brand-primary-border);
  font-weight: 600;
}

.app-layout-rail-collapsed .nav-item a.active {
  box-shadow: none;
  outline: 1px solid var(--entropia-color-brand-primary-border);
  outline-offset: -1px;
}

/* The rail scrolls independently; a hairline keeps its edge from vibrating
   against the light canvas at the seam. */
.sidebar {
  border-right: 1px solid var(--entropia-color-rail-divider);
}

/* Custom scrollbar — the default light-on-dark bar is a bright stripe down the
   side of an otherwise dark column. */
.sidebar-section::-webkit-scrollbar { width: 8px; }
.sidebar-section::-webkit-scrollbar-track { background: transparent; }
.sidebar-section::-webkit-scrollbar-thumb {
  background: var(--entropia-color-rail-bg-hover);
  border-radius: 999px;
}
.sidebar-section::-webkit-scrollbar-thumb:hover { background: #6E5640; }
.sidebar-section { scrollbar-width: thin; scrollbar-color: var(--entropia-color-rail-bg-hover) transparent; }

/* ----------------------------------------------------------------------------
 * 10. Navigation icons — the dark-on-dark bug
 *
 * The rail icons were invisible: black strokes on a #241B14 (light theme) or
 * #160F0A (dark theme) rail, about 1.2:1. Collapsed, where the icons are the
 * only thing left, the rail read as an empty dark strip.
 *
 * Cause: the SVGs draw with stroke="currentColor", but the markup loads them as
 * <img src="...">. An <img> renders the SVG as a separate, isolated document, so
 * currentColor has no inherited value and resolves to its initial value, black.
 * site.css's `.nav-icon { color: ... }` cannot cross the <img> boundary, so it
 * had no effect at all — the icons were never the rail's ink colour.
 *
 * A filter is the only thing that can recolour an <img>, short of inlining every
 * SVG. `brightness(0)` flattens the artwork to black whatever it started as, and
 * `invert(1)` then lifts it to white — so this works regardless of what fill a
 * future icon ships with. Opacity carries the idle/hover/active hierarchy.
 * -------------------------------------------------------------------------- */

.nav-icon {
  filter: brightness(0) invert(1);
  opacity: 0.7;
  transition: opacity var(--entropia-duration-fast) var(--entropia-ease);
}

.nav-item a:hover .nav-icon {
  opacity: 1;
}

.nav-item a.active .nav-icon {
  opacity: 1;
}

/* Collapsed, the icon is the only affordance, so none of them are dimmed. */
.app-layout-rail-collapsed .nav-icon {
  opacity: 0.9;
}

.app-layout-rail-collapsed .nav-item a:hover .nav-icon,
.app-layout-rail-collapsed .nav-item a.active .nav-icon {
  opacity: 1;
}

/* The active pill inverts between themes: a coral fill in light mode, a light
   coral fill in dark mode. A white icon would disappear on the latter, so the
   active icon flattens to black there instead of being inverted to white. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .nav-item a.active .nav-icon {
    filter: brightness(0);
  }
}

:root[data-theme="dark"] .nav-item a.active .nav-icon {
  filter: brightness(0);
}

/* The brand mark sits on the same coral fill and has the same problem. */
.sidebar-brand-mark img {
  filter: brightness(0) invert(1);
}

/* License summary — the seat-usage card shared by the dashboard and the admin
   settings page. Tokens only; the palette lives in tokens.generated.css. */
.license-summary-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.license-summary-head h3 {
  margin: 0;
}

.license-summary-sep {
  margin: 0 6px;
  color: var(--entropia-color-line);
}

.license-summary-seats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 12px;
  margin: 12px 0 0;
}

.license-summary-seat dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--entropia-color-ink-muted);
}

.license-summary-seat dd {
  margin: 2px 0 0;
  font-variant-numeric: tabular-nums;
  color: var(--entropia-color-ink-muted);
}

.license-summary-used {
  font-size: 20px;
  font-weight: 600;
  color: var(--entropia-color-ink);
}

/* Skeletons are inline spans elsewhere; here they stack as two lines. */
.license-summary .skeleton {
  display: block;
  margin-bottom: 8px;
}

/* Opening-credentials panel on the Users page. The same markup is the printable
   slip an operator without a mailbox is handed, so printing drops the rest of
   the page and the controls that mean nothing on paper. */
.credentials-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin: 12px 0 0;
}

.credentials-list dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--entropia-color-ink-muted);
}

.credentials-list dd {
  margin: 4px 0 0;
  display: flex;
  align-items: center;
  gap: 8px;
}

.credentials-list code {
  font-size: 16px;
  letter-spacing: 0.06em;
  -webkit-user-select: all;
  user-select: all;
}

@media print {
  body * {
    visibility: hidden;
  }

  .credentials-slip,
  .credentials-slip * {
    visibility: visible;
  }

  .credentials-slip {
    position: absolute;
    inset: 0 auto auto 0;
    width: 100%;
    box-shadow: none;
    border: 1px solid var(--entropia-color-ink, #000);
  }

  .credentials-slip-actions {
    display: none;
  }
}

/* SMTP card: what is actually sending mail, and how the configuration grades. */
.smtp-effective,
.smtp-validation {
  border: 1px solid var(--entropia-color-line);
  border-radius: 6px;
  padding: 12px;
  margin-bottom: 12px;
  background: var(--entropia-color-surface-sunken);
}

.smtp-effective-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

.smtp-effective-values {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px 12px;
  margin: 0;
}

.smtp-effective-values dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--entropia-color-ink-muted);
}

.smtp-effective-values dd {
  margin: 2px 0 0;
  font-variant-numeric: tabular-nums;
  word-break: break-word;
}

.smtp-check-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}

.smtp-check-list li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  line-height: 1.5;
}

/* One-line state header carried by every settings card. */
.settings-state {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 0 0 10px;
  line-height: 1.5;
}

/* ============================================================================
   Dark mode repair.

   site.css hardcodes the light palette in about two dozen rules — canvas,
   headings, cards, the rail, inputs, chips. Setting data-theme="dark" flips the
   tokens underneath but leaves those literals alone, so the page ended up with
   dark surfaces under dark text: nothing readable, form controls invisible, and
   no way to see what you were typing.

   These rules restate the same declarations against the tokens. They sit at the
   end of components.css, which loads after site.css, so they win on order at
   equal specificity — and because they resolve through tokens they are correct
   in BOTH themes rather than being a dark-only patch. Anything added here must
   use a var(), never a literal.
   ============================================================================ */

body {
  background: var(--entropia-color-canvas);
  color: var(--entropia-color-ink);
}

h1, h2, h3, h4, h5, h6 {
  color: var(--entropia-color-ink-strong);
}

.muted { color: var(--entropia-color-ink-muted); }
.soft { color: var(--entropia-color-ink-soft, var(--entropia-color-ink-muted)); }
.text-muted { color: var(--entropia-color-ink-muted); }

/* Surfaces ---------------------------------------------------------------- */
.card,
.panel-card,
.topbar,
.drawer-panel,
.confirm-dialog,
.empty-state-card {
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink);
  border-color: var(--entropia-color-line);
}

.topbar { border-bottom: 1px solid var(--entropia-color-line); }

/* Form controls — the ones that made the page unusable ---------------------- */
input,
select,
textarea,
.form-control,
.form-select,
.input {
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink);
  border: 1px solid var(--entropia-color-line);
}

input::placeholder,
textarea::placeholder,
.form-control::placeholder {
  color: var(--entropia-color-ink-soft, var(--entropia-color-ink-muted));
  opacity: 1;
}

input:focus,
select:focus,
textarea:focus,
.form-control:focus,
.form-select:focus {
  border-color: var(--entropia-color-brand-primary);
  outline: none;
  box-shadow: 0 0 0 3px var(--entropia-color-brand-primary-soft);
}

/* A native dropdown paints its list from the control's own colours; without
   these the options render as black-on-black once the control goes dark. */
select option {
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink);
}

input:disabled,
select:disabled,
textarea:disabled,
.form-control:disabled {
  background: var(--entropia-color-surface-sunken);
  color: var(--entropia-color-ink-muted);
}

/* Tables ------------------------------------------------------------------- */
.data-table,
table {
  color: var(--entropia-color-ink);
}

.data-table th,
.data-table td,
table th,
table td {
  border-color: var(--entropia-color-line);
}

.data-table thead th {
  color: var(--entropia-color-ink-muted);
  background: var(--entropia-color-surface-sunken);
}

.data-table tbody tr:hover {
  background: var(--entropia-color-surface-sunken);
}

/* Meme plancher confortable que la regle `.fluent-data-grid` (juste au-dessus de
  cette section — voir block-comment juste apres pour le contexte du `height`
  vs `min-height`), pour qu'un tableau natif et une grille Fluent se lisent
  pareil "partout" sur l'admin. Un <table> reel n'a pas le bogue de collision
  de classe des grilles Fluent (sa ligne grandit deja correctement avec son
  contenu) : ceci est de la coherence visuelle, pas un correctif.
  La regle visait auparavant `.data-table-scroll:not([data-dense="true"]) .data-table
  td`, un balisage de Components/Shared/DataTable.razor — composant sans appel dans
  l'app (ni ButcheryDashboard ni ExpiryRules, qui rendent des FluentDataGrid) et
  supprime au passage. On vise donc directement le balisage qui existe vraiment :
  `<table class="data-table">` (BackupSettingsCard.razor:143, ErpConnectionsCard.razor:28),
  pas enveloppe dans .data-table-scroll.
  `height` et non `min-height` : verifie dans un vrai Chromium headless (22/08) —
  `min-height` sur un <td> (display: table-cell) est un comportement NON DEFINI
  par la spec CSS pour les elements de tableau internes ; en pratique Chromium
  l'ignore purement et simplement (mesure : cellule a 19px de haut, inchangee,
  malgre min-height:48px). `height` sur un <td> se comporte lui comme un
  PLANCHER en layout de tableau — la ligne grandit encore pour un contenu plus
  haut — et produit bien 48px+bordures a la mesure. min-height ici aurait ete
  un correctif qui ne peint rien, exactement le piege signale sur .row-selected
  plus bas dans ce fichier. */
.data-table td {
  height: 48px;
}

/* Rail — background only. Its ink is deliberately left to site.css: the rail is
   espresso in BOTH themes, so routing its text through --entropia-color-ink would
   put near-black type on a near-black rail in light mode. */
.sidebar {
  background: var(--entropia-color-rail-bg);
  color: var(--entropia-color-rail-text);
}

/* Secondary button — its hover was a light-theme parchment tint ------------- */
.btn {
  background: var(--entropia-color-surface);
  color: var(--entropia-color-ink);
  border: 1px solid var(--entropia-color-line);
}

.btn:hover {
  background: var(--entropia-color-surface-sunken);
  border-color: var(--entropia-color-line-strong);
}

/* Chips: the success pair was literal, so it stayed mint-on-mint in dark ---- */
.chip-success {
  background: var(--entropia-color-success-soft);
  color: var(--entropia-color-success);
}

.chip-warning {
  background: var(--entropia-color-warning-soft);
  color: var(--entropia-color-warning);
}

.chip-danger {
  background: var(--entropia-color-danger-soft);
  color: var(--entropia-color-danger);
}

.chip-brand {
  background: var(--entropia-color-brand-primary-soft);
  color: var(--entropia-color-brand-primary);
}

.chip-info {
  background: var(--entropia-color-info-soft);
  color: var(--entropia-color-info);
}

/* CFG-01 rebuild — settings tabbed sub-structure + default hints + audit viewer.
   The group nav pane stays; inside each group, FluentTabs splits the cards into
   concern-specific tabs so a group like Policy no longer forces scrolling past
   ~30 fields. The field-default caption sits under a knob so an operator can see
   the built-in default without leaving the page. */
.settings-tabs {
  width: 100%;
}

.settings-field-default {
  display: block;
  margin-top: 2px;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

.settings-section-toolbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 12px;
}

.settings-section-toolbar .dirty-indicator {
  margin-right: auto;
  font-size: 0.8rem;
  color: var(--entropia-color-ink-muted, var(--grid-muted));
}

.audit-json {
  display: inline-block;
  max-width: 22rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
  font-size: 0.75rem;
}

.table-wrap {
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--entropia-color-line) transparent;
}

.chip-neutral {
  background: var(--entropia-color-surface-sunken);
  color: var(--entropia-color-ink-muted);
}

/* Feedback banners --------------------------------------------------------- */
.feedback-banner {
  background: var(--entropia-color-surface-sunken);
  color: var(--entropia-color-ink);
  border: 1px solid var(--entropia-color-line);
}

.feedback-banner.error {
  background: var(--entropia-color-danger-soft);
  color: var(--entropia-color-danger);
  border-color: var(--entropia-color-danger);
}

/* Anything still painting its own light surface would strand its text; these
   two keep code and preformatted blocks legible. */
code, pre {
  background: var(--entropia-color-surface-sunken);
  color: var(--entropia-color-ink);
}

/* Workflow ribbon — compact progress indicator above the page H1 ------------- */
.workflow-ribbon {
  margin-bottom: var(--bl);
  padding: 8px 12px;
  background: var(--entropia-color-surface-sunken);
  border: 1px solid var(--entropia-color-line);
  border-radius: 4px;
  font-size: 0.875rem;
}

.workflow-steps {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.workflow-steps li {
  display: flex;
  align-items: center;
  gap: 8px;
}

.workflow-steps li:not(:last-child)::after {
  content: "→";
  color: var(--entropia-color-ink-muted);
  font-size: 0.75rem;
}

.workflow-steps a {
  color: var(--entropia-color-ink);
  text-decoration: none;
  padding: 4px 8px;
  border-radius: 4px;
}

.workflow-steps a:hover {
  background: var(--entropia-color-surface-sunken);
  color: var(--entropia-color-brand-primary);
}

.workflow-steps .workflow-step-current a {
  font-weight: 600;
  background: var(--entropia-color-brand-primary-soft);
  color: var(--entropia-color-brand-primary-strong);
}

.workflow-steps .workflow-step-terminal a {
  color: var(--entropia-color-success);
}

/* Fluent UI overrides — keep the Fast components visually consistent with the
   existing palette. Only minimal overrides; the token bridge above does the
   heavy lifting. */
fluent-button[appearance="accent"] {
  --accent-fill-rest: var(--entropia-color-brand-primary);
  --accent-fill-hover: var(--entropia-color-brand-primary-strong);
  --accent-fill-active: var(--entropia-color-brand-primary-strong);
}

/* ============================================================================
 * Fluent 2 foundation — workspace grid, form sections, sticky actions
 * ==========================================================================*/

/* Master-detail workspace: 12-col grid, detail panel beside the master grid on
   wide screens, stacking below 1200px. No max-width cap — operational pages use
   the full workspace. */
.workspace-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 16px;
  align-items: start;
}

.workspace-grid > .workspace-master { grid-column: span 12; }
.workspace-grid > .workspace-detail { grid-column: span 12; }

@media (min-width: 1200px) {
  .workspace-grid > .workspace-master { grid-column: span 7; }
  .workspace-grid > .workspace-detail { grid-column: span 5; }
}

@media (min-width: 1440px) {
  .workspace-grid > .workspace-master { grid-column: span 8; }
  .workspace-grid > .workspace-detail { grid-column: span 4; }
}

/* A page whose editor moved into a centred card has no detail pane left, so the master
   must reclaim the four columns the pane used to hold — otherwise a third of the width
   sits empty and the grid keeps truncating for no reason at all. Written as :has() so a
   page gets this automatically by dropping its .workspace-detail, with nothing to
   remember and no per-page class to keep in sync. */
.workspace-grid:not(:has(> .workspace-detail)) > .workspace-master {
  grid-column: span 12;
}

@media (min-width: 1200px) {
  .workspace-grid > .workspace-detail {
    position: sticky;
    top: 16px;
    max-height: calc(100vh - 32px);
    max-height: calc(100dvh - 32px);
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--entropia-color-line) transparent;
  }
}

/* Colonnes a plancher pixel : la grille peut desormais depasser son volet.
   Sans conteneur defilant, les colonnes en fr se contentaient de retrecir --
   8 colonnes dans un volet de 8/12 tombaient a ~111px et tout se tronquait,
   en-tetes compris, sans jamais offrir de defilement. Le plancher rend la
   largeur reelle, ceci la rend atteignable.

   Cible le conteneur qui porte la grille plutot que la grille elle-meme :
   un element en display:grid ne peut pas etre son propre volet de defilement. */
:where(.panel-card, .workspace-master, .workspace-detail):has(.fluent-data-grid) {
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--entropia-color-line) transparent;
}

/* Settings nav pane + full-width form (contract §6). Narrow left nav lists the
   configuration groups; the selected group's cards render full-width on the
   right so each form gets the space it needs. Stacks below 1024px. */
.settings-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  align-items: start;
}

@media (min-width: 1024px) {
  .settings-layout {
    grid-template-columns: minmax(180px, 220px) 1fr;
  }
}

.settings-nav {
  position: sticky;
  top: 16px;
}

.settings-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.settings-nav-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 10px 12px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--entropia-color-ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.settings-nav-item:hover {
  background: var(--entropia-color-surface-alt, rgba(0, 0, 0, 0.04));
}

.settings-nav-item.active {
  background: var(--entropia-color-brand-primary-soft);
  border-color: var(--entropia-color-brand-primary-border);
  font-weight: 600;
}

.settings-nav-item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.settings-nav-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--entropia-color-surface-alt, rgba(0, 0, 0, 0.08));
  color: var(--entropia-color-ink-muted, var(--grid-muted));
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

.settings-nav-item.active .settings-nav-count {
  background: var(--accent);
  color: var(--entropia-color-on-accent, #fff);
}

.settings-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

.settings-form .panel-card {
  margin: 0;
}

.license-summary-card {
  border-top: 2px solid var(--accent);
}

/* Entity form grid — 4/3/2/1 columns by breakpoint. */
.entity-form-grid {
  display: grid;
  gap: 12px 16px;
  align-items: start;
}

.entity-form-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.entity-form-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.entity-form-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.entity-form-grid .span-2 { grid-column: span 2; }
.entity-form-grid .span-3 { grid-column: span 3; }
.entity-form-grid .span-full { grid-column: 1 / -1; }

@media (max-width: 1439px) {
  .entity-form-grid-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .entity-form-grid-4 .span-3 { grid-column: span 2; }
}

@media (max-width: 1199px) {
  .entity-form-grid-3,
  .entity-form-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .entity-form-grid .span-3 { grid-column: span 2; }
}

@media (max-width: 767px) {
  .entity-form-grid-2,
  .entity-form-grid-3,
  .entity-form-grid-4 { grid-template-columns: minmax(0, 1fr); }
  .entity-form-grid .span-2,
  .entity-form-grid .span-3 { grid-column: span 1; }
}

/* Form sections ----------------------------------------------------------- */
.form-section {
  padding: 16px 0;
  border-top: 1px solid var(--entropia-color-line);
}

.form-section:first-child { border-top: none; padding-top: 0; }

.form-section-title {
  margin: 0 0 12px;
  font-size: 0.8125rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--entropia-color-ink-muted);
}

.form-section-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 0;
  margin: 0 0 12px;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
}

.form-section-toggle .form-section-title { margin: 0; }

.form-section-chevron {
  display: inline-block;
  transition: transform 0.15s ease;
  color: var(--entropia-color-ink-muted);
}

.form-section-chevron.expanded { transform: rotate(90deg); }

/* Sticky form actions ------------------------------------------------------ */
.sticky-form-actions {
  position: sticky;
  bottom: 0;
  margin: 16px -16px -16px;
  padding: 12px 16px;
  background: var(--entropia-color-canvas);
  border-top: 1px solid var(--entropia-color-line);
  z-index: 10;
}

.sticky-form-actions-inner {
  display: flex;
  align-items: center;
  gap: 8px;
}

.sticky-form-commands {
  margin-left: auto;
  display: flex;
  gap: 8px;
}

/* Status field -------------------------------------------------------------- */
.status-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.status-field-label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--entropia-color-ink-muted);
}

/* Audit fields ---------------------------------------------------------------- */
.audit-fields {
  display: flex;
  gap: 24px;
  margin: 16px 0 0;
  padding: 12px 0 0;
  border-top: 1px solid var(--entropia-color-line);
  font-size: 0.8125rem;
  color: var(--entropia-color-ink-muted);
}

.audit-field dt { font-weight: 600; }
.audit-field dd { margin: 2px 0 0; }

/* Handoff banner (workflow CTAs) ------------------------------------------------ */
.handoff-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  background: var(--entropia-color-brand-primary-soft);
  border: 1px solid var(--entropia-color-brand-primary-border);
  border-radius: 6px;
  font-size: 0.875rem;
}

.handoff-banner .btn { margin-left: auto; }
.handoff-banner .btn-ghost { margin-left: 0; }

/* FluentDataGrid empty states -------------------------------------------------
   Several admin pages already supply EmptyContent, but the runtime can emit the
   empty row as a single collapsed table/grid cell. When that happens the content
   exists yet renders as a near-invisible sliver, which is exactly what the user
   saw on empty master grids. Force the empty row back into the grid flow and
   style it like a real "empty table" body region. */
.fluent-data-grid .empty-content-cell,
.fluent-data-grid :is(td, [role="gridcell"], .fluent-data-grid-cell):has(.empty-state-card) {
  grid-column: 1 / -1 !important;
  display: grid !important;
  place-items: center;
  width: 100% !important;
  min-height: 132px;
  padding: 24px !important;
  background: var(--entropia-color-surface);
}

.fluent-data-grid > tbody:has(.empty-content-cell),
.fluent-data-grid > tbody:has(.empty-state-card),
.fluent-data-grid tr:has(> .empty-content-cell),
.fluent-data-grid tr:has(.empty-state-card),
.fluent-data-grid-row:has(.empty-state-card) {
  display: contents !important;
}

.fluent-data-grid .empty-content-cell .empty-state-card,
.fluent-data-grid :is(td, [role="gridcell"], .fluent-data-grid-cell):has(.empty-state-card) .empty-state-card {
  width: min(100%, 560px);
  margin: 0 auto;
  box-shadow: none !important;
}

/* Ligne selectionnee sur la grille maitre. Piege verifie dans le bundle Fluent livre
   (b6pgxrrsua.bundle.scp.css, regle `.grid tr { display: contents }`, active sur TOUTE
   FluentDataGrid — correction 07/09 : l'ancien commentaire disait "des qu'un
   GridTemplateColumns est pose", c'est FAUX. La classe `grid` est posee sans condition
   par le composant des que DisplayMode vaut DataGridDisplayMode.Grid, ce qui est la
   valeur par defaut ; aucun GridTemplateColumns n'est requis) :
   un <tr> en display:contents ne genere aucune boite propre, donc un fond pose
   directement dessus ne peint RIEN, meme si le selecteur matche. Cette regle ciblait le
   <tr> depuis son ajout et n'a donc jamais rien teinte a l'ecran. On peint les
   CELLULES a la place — seules a avoir une vraie boite ; meme trio de selecteurs que
   la regle de padding/bordure juste plus bas, pour couvrir <td> classique ou
   role="gridcell" selon la colonne. */
tr.row-selected :is(td, [role="gridcell"], .fluent-data-grid-cell) {
  background: var(--entropia-color-brand-primary-soft);
}

/* ----------------------------------------------------------------------------
 * HAUTEUR DE LIGNE DES GRILLES — CAUSE REELLE (verifiee de bout en bout le 07/09).
 *
 * Symptome : toutes les grilles du back-office rendent leurs lignes a peu pres a
 * mi-hauteur — texte coupe, puces d'etat ("Peremption", "FEFO") et boutons
 * ("Confirmer") tranches.
 *
 * Arithmetique exacte, pas une hypothese :
 *   1. FluentUI 4.12.1 (FluentDataGridCell.razor.cs) pose un style INLINE `height`
 *      sur CHAQUE <td> : la valeur de RowSize hors virtualisation
 *      (DataGridRowSize.Small = 32px, le defaut) ou celle d'ItemSize en
 *      virtualisation (32f par defaut). Un style inline bat toute regle de
 *      feuille de style qui n'est pas `!important`.
 *   2. Le bundle scoped de la librairie pose `td { padding: 6px 16px;
 *      overflow: hidden; align-content: center }` et `.fluent-data-grid
 *      { align-items: center }`.
 *   3. Nos surcharges ci-dessous posaient 14px de remplissage haut ET bas plus
 *      1px de bordure sur chaque cellule (specificite 0,2,0, elle bat le 0,1,1
 *      de la librairie).
 *   4. `box-sizing: border-box` est global dans cette feuille (~ligne 122).
 *   => 32 - 14 - 14 - 1 = 3px de boite de contenu utilisable, en `overflow: hidden`
 *      et centree : une ligne de 24px, une `.chip` de 22px ou un `.btn` de 40px
 *      sont rabotes a une fente de 3px.
 *
 * Pourquoi ca se lisait "mi-hauteur" et pas "totalement tranche" : le
 * `grid-auto-rows: minmax(48px, auto)` ci-dessous (ajoute par ef08041a le
 * 22/08, qui avait mal diagnostique la cause comme une collision de classe
 * `.grid`) fait bien grandir la PISTE de la ligne a 48px, mais le
 * `align-items: center` de la librairie laisse la CELLULE a ses 32px inline au
 * milieu de cette piste.
 *
 * Le correctif tient donc en trois morceaux indissociables :
 *   a) `height: auto !important` sur la cellule — SEUL moyen de battre le style
 *      inline de la librairie ; sans le `!important` la regle est inerte.
 *   b) `align-items: stretch` sur `.fluent-data-grid.grid` pour que la cellule
 *      remplisse la piste au lieu d'y flotter centree. La specificite compte :
 *      la regle de la librairie est `.fluent-data-grid[b-ppmhrkw1mj]` = (0,2,0).
 *      Un `.fluent-data-grid` nu vaut (0,1,0) et serait silencieusement inerte ;
 *      `.fluent-data-grid.grid` vaut (0,2,0) et l'emporte par ordre de cascade
 *      (entropia.css est charge APRES le bundle de la librairie). La classe
 *      `grid` est posee sans condition sur toute FluentDataGrid.
 *   c) le plancher `grid-auto-rows: minmax(48px, auto)`, conserve tel quel.
 *
 * `min-height: 48px` sur la cellule est une ceinture-bretelles : en mode grille
 * le <tr> est en `display: contents`, donc la cellule est un ELEMENT DE GRILLE
 * (pas une `table-cell`) et `min-height` mord bien ici — contrairement au cas
 * `.data-table td` documente plus bas ou Chromium l'ignore. Ce n'est PAS la
 * piece portante : ne jamais "simplifier" en gardant `min-height` seul et en
 * retirant `height: auto !important` + `align-items: stretch`.
 * ---------------------------------------------------------------------------- */

/* Row floor: simple text rows stay comfortable; auto lets badge/input rows grow. */
.fluent-data-grid {
  --fluent-data-grid-resize-handle-color: transparent;
  grid-auto-rows: minmax(48px, auto);
}

/* Voir le bloc ci-dessus, point (b) : (0,2,0) obligatoire pour battre le
   `align-items: center` scope de la librairie. */
.fluent-data-grid.grid {
  align-items: stretch;
}

/* `height: auto !important` ici aussi, en symetrie du point (b) du bloc ci-dessus :
   `align-items: stretch` est traite comme `start` par CSS Grid pour tout element de
   grille dont la hauteur est DEFINIE. La ligne d'entete est une ligne de grille comme
   une autre (meme `display: contents` sur le <tr>, meme piste de 48px) ; si la cellule
   d'entete porte elle aussi une hauteur inline, elle serait epinglee en HAUT de la
   piste et laisserait une bande transparente sous l'entete. Sans hauteur inline, c'est
   un no-op strict. */
.fluent-data-grid .column-header,
.fluent-data-grid :is(th, [role="columnheader"]) {
  height: auto !important;
  /* Override Fluent's sticky-column inline background along with its height. */
  background: var(--entropia-color-surface-raised) !important;
  color: var(--entropia-color-ink-strong);
  border-bottom: 1px solid var(--entropia-color-line);
}

/* `height: auto !important` : le `!important` est la SEULE chose capable de battre
   le style inline `height: 32px` que FluentDataGridCell pose sur chaque <td>
   (voir le bloc de commentaire plus haut). Sans lui, la regle ne s'applique pas. */
.fluent-data-grid :is(td, [role="gridcell"], .fluent-data-grid-cell) {
  height: auto !important;
  min-height: 48px;
  padding-top: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--entropia-color-line);
}

/* Meme piege que .row-selected juste au-dessus (display:contents sur <tr>) : ce
   survol generique ciblait le <tr> et ne peignait donc rien du tout, pas seulement
   "un gris a 2% qu'on voit mal" — il etait invisible a 100%. On repose le fond sur
   les cellules pour que le survol existe enfin, meme sur une grille sans ligne
   cliquable (juste comme reperage visuel de la ligne survolee). */
.fluent-data-grid tbody tr:hover :is(td, [role="gridcell"], .fluent-data-grid-cell) {
  background: rgba(37, 99, 235, 0.04);
}

/* ----------------------------------------------------------------------------
 * Ligne cliquable — motif partage, pose une seule fois ici et applique via
 * RowClass="@(item => ... ? "row-selected row-clickable" : "row-clickable")" sur
 * toute grille dont OnRowClick ouvre un detail ailleurs sur la page (zones d'un
 * entrepot, fiche d'un job de sync, historique d'une session boucherie...).
 *
 * Le probleme signale : rien ne distinguait une ligne "qui mene quelque part" d'une
 * ligne inerte — pas de curseur fiable, un survol qui ne peignait rien (voir plus
 * haut), et aucun signe pour l'operateur qui ne survole jamais (tablette d'entrepot,
 * ou simple inattention). /warehouses en est l'exemple cite : cliquer un entrepot
 * ouvre son panneau de zones, mais la ligne ne ressemblait a rien de cliquable.
 *
 * Trois garanties, aucune ne suffit seule :
 *   1) curseur main + survol nettement plus marque que le survol generique
 *      ci-dessus (bordure gauche franche + fond plus dense), pour rester lisible
 *      sur un ecran d'entrepot en plein jour ;
 *   2) une puce "›" APRES le libelle de la premiere colonne — visible SANS survol,
 *      donc utile sur tablette (pas de hover tactile) et pour qui ne survole
 *      jamais. Posee sur la PREMIERE cellule et non la derniere : la derniere
 *      porte souvent une colonne d'actions (Desactiver/Reactiver, Confirmer) et un
 *      chevron y chevaucherait le libelle du bouton. Posee sur la cellule et non
 *      le <tr>, pour la meme raison de display:contents que ci-dessus ;
 *   3) un halo :focus-visible net sur la cellule focalisee. FluentDataGrid gere
 *      deja Tab pour entrer dans la grille, les fleches pour deplacer le focus de
 *      cellule en cellule, et Entree pour declencher OnRowClick — confirme en lisant
 *      la source exacte de la version livree (nuget 4.12.1) :
 *      FluentDataGridRow.razor pose "@onkeydown" sur le <tr> lui-meme (bulle depuis
 *      la cellule focalisee), et HandleOnRowKeyDownAsync n'invoque OnRowClick que
 *      pour KEYBOARD_SELECT_KEYS = ["Enter", "NumpadEnter"] — PAS Espace, malgre le
 *      pattern ARIA grid habituel. Ce halo rend cette navigation enfin VISIBLE, ce
 *      qui manquait completement. Un <tr @onclick> nu (sans cette gestion clavier)
 *      ne serait atteignable par personne au clavier ; ce n'est pas notre cas ici
 *      parce que FluentDataGrid la fournit deja pour toute ligne portant OnRowClick
 *      — juste au clavier avec Entree, pas Espace.
 * -------------------------------------------------------------------------- */
.fluent-data-grid tr.row-clickable :is(td, [role="gridcell"], .fluent-data-grid-cell) {
  cursor: pointer;
}

/* Distinct de .row-selected (--entropia-color-brand-primary-soft, plus haut) : une
   ligne selectionnee survolee par une AUTRE ligne ne doit pas se confondre avec la
   ligne survolee elle-meme. Meme teinte que le survol generique ci-dessus, opacite
   plus que doublee (0.04 -> 0.10) pour rester nettement visible sur un ecran
   d'entrepot, sans jamais egaler le fond plein d'une selection. */
.fluent-data-grid tr.row-clickable:hover :is(td, [role="gridcell"], .fluent-data-grid-cell) {
  background: rgba(37, 99, 235, 0.1);
}

/* Accent sur la premiere cellule seulement — pose sur chaque cellule, ce
   box-shadow dessinerait une bordure entre CHAQUE colonne au lieu d'un seul
   accent au bord gauche de la ligne. */
.fluent-data-grid tr.row-clickable:hover :is(td, [role="gridcell"], .fluent-data-grid-cell):first-child {
  box-shadow: inset 3px 0 0 var(--entropia-color-brand-primary);
}

.fluent-data-grid tr.row-clickable :is(td, [role="gridcell"], .fluent-data-grid-cell):first-child::after {
  content: "\203A";
  display: inline-block;
  margin-left: 8px;
  font-weight: 700;
  color: var(--entropia-color-brand-primary);
  opacity: 0.7;
}

.fluent-data-grid tr.row-clickable :is(td, [role="gridcell"], .fluent-data-grid-cell):focus-visible {
  position: relative;
  z-index: 1;
  outline: 2px solid var(--entropia-color-brand-primary);
  outline-offset: -2px;
}

.admin-detail-empty {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.admin-detail-empty .empty-state-card {
  flex: 1 1 auto;
  min-height: 280px;
  justify-content: center;
}

.table-metric-icon {
  width: 52px;
  height: 52px;
  border-radius: 16px;
  display: inline-grid;
  place-items: center;
  font-size: 24px;
  font-weight: 700;
  color: var(--entropia-color-on-brand);
}

.table-metric-icon.users { background: linear-gradient(180deg, var(--entropia-color-info) 0%, var(--entropia-color-brand-primary-strong) 100%); }
.table-metric-icon.success { background: linear-gradient(180deg, var(--entropia-color-success) 0%, #15803d 100%); }
.table-metric-icon.warning { background: linear-gradient(180deg, var(--entropia-color-warning) 0%, #d97706 100%); }
.table-metric-icon.info { background: linear-gradient(180deg, #6366f1 0%, #4f46e5 100%); }

.metric-tile.metric-tile-rich {
  min-height: 132px;
  padding: 20px;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 16px;
  align-items: center;
}

.metric-tile.metric-tile-rich strong {
  margin-top: 0;
}

.metric-tile.metric-tile-rich .metric-copy {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* FluentDataGrid column headers — the stealth sort buttons carry FAST's default
   neutral fill which stays light in dark mode. Pin them to the page surface. */
.fluent-data-grid .column-header .col-sort-button,
.fluent-data-grid .column-header fluent-button.col-sort-button::part(control) {
  background: transparent;
  color: var(--entropia-color-ink);
}

/* Row actions cell — two editor links cannot sit side-by-side at 1024×768 in a
   1fr track (the labels are ~22 chars each). Stack them vertically by design:
   full-width buttons, tight gap. This is the intended layout, not a wrap
   artifact, so the actions column reads as a neat control stack at every
   breakpoint and both actions stay visible (contract §5: no hover-only). */
.fluent-data-grid .row-actions {
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  flex-wrap: nowrap;
}

.fluent-data-grid .row-actions .btn {
  width: 100%;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ----------------------------------------------------------------------------
 * Shared form repair — larger controls, cleaner wrapping, visible validation.
 * -------------------------------------------------------------------------- */
.entity-form-grid {
  gap: 16px 18px;
}

.entity-form-grid > div,
.entity-form-grid > section,
.field,
.login-field {
  min-width: 0;
}

.field-help-label {
  align-items: flex-start;
  line-height: 1.35;
}

.field-help-hint,
.form-section-title,
.app-layout .validation-message {
  overflow-wrap: anywhere;
}

.app-layout .validation-message {
  display: block;
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--entropia-color-danger);
}

.form-control,
.form-select {
  min-height: 46px;
  padding: 12px 14px;
  font-size: 14px;
  line-height: 1.4;
  box-shadow: none;
}

fluent-text-field,
fluent-number-field,
fluent-select {
  /* Keep the Fluent host and its shadow control at the same usable height.
     Enlarging only ::part(control) leaves a 32px host around a 46px input. */
  --base-height-multiplier: 12;
}

fluent-text-field,
fluent-number-field,
fluent-select,
fluent-text-area {
  width: 100%;
}

fluent-text-field::part(root),
fluent-number-field::part(root),
fluent-select::part(root),
fluent-text-area::part(root) {
  width: 100%;
}

fluent-text-field::part(control),
fluent-number-field::part(control),
fluent-select::part(control),
fluent-text-area::part(control) {
  min-height: 46px;
  padding: 11px 14px;
  font-size: 14px;
  line-height: 1.4;
  background: var(--entropia-surface-raised);
  color: var(--entropia-ink);
  box-sizing: border-box;
}

fluent-text-area::part(control) {
  min-height: 112px;
}

/* ═════════════════════════════════════════════════════════════════════════════
   L4 — CROSS-BROWSER COMPAT (Safari iOS 16+, Firefox ESR; Chrome/Windows reference)
   Engine parity: text inflation, tap highlight, coarse-pointer input sizing,
   scrollbar parity, reduced motion, scroll containment. Viewport-unit fallbacks
   and -webkit- prefix twins live beside their declarations (L1–L3), not here.
   ═════════════════════════════════════════════════════════════════════════════ */

/* Text inflation: iOS Safari zooms text when rotated unless this is pinned. */
html {
  /* Fluent anchored menus measure this rectangle as their viewport. A tall
     document must not make an offscreen menu look as though it still fits. */
  height: 100%;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Tap polish: kills the gray flash on tappable elements under iOS/Android. */
a, button, [role="button"], summary {
  -webkit-tap-highlight-color: transparent;
}

/* Scroll containment: drawers and the reconnect scrim must not chain their
   overscroll to the page underneath (Safari iOS rubber-bands the shell). */
.drawer-panel .drawer-body,
#components-reconnect-modal .reconnect-card,
#components-reconnect-modal {
  overscroll-behavior: contain;
}

/* Coarse pointers: iOS Safari zooms any focused input whose font is < 16px.
   Raw elements get 16px directly; Fluent fields get it via the type ramp var
   (they cap at 14px through --type-ramp-base-font-size internally). */
@media (pointer: coarse) {
  input, select, textarea {
    font-size: 16px;
  }

  fluent-text-field, fluent-number-field, fluent-select, fluent-search,
  fluent-combobox, fluent-text-area {
    --type-ramp-base-font-size: 16px;
  }
}

/* Reduced motion: vestibular safety — collapses every authored animation and
   transition to effectively zero. Fluent internals honor the same media query. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Keep navigation out of the document grid on small windows. Hidden navigation
   must neither widen the page nor expose offscreen keyboard targets. */
.sidebar-section-copy { flex: 0 0 auto !important; }
@media (min-width: 901px) {
  .app-layout.app-layout-rail-collapsed { grid-template-columns: 72px minmax(0, 1fr); }
  .app-layout-rail-collapsed .sidebar-section-copy { display: none; }
  .sidebar-mobile-close { display: none; }
}
@media (max-width: 900px) {
  .app-layout, .app-layout.app-layout-rail-collapsed {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    grid-template-areas: "topbar" "main";
  }
  .app-layout .sidebar { display: none; }
  .app-layout .sidebar.is-mobile-open {
    display: flex;
    position: fixed;
    inset: 0 auto 0 0;
    width: min(320px, 90vw);
    height: 100dvh;
    z-index: 1100;
    transform: none;
    overflow-y: auto;
    flex-direction: column;
  }
  .sidebar-section-body { flex-direction: column; }
  .topbar { height: auto; min-width: 0; max-width: 100%; }
  .topbar-main { height: auto; min-height: 56px; flex-wrap: wrap; gap: 8px; padding: 8px 12px; }
  .topbar-section-nav { max-width: 100%; min-width: 0; overflow-x: auto; flex-wrap: nowrap; }
  .topbar-section-tab { flex-shrink: 0; }
  .topbar-search { flex: 1 1 100%; width: 100%; }
  .content.content-modern { min-width: 0; padding: 16px; }
  .topbar .rail-collapse-toggle { display: none; }
}
/* A failed picker is an inline form error, not a permanently open dropdown
   covering the next field. */
.entity-picker > .entity-picker-load-state { position: static; width: 100%; }

/* Fluent 4.12 places menus using a 200px threshold. Longer overflow menus
   need their own scroll area so the final tab remains reachable on a PDA. */
.fluent-menu-provider fluent-menu {
  max-height: min(200px, calc(50dvh - 16px));
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Technical setting names and translated tab labels must fit narrow forms. */
.settings-form label {
  overflow-wrap: anywhere;
}
.settings-form fluent-tab {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
}
.settings-form fluent-button {
  max-width: 100%;
}
.settings-form fluent-button::part(control) {
  max-width: 100%;
  height: auto;
  min-height: 32px;
  white-space: normal;
}
.settings-form fluent-button::part(content) {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Compact supervisor/admin workspaces without hiding fields or actions. */
@media (max-width: 600px) {
  :is(.modules-page, .slotting-page) .grid-wrap {
    padding-inline: 8px;
  }
  :is(.modules-page, .slotting-page) .mb-grid h1.grid-h1 {
    font-size: 1.75rem;
    line-height: 1.2;
    overflow-wrap: anywhere;
  }
  :is(.modules-page, .slotting-page) .panel-card {
    padding: 12px;
  }
  :is(.modules-page, .slotting-page) .page-toolbar {
    gap: 8px;
  }
  .modules-page .metric-strip {
    grid-template-columns: 1fr;
    gap: 4px;
  }
  .modules-page .form-section-body {
    padding-inline: 8px;
  }
  .modules-page .form-section > .form-section-title {
    padding-inline: 8px;
  }
  .modules-page .metric-tile {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    min-height: 44px;
    padding: 8px 12px;
  }
  .modules-page .metric-tile strong {
    font-size: 1.25rem;
    flex-shrink: 0;
  }
  .modules-page .fluent-data-grid {
    grid-template-columns: minmax(108px, 1fr) 82px 100px !important;
  }
  .modules-page .fluent-data-grid :is(th, td) {
    padding-inline: 4px;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .modules-page .fluent-data-grid .col-title {
    width: 100% !important;
  }
  .modules-page .fluent-data-grid .col-title-text {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }
  :is(.modules-page, .slotting-page) fluent-button::part(control) {
    min-height: 44px;
    height: auto;
    white-space: normal;
  }
  .modules-page .drawer-panel.inline-panel > :is(.drawer-header, .drawer-body) {
    padding: 12px;
  }
}
