/* ═══════════════════════════════════════════════════════════
   WSHA ETL design system: tokens, light and dark themes, base components.

   Colours are semantic tokens. Components use meanings (--app-surface,
   --app-text-2, --app-danger-fg…), never raw hex, so the dark theme only has
   to redefine the tokens. The brand palette (--app-navy*, --app-teal*) is set
   at runtime by appApplyBranding (js/branding.js) as inline styles on <html>,
   which beat any stylesheet rule: the themes must never redefine it, only
   derive from it.

   The theme is chosen by data-bs-theme on <html> (light | dark), set before
   first paint by js/theme.js from the person's preference (or the OS).
   ═══════════════════════════════════════════════════════════ */

:root {
  /* ── Brand palette (overridden at runtime by Admin › Branding) ── */
  --app-navy:        #0D2447;
  --app-navy-dark:   #091A36;
  --app-navy-700:    #162F5A;
  --app-navy-600:    #1E3D70;
  --app-navy-400:    #3A5A96;
  --app-teal:        #00C5A8;
  --app-teal-600:    #009E88;
  --app-teal-50:     rgba(0, 197, 168, 0.08);
  --app-teal-glow:   rgba(0, 197, 168, 0.18);
  --app-navy-rgb:    13, 36, 71;
  --app-teal-rgb:    0, 197, 168;

  /* ── Glass (on the navy sidebar and sign-in page, both themes) ── */
  --app-glass-bg:     rgba(255, 255, 255, 0.06);
  --app-glass-border: rgba(255, 255, 255, 0.12);
  --app-glass-blur:   24px;

  /* ── Surfaces ── */
  --app-bg:             #F3F6FB;
  --app-surface:        #FFFFFF;
  --app-surface-2:      #EBF0F7;
  --app-surface-sunken: #F6F8FC;
  --app-white:          #FFFFFF;   /* literal white (text on brand fills); use --app-surface for panels */
  --app-overlay:        rgba(9, 17, 32, 0.45);
  --app-logo-plate:     #FFFFFF;   /* behind uploaded logos, both themes: logos are drawn for white */

  /* ── Text ── */
  --app-text:        #13213A;
  --app-text-1:      var(--app-text);
  --app-text-2:      #4A5B78;
  --app-text-3:      #5E6E87;
  --app-text-4:      #8A9BB5;
  --app-heading:     var(--app-navy);
  --app-link:        var(--app-accent-text);   /* teal, like dark mode: navy links read as body text */
  --app-link-hover:  color-mix(in srgb, var(--app-accent-text) 75%, black);
  --app-accent-text: color-mix(in srgb, var(--app-teal-600) 78%, black);

  /* ── Lines, focus, shadows ── */
  --app-border:      #DCE4EF;
  --app-border-2:    #C5D2E5;
  --app-focus:       rgba(0, 197, 168, 0.35);
  --app-shadow-rgb:  13, 36, 71;
  --app-shadow-xs:   0 1px 2px rgba(var(--app-shadow-rgb), 0.05);
  --app-shadow-sm:   0 1px 3px rgba(var(--app-shadow-rgb), 0.06), 0 1px 2px rgba(var(--app-shadow-rgb), 0.04);
  --app-shadow:      0 4px 14px rgba(var(--app-shadow-rgb), 0.08), 0 1px 3px rgba(var(--app-shadow-rgb), 0.05);
  --app-shadow-lg:   0 12px 32px rgba(var(--app-shadow-rgb), 0.12), 0 3px 8px rgba(var(--app-shadow-rgb), 0.06);
  --app-shadow-lift: 0 20px 48px rgba(var(--app-shadow-rgb), 0.17), 0 8px 16px rgba(var(--app-shadow-rgb), 0.08);

  /* ── Primary action ── */
  --app-primary-bg:    var(--app-navy);
  --app-primary-hover: var(--app-navy-600);
  --app-primary-fg:    #FFFFFF;

  /* ── Status ── */
  --app-danger-bg:   #FEF1F1;  --app-danger-fg:  #B42318;  --app-danger-border:  #F8C9C9;  --app-danger-solid:  #D92D20;
  --app-warning-bg:  #FFF6E5;  --app-warning-fg: #8A4B08;  --app-warning-border: #F7D8A3;  --app-warning-solid: #F59E0B;
  --app-success-bg:  #EAFBF4;  --app-success-fg: #05704F;  --app-success-border: #A9E8CF;  --app-success-solid: #12B76A;
  --app-info-bg:     #EEF4FF;  --app-info-fg:    #1D4ED8;  --app-info-border:    #C3D6FB;  --app-info-solid:    #2E6BEA;
  --app-neutral-bg:  var(--app-surface-2); --app-neutral-fg: var(--app-text-2); --app-neutral-border: var(--app-border);

  /* ── Shape and motion ── */
  --app-r-sm:  6px;
  --app-r:     10px;
  --app-r-lg:  14px;
  --app-r-xl:  20px;
  --app-ease:  cubic-bezier(0.16, 1, 0.3, 1);
  --app-fast:  0.15s;
  --app-mid:   0.25s;
  --app-slow:  0.38s;

  /* Height of the pinned app chrome (top bar, plus the alpha strip when shown); set by MainLayout. */
  --app-chrome-top: 58px;

  /* ── Bootstrap, mapped onto the tokens so stock components follow brand and theme ── */
  --bs-body-bg:          var(--app-bg);
  --bs-body-color:       var(--app-text);
  --bs-emphasis-color:   var(--app-heading);
  --bs-secondary-color:  var(--app-text-2);
  --bs-tertiary-color:   var(--app-text-3);
  --bs-border-color:     var(--app-border);
  --bs-secondary-bg:     var(--app-surface-2);
  --bs-tertiary-bg:      var(--app-surface-sunken);
  --bs-primary:          var(--app-navy);
  /* ── Sidebar: part of the page in either theme (Admin › Branding can make it the brand colour) ── */
  --app-sidebar-bg:        var(--app-surface);
  --app-sidebar-border:    var(--app-border);
  --app-sidebar-fg:        var(--app-text-2);
  --app-sidebar-fg-strong: var(--app-heading);
  --app-sidebar-muted:     var(--app-text-3);
  --app-sidebar-hover-bg:  var(--app-surface-2);
  --app-sidebar-active-bg: var(--app-surface-2);
  --app-sidebar-accent:    var(--app-accent-text);
  --app-sidebar-control:   var(--app-surface-2);
  --bs-primary-rgb:      var(--app-navy-rgb);
  --bs-link-color:       var(--app-link);
  --bs-link-hover-color: var(--app-link-hover);
  color-scheme: light;
}

/* ── Dark theme: only semantic tokens change; the brand palette stays as configured ── */
:root[data-bs-theme="dark"] {
  --app-bg:             #0B1220;
  --app-surface:        #111A2B;
  --app-surface-2:      #1A263B;
  --app-surface-sunken: #0D1524;
  --app-overlay:        rgba(0, 0, 0, 0.6);

  --app-text:        #E4EAF4;
  --app-text-2:      #AEBBD0;
  --app-text-3:      #8796AF;
  --app-text-4:      #6B7A93;
  --app-heading:     #F2F6FC;
  --app-link:        color-mix(in srgb, var(--app-teal) 72%, white);
  --app-link-hover:  #FFFFFF;
  --app-accent-text: color-mix(in srgb, var(--app-teal) 72%, white);

  --app-border:      #243149;
  --app-border-2:    #33425F;

  --app-sidebar-bg:        #080E19;
  --app-sidebar-border:    #1B2538;
  --app-sidebar-fg:        var(--app-text-2);
  --app-sidebar-fg-strong: var(--app-heading);
  --app-sidebar-muted:     var(--app-text-3);
  --app-sidebar-hover-bg:  var(--app-surface);
  --app-sidebar-active-bg: var(--app-surface-2);
  --app-sidebar-accent:    var(--app-teal);
  --app-sidebar-control:   var(--app-surface);
  --app-focus:       rgba(0, 197, 168, 0.45);
  --app-shadow-rgb:  0, 0, 0;

  --app-primary-bg:    var(--app-teal);
  --app-primary-hover: color-mix(in srgb, var(--app-teal) 82%, white);
  --app-primary-fg:    #04201B;

  --app-danger-bg:   #2B1216;  --app-danger-fg:  #FDA4A4;  --app-danger-border:  #5B2028;  --app-danger-solid:  #E5484D;
  --app-warning-bg:  #2A1F0C;  --app-warning-fg: #FBCB6B;  --app-warning-border: #5C4413;  --app-warning-solid: #F5A524;
  --app-success-bg:  #0B2A21;  --app-success-fg: #6EE7B7;  --app-success-border: #17513F;  --app-success-solid: #22C55E;
  --app-info-bg:     #0F1D38;  --app-info-fg:    #9CC2FF;  --app-info-border:    #213D6E;  --app-info-solid:    #4C8DFF;

  --bs-primary:      var(--app-teal);
  --bs-primary-rgb:  var(--app-teal-rgb);
  color-scheme: dark;
}

:root[data-sidebar="brand"] {
  --app-sidebar-bg:        var(--app-navy);
  --app-sidebar-border:    var(--app-navy-dark);
  --app-sidebar-fg:        rgba(255, 255, 255, 0.72);
  --app-sidebar-fg-strong: #FFFFFF;
  --app-sidebar-muted:     rgba(255, 255, 255, 0.6);
  --app-sidebar-hover-bg:  rgba(255, 255, 255, 0.08);
  --app-sidebar-active-bg: rgba(255, 255, 255, 0.12);
  --app-sidebar-accent:    var(--app-teal);
  --app-sidebar-control:   rgba(255, 255, 255, 0.08);
}

/* ─────────────────────────────────────────────────────────
   Base
   ───────────────────────────────────────────────────────── */

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

html, body {
  font-family: 'Outfit', system-ui, -apple-system, sans-serif;
  font-size: 15px;
  color: var(--app-text);
  background: var(--app-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

/* ─────────────────────────────────────────────────────────
   Typography
   ───────────────────────────────────────────────────────── */

h1, .h1 {
  font-family: 'Outfit', system-ui, sans-serif;
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--app-heading);
  letter-spacing: -0.02em;
  line-height: 1.2;
}

h2, .h2 {
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--app-heading);
  letter-spacing: -0.015em;
}

h3, h4, h5, h6, .h3, .h4, .h5, .h6 {
  font-weight: 600;
  color: var(--app-heading);
  letter-spacing: -0.005em;
}

/* A small heading above a group of rows (folder names, "Start from a template"). */
.section-label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--app-text-2);
  margin: 0 0 0.5rem;
}

/* Numbers that line up and don't jitter as they change. */
.num { font-variant-numeric: tabular-nums; }
/* Lets a flex child shrink below its content, so long names wrap instead of pushing siblings out. */
.min-w-0 { min-width: 0; }

/* ── Data checks (job editor) ── */
.check-row {
    border: 1px solid var(--app-border);
    border-radius: var(--app-r-sm);
    background: var(--app-surface);
    padding: .5rem .75rem .625rem;
    margin-bottom: .5rem;
}
.check-row__head { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.check-row__num {
    font-variant-numeric: tabular-nums;
    color: var(--app-text-3);
    font-size: .8125rem;
    min-width: 1.25rem;
}
.check-row__kind { width: auto; min-width: 8.5rem; flex: 0 0 auto; }
.check-row__column { width: auto; min-width: 6rem; max-width: 16rem; flex: 1 1 6rem; }
.check-row__body { margin-top: .5rem; padding-left: 1.75rem; }
.check-row__bound { width: 9rem; }
.check-row__table { width: 18rem; max-width: 100%; }
.check-row__foot { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: .5rem; }
.check-row__name { flex: 1 1 14rem; width: auto; min-width: 0; }
.check-row__tolerance {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    margin: 0;
    white-space: nowrap;
    color: var(--app-text-3);
}
.check-row__tolerance input { width: 4.5rem; }
/* Run page: the check's status pill in a fixed column, so the names line up. */
.run-check__status { flex: 0 0 7.5rem; }
@media (max-width: 575.98px) { .run-check__status { flex-basis: auto; } }
/* A drafted value beside what's there now (AI descriptions). */
.draft-row {
    display: grid;
    grid-template-columns: minmax(7rem, 12rem) 1fr auto;
    gap: .5rem .75rem;
    align-items: start;
    padding: .375rem 0;
    border-top: 1px solid var(--app-border);
    font-size: .875rem;
}
.draft-row:first-of-type { border-top: 0; }
.draft-row__label { color: var(--app-text-3); overflow-wrap: anywhere; }

/* A column select whose (effective) classification is PHI. */
.form-select.is-phi { border-color: var(--app-danger-border); color: var(--app-danger-fg); background-color: var(--app-danger-bg); }
@media (max-width: 575.98px) {
    .draft-row { grid-template-columns: 1fr auto; }
    .draft-row__label { grid-column: 1 / -1; }
}
.check-suggestions {
    border: 1px dashed var(--app-border);
    border-radius: var(--app-r-sm);
    padding: .625rem .75rem;
    background: var(--app-surface-2);
}
@media (max-width: 575.98px) {
    .check-row__body { padding-left: 0; }
    .check-row__kind, .check-row__column { min-width: 0; flex: 1 1 40%; }
}

/* ─────────────────────────────────────────────────────────
   Links and focus
   ───────────────────────────────────────────────────────── */

a, .btn-link {
  color: var(--app-link);
  text-decoration: none;
  transition: color var(--app-fast) ease;
}

a:hover, .btn-link:hover {
  color: var(--app-link-hover);
  text-decoration: none;
}

/* One visible focus ring for everything a keyboard can reach. */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
[tabindex]:focus-visible,
summary:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--app-focus) !important;
}

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 36px;
  font-family: 'Outfit', sans-serif;
  font-weight: 500;
  font-size: 0.875rem;
  line-height: 1.2;
  border-radius: var(--app-r-sm);
  transition: background-color var(--app-fast) ease, border-color var(--app-fast) ease,
              color var(--app-fast) ease, box-shadow var(--app-fast) ease;
}

.btn-sm { min-height: 30px; padding: 0.25rem 0.65rem; font-size: 0.8125rem; gap: 0.3rem; }
.btn-lg { min-height: 44px; }
.btn.btn-link { min-height: 0; }

.btn-primary {
  background: var(--app-primary-bg) !important;
  border-color: var(--app-primary-bg) !important;
  color: var(--app-primary-fg) !important;
}
.btn-primary:hover, .btn-primary:focus-visible {
  background: var(--app-primary-hover) !important;
  border-color: var(--app-primary-hover) !important;
}
.btn-primary:disabled, .btn-primary.disabled { opacity: 0.55; }

.btn-outline-primary {
  border-color: color-mix(in srgb, var(--app-link) 50%, transparent) !important;
  color: var(--app-link) !important;
  background: transparent !important;
}
.btn-outline-primary:hover {
  background: color-mix(in srgb, var(--app-link) 10%, transparent) !important;
  border-color: var(--app-link) !important;
}

.btn-outline-secondary {
  border-color: var(--app-border-2) !important;
  color: var(--app-text) !important;
  background: var(--app-surface) !important;
}
.btn-outline-secondary:hover {
  border-color: var(--app-text-3) !important;
  background: var(--app-surface-2) !important;
}

.btn-secondary {
  background: var(--app-surface-2) !important;
  border-color: var(--app-surface-2) !important;
  color: var(--app-text) !important;
}
.btn-secondary:hover { border-color: var(--app-border-2) !important; }

.btn-danger {
  background: var(--app-danger-solid) !important;
  border-color: var(--app-danger-solid) !important;
  color: #FFFFFF !important;
}
.btn-danger:hover { filter: brightness(0.92); }

.btn-outline-danger {
  border-color: var(--app-danger-border) !important;
  color: var(--app-danger-fg) !important;
  background: transparent !important;
}
.btn-outline-danger:hover { background: var(--app-danger-bg) !important; }

.btn-link { padding-left: 0.35rem; padding-right: 0.35rem; }
.btn-link.text-danger { color: var(--app-danger-fg) !important; }

.btn:focus, .btn:active:focus { box-shadow: none; }

/* ─────────────────────────────────────────────────────────
   Forms
   ───────────────────────────────────────────────────────── */

.form-control, .form-select {
  font-family: 'Outfit', sans-serif;
  font-size: 0.875rem;
  min-height: 36px;
  padding: 0.4rem 0.75rem;
  border: 1px solid var(--app-border-2);
  border-radius: var(--app-r-sm);
  color: var(--app-text);
  background-color: var(--app-surface);
  transition: border-color var(--app-fast) ease, box-shadow var(--app-fast) ease;
}
.form-select { padding-right: 2.25rem; }
textarea.form-control { min-height: 0; }
.form-control::placeholder { color: var(--app-text-4); }
/* Read-only and disabled fields: a filled background that differs from an editable one in both themes
   (sunken was all but invisible against the dark surface). */
.form-control:disabled, .form-select:disabled, .form-control[readonly] {
  background-color: var(--app-surface-2);
  color: var(--app-text-2);
}
.form-control:disabled, .form-select:disabled { cursor: not-allowed; }

.form-control-sm, .form-select-sm {
  min-height: 30px;
  font-size: 0.8125rem;
  padding: 0.25rem 0.6rem;
}
.form-select-sm { padding-right: 2rem; }

.form-control:focus, .form-select:focus {
  border-color: var(--app-teal);
  box-shadow: 0 0 0 3px var(--app-focus);
  outline: none;
  background-color: var(--app-surface);
  color: var(--app-text);
}

.form-label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--app-text-2);
  margin-bottom: 0.3rem;
}

.form-text { font-size: 0.78rem; color: var(--app-text-3); }

.input-group-text {
  background: var(--app-surface-2);
  border-color: var(--app-border-2);
  color: var(--app-text-2);
  font-size: 0.8125rem;
}

.form-check-input {
  background-color: var(--app-surface);
  border-color: var(--app-border-2);
}
.form-check-input:checked {
  background-color: var(--app-teal);
  border-color: var(--app-teal);
}
.form-check-input:focus { box-shadow: 0 0 0 3px var(--app-focus); border-color: var(--app-teal); }

.form-switch .form-check-input {
  width: 2.3em;
  height: 1.25em;
  margin-top: 0.12em;
  cursor: pointer;
}
.form-check-label { color: var(--app-text); }

/* ─────────────────────────────────────────────────────────
   Cards and surfaces
   Flat by default; .card--raised for things that float.
   ───────────────────────────────────────────────────────── */

.card {
  --bs-card-bg: var(--app-surface);
  --bs-card-color: var(--app-text);
  border: 1px solid var(--app-border) !important;
  border-radius: var(--app-r) !important;
  box-shadow: none;
  background: var(--app-surface);
  color: var(--app-text);
}
.card .card { background: var(--app-surface-sunken); }
.card--raised { box-shadow: var(--app-shadow) !important; }

.card-header {
  background: transparent !important;
  border-bottom: 1px solid var(--app-border) !important;
  border-radius: var(--app-r) var(--app-r) 0 0 !important;
  padding: 0.75rem 1.25rem;
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--app-heading);
}
.card-body { padding: 1.25rem; }
.card-title { color: var(--app-heading); }
.card-footer { background: transparent; border-top-color: var(--app-border); }

/* ─────────────────────────────────────────────────────────
   Tables
   ───────────────────────────────────────────────────────── */

.table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--app-text);
  --bs-table-hover-bg: var(--app-surface-2);
  --bs-table-hover-color: var(--app-text);
  --bs-table-striped-bg: var(--app-surface-sunken);
  --bs-table-active-bg: var(--app-surface-2);
  border-color: var(--app-border);
  font-size: 0.875rem;
  margin-bottom: 0;
}

.table thead th {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--app-text-3);
  border-bottom: 1px solid var(--app-border) !important;
  padding: 0.6rem 0.9rem;
  background: transparent;
  white-space: nowrap;
}

.table tbody td {
  padding: 0.65rem 0.9rem;
  vertical-align: middle;
  border-color: var(--app-border);
  color: var(--app-text);
}

.table-sm thead th { padding: 0.4rem 0.6rem; }
.table-sm tbody td { padding: 0.35rem 0.6rem; }
.table tbody tr:last-child td { border-bottom-color: transparent; }

.table-hover tbody tr {
  transition: background-color var(--app-fast) ease;
  cursor: pointer;
}

.table td.num, .table th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Header that stays visible while the page scrolls (wrap the table in .table-sticky instead of
   .table-responsive). Wide screens only: on phones the table scrolls sideways instead. */
.table-sticky { overflow-x: auto; }
@media (min-width: 992px) {
  .table-sticky { overflow-x: clip; }
  .table-sticky thead th {
    position: sticky;
    top: var(--app-chrome-top);
    z-index: 2;
    background: var(--app-bg);
  }
}

/* A long or wide list in its own scroll box: the header stays visible and the horizontal scrollbar
   sits at the bottom of the box, on screen, not at the bottom of a long page. */
.table-scroll {
  max-height: 70vh;
  overflow: auto;
  border: 1px solid var(--app-border);
  border-radius: 0.5rem;
  background: var(--app-surface);
}
.table-scroll > .table { margin-bottom: 0; }
.table-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--app-surface-2);
}

/* ─────────────────────────────────────────────────────────
   Badges and pills
   ───────────────────────────────────────────────────────── */

.badge {
  font-family: 'Outfit', sans-serif;
  font-weight: 500;
  font-size: 0.72rem;
  letter-spacing: 0;
  border-radius: 999px;
  padding: 0.3em 0.65em;
}

.badge.bg-success   { background: var(--app-success-bg) !important; color: var(--app-success-fg) !important; }
.badge.bg-danger    { background: var(--app-danger-bg) !important;  color: var(--app-danger-fg) !important; }
.badge.bg-warning   { background: var(--app-warning-bg) !important; color: var(--app-warning-fg) !important; }
.badge.bg-info      { background: var(--app-info-bg) !important;    color: var(--app-info-fg) !important; }
.badge.bg-primary   { background: var(--app-primary-bg) !important; color: var(--app-primary-fg) !important; }
.badge.bg-secondary { background: var(--app-neutral-bg) !important; color: var(--app-neutral-fg) !important; }

/* A neutral tag: mode names, kinds, settings. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--app-neutral-border);
  background: var(--app-neutral-bg);
  color: var(--app-neutral-fg);
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.5;
  white-space: nowrap;
}

/* ─────────────────────────────────────────────────────────
   List groups
   ───────────────────────────────────────────────────────── */

.list-group {
  --bs-list-group-bg: var(--app-surface);
  --bs-list-group-color: var(--app-text);
  --bs-list-group-border-color: var(--app-border);
  --bs-list-group-action-hover-bg: var(--app-surface-2);
  --bs-list-group-action-hover-color: var(--app-text);
  --bs-list-group-active-bg: var(--app-primary-bg);
  --bs-list-group-active-border-color: var(--app-primary-bg);
  --bs-list-group-active-color: var(--app-primary-fg);
}
.list-group-flush .list-group-item {
  padding: 0.75rem 1.25rem;
  font-size: 0.875rem;
  transition: background-color var(--app-fast) ease;
}
.list-group-flush .list-group-item:hover { background-color: var(--app-surface-2); }

/* ─────────────────────────────────────────────────────────
   Alerts
   ───────────────────────────────────────────────────────── */

.alert {
  border-radius: var(--app-r-sm);
  font-size: 0.875rem;
  border-width: 1px;
}
.alert-danger    { background: var(--app-danger-bg);  border-color: var(--app-danger-border);  color: var(--app-danger-fg); }
.alert-warning   { background: var(--app-warning-bg); border-color: var(--app-warning-border); color: var(--app-warning-fg); }
.alert-success   { background: var(--app-success-bg); border-color: var(--app-success-border); color: var(--app-success-fg); }
.alert-info      { background: var(--app-info-bg);    border-color: var(--app-info-border);    color: var(--app-info-fg); }
.alert-secondary,
.alert-light     { background: var(--app-surface-2);  border-color: var(--app-border);         color: var(--app-text); }
.alert .alert-link { color: inherit; text-decoration: underline; }

/* ─────────────────────────────────────────────────────────
   Tabs (Bootstrap nav-tabs and the admin/profile tab bar share one look)
   ───────────────────────────────────────────────────────── */

.nav-tabs {
  border-bottom: 1px solid var(--app-border);
  gap: 0.125rem;
}

.nav-tabs .nav-link {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--app-text-2);
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  padding: 0.6rem 0.9rem;
  margin-bottom: -1px;
  background: transparent;
  transition: color var(--app-fast) ease, border-color var(--app-fast) ease;
}
.nav-tabs .nav-link:hover { color: var(--app-text); border-bottom-color: var(--app-border-2); }
.nav-tabs .nav-link.active {
  color: var(--app-heading);
  border-bottom-color: var(--app-teal);
  background: transparent;
  font-weight: 600;
}

/* ─────────────────────────────────────────────────────────
   Dropdowns, modals, popovers
   ───────────────────────────────────────────────────────── */

.dropdown-menu {
  --bs-dropdown-bg: var(--app-surface);
  --bs-dropdown-color: var(--app-text);
  --bs-dropdown-border-color: var(--app-border);
  --bs-dropdown-link-color: var(--app-text);
  --bs-dropdown-link-hover-bg: var(--app-surface-2);
  --bs-dropdown-link-hover-color: var(--app-text);
  --bs-dropdown-divider-bg: var(--app-border);
  border-radius: var(--app-r);
  box-shadow: var(--app-shadow-lg);
  font-size: 0.875rem;
}

.modal-content {
  background: var(--app-surface);
  color: var(--app-text);
  border: 1px solid var(--app-border);
  border-radius: var(--app-r-lg);
  box-shadow: var(--app-shadow-lift);
}
.modal-header, .modal-footer { border-color: var(--app-border); }
.modal-title { color: var(--app-heading); font-weight: 600; }

/* The page-dimming layer behind our own dialogs (Modal, ConfirmDialog). */
.app-overlay { background: var(--app-overlay); }

[data-bs-theme="dark"] .btn-close { filter: invert(1) grayscale(100%) brightness(200%); }

/* ─────────────────────────────────────────────────────────
   Code
   ───────────────────────────────────────────────────────── */

code {
  color: var(--app-accent-text);
  background: color-mix(in srgb, var(--app-teal) 10%, transparent);
  padding: 0.1em 0.35em;
  border-radius: 4px;
  font-size: 0.85em;
}

/* A block of SQL, YAML or output. */
.code-block {
  display: block;
  margin: 0;
  padding: 0.6rem 0.75rem;
  background: var(--app-surface-sunken);
  border: 1px solid var(--app-border);
  border-radius: var(--app-r-sm);
  color: var(--app-text);
  font-family: ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', monospace;
  font-size: 0.8rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  overflow: auto;
}
.code-block code { background: none; color: inherit; padding: 0; font-size: inherit; }

/* ─────────────────────────────────────────────────────────
   Animations
   ───────────────────────────────────────────────────────── */

@keyframes crm-slide-up {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes crm-slide-in-row {
  from { opacity: 0; transform: translateX(-8px); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes crm-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes crm-scale-up {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes crm-float-orb {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(60px, -80px); }
  50%  { transform: translate(-40px, -120px); }
  75%  { transform: translate(-80px, -40px); }
  100% { transform: translate(0, 0); }
}

@keyframes crm-pulse-glow {
  0%, 100% { box-shadow: 0 0 16px rgba(var(--app-teal-rgb), 0.15), 0 0 4px rgba(var(--app-teal-rgb), 0.10); }
  50%      { box-shadow: 0 0 28px rgba(var(--app-teal-rgb), 0.28), 0 0 8px rgba(var(--app-teal-rgb), 0.18); }
}

@keyframes crm-border-sweep {
  0%   { background-position: 0% 50%; }
  100% { background-position: 200% 50%; }
}

@keyframes crm-shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

/* ── Skeleton shimmer (see Shared/Skeleton.razor) ── */

.crm-skel {
  background: linear-gradient(90deg,
    var(--app-surface-2) 25%,
    color-mix(in srgb, var(--app-surface-2) 45%, var(--app-surface)) 50%,
    var(--app-surface-2) 75%);
  background-size: 200% 100%;
  animation: crm-shimmer 1.6s ease-in-out infinite;
  border-radius: var(--app-r-sm);
}

/* In the sidebar: its own colours (neutral, or the brand colour). */
.crm-skel--dark {
  background: linear-gradient(90deg,
    var(--app-sidebar-hover-bg) 25%,
    var(--app-sidebar-active-bg) 50%,
    var(--app-sidebar-hover-bg) 75%);
  background-size: 200% 100%;
  animation: crm-shimmer 1.6s ease-in-out infinite;
  border-radius: var(--app-r-sm);
}

@media (prefers-reduced-motion: reduce) {
  .crm-skel, .crm-skel--dark { animation: none; }
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ─────────────────────────────────────────────────────────
   Validation
   ───────────────────────────────────────────────────────── */

.valid.modified:not([type=checkbox]) { border-color: var(--app-teal) !important; }
.invalid { border-color: var(--app-danger-solid) !important; }
.validation-message { color: var(--app-danger-fg); font-size: 0.8rem; margin-top: 0.25rem; }

/* ─────────────────────────────────────────────────────────
   Loading Spinner
   ───────────────────────────────────────────────────────── */

.loading-progress {
  position: absolute;
  display: block;
  width: 3rem;
  height: 3rem;
  inset: 0;
  margin: auto;
}

.loading-progress circle {
  fill: none;
  stroke: rgba(255, 255, 255, 0.08);
  stroke-width: 0.35rem;
  transform-origin: 50% 50%;
  transform: rotate(-90deg);
}

.loading-progress circle:last-child {
  stroke: var(--app-teal);
  stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
  transition: stroke-dasharray 0.05s ease-in-out;
}

.loading-progress-text {
  position: absolute;
  text-align: center;
  font-weight: 500;
  font-family: 'Outfit', sans-serif;
  font-size: 0.7rem;
  color: rgba(255, 255, 255, 0.4);
  inset: calc(50% + 1.75rem) 0 auto 0;
}

.loading-progress-text::after {
  content: var(--blazor-load-percentage-text, "Loading");
}

/* ─────────────────────────────────────────────────────────
   Blazor Error UI
   ───────────────────────────────────────────────────────── */

#blazor-error-ui {
  background: var(--app-warning-bg);
  border-top: 2px solid var(--app-warning-solid);
  bottom: 0;
  box-shadow: var(--app-shadow-lg);
  box-sizing: border-box;
  display: none;
  left: 0;
  padding: 0.75rem 1.5rem;
  position: fixed;
  width: 100%;
  z-index: 1000;
  font-size: 0.875rem;
  color: var(--app-warning-fg);
}

#blazor-error-ui .dismiss {
  cursor: pointer;
  position: absolute;
  right: 0.75rem;
  top: 0.6rem;
}

.blazor-error-boundary {
  background: var(--app-danger-bg);
  border: 1px solid var(--app-danger-border);
  border-radius: var(--app-r);
  padding: 1.25rem;
  color: var(--app-danger-fg);
  font-size: 0.875rem;
}

.blazor-error-boundary::after { content: "An error has occurred."; }

/* ─────────────────────────────────────────────────────────
   Utilities
   ───────────────────────────────────────────────────────── */

.content { padding-top: 0; }
.text-muted { color: var(--app-text-3) !important; }
.text-body-secondary { color: var(--app-text-2) !important; }

/* Floating label fix */
.form-floating > .form-control-plaintext::placeholder,
.form-floating > .form-control::placeholder {
  color: var(--app-text-3);
  text-align: end;
}
.form-floating > .form-control-plaintext:focus::placeholder,
.form-floating > .form-control:focus::placeholder {
  text-align: start;
}


/* ── Audit trail (global — used by AuditTrail.razor component) ── */

.audit-trail { display: flex; flex-direction: column; gap: 0.5rem; }

.audit-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.55rem 0.75rem;
    background: var(--app-bg);
    border: 1px solid var(--app-border);
    border-radius: var(--app-r-sm);
    font-size: 0.82rem;
    transition: background var(--app-fast) ease;
}
.audit-row:hover { background: var(--app-surface); }

.audit-time    { color: var(--app-text-2); }
.audit-actor   { font-weight: 500; color: var(--app-heading); }
.audit-notes-inline { color: var(--app-text-3); font-style: italic; }

.audit-action-badge {
    display: inline-block;
    padding: 0.18rem 0.5rem;
    border-radius: 20px;
    font-size: 0.71rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    white-space: nowrap;
}
.audit-badge-auth    { background: var(--app-teal-50); color: var(--app-accent-text); border: 1px solid var(--app-teal); }
.audit-badge-create  { background: var(--app-success-bg); color: var(--app-success-fg); border: 1px solid var(--app-success-border); }
.audit-badge-update  { background: var(--app-info-bg); color: var(--app-info-fg); border: 1px solid var(--app-info-border); }
.audit-badge-delete  { background: var(--app-danger-bg); color: var(--app-danger-fg); border: 1px solid var(--app-danger-border); }
.audit-badge-complete { background: var(--app-success-bg); color: var(--app-success-fg); border: 1px solid var(--app-success-border); }
.audit-badge-neutral { background: var(--app-bg); color: var(--app-text-2); border: 1px solid var(--app-border-2); }

/* ─────────────────────────────────────────────────────────
   Tab bar (shared across Admin Settings, Profile, etc.)
   ───────────────────────────────────────────────────────── */

.admin-tab-bar {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--app-border);
  padding-bottom: 0;
}

.admin-tab {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.6rem 1.25rem;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-family: 'Outfit', sans-serif;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--app-text-2);
  cursor: pointer;
  transition: color var(--app-fast) ease, border-color var(--app-fast) ease;
  border-radius: var(--app-r-sm) var(--app-r-sm) 0 0;
}

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

.admin-tab.active {
  color: var(--app-heading);
  border-bottom-color: var(--app-teal);
  font-weight: 600;
}

/* ── Clickable card link ─────────────────────────────────── */

a.card-link { color: var(--app-text); }
a.card-link:hover { color: var(--app-text); }
a.card-link .fw-semibold { transition: color var(--app-fast) ease; }
a.card-link:hover .fw-semibold { color: var(--app-link); }

/* ── Activity list — type accent borders ──────────────────── */

.activity-item {
  border-left: 4px solid transparent;
  transition: border-color var(--app-fast) ease;
}
.activity-call    { border-left-color: var(--app-navy-400); }
.activity-email   { border-left-color: var(--app-info-solid); }
.activity-meeting { border-left-color: var(--app-teal); }
.activity-note    { border-left-color: var(--app-border-2); }

/* ── Empty state ─────────────────────────────────────────── */

/* Plain-markup empty state; Shared/EmptyState.razor is the richer version (icon, title, actions). */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.5rem;
  padding: 2.5rem 1rem;
  color: var(--app-text-2);
  border: 1px dashed var(--app-border-2);
  border-radius: var(--app-r-lg);
  background: var(--app-surface-sunken);
}
.empty-state svg { opacity: 0.45; }
.empty-state p { margin: 0; font-size: 0.875rem; }

/* ── Filter chips ─────────────────────────────────────────────
   These styles back the role / classification chip buttons rendered
   inline in list pages (AccountList, ContactList). The same selectors
   exist in ClassificationFilter.razor.css scoped to that component;
   list pages render their own chips outside the component so they
   need a global rule. */
.cf-wrapper { width: 100%; }

.cf-chipbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-items: center;
}

.cf-label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--app-text-2);
  margin-right: 0.25rem;
}

.cf-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.65rem;
  font-size: 0.8125rem;
  line-height: 1.25;
  border-radius: 999px;
  border: 1px solid transparent;
  background: transparent;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
  cursor: pointer;
  user-select: none;
}
.cf-chip:focus-visible {
  outline: 2px solid var(--app-teal);
  outline-offset: 2px;
}
.cf-chip i { font-size: 0.875rem; line-height: 1; }

.cf-chip-neutral {
  border-color: var(--app-border-2);
  color: var(--app-text);
}
.cf-chip-neutral:hover {
  background: var(--app-surface-2);
  border-color: var(--app-text-3);
}
.cf-chip-neutral i { color: var(--app-text-3); }

.cf-chip-include {
  background: var(--app-primary-bg);
  border-color: var(--app-primary-bg);
  color: var(--app-primary-fg);
}
.cf-chip-include:hover { filter: brightness(1.08); }

.cf-chip-exclude {
  background: var(--app-danger-bg);
  border-color: var(--app-danger-border);
  color: var(--app-danger-fg);
  text-decoration: line-through;
}
.cf-chip-exclude:hover {
  background: var(--app-danger-solid);
  border-color: var(--app-danger-solid);
  color: #FFFFFF;
}

.cf-clear {
  padding: 0 0.25rem;
  color: var(--app-text-2);
  text-decoration: none;
}
.cf-clear:hover {
  color: var(--app-text);
  text-decoration: underline;
}

.cf-chip-name { white-space: nowrap; }

/* Mobile-only actions toggle (the ⋮ button). Hidden by default; the
   mobile media block below flips it on. Compound `.btn.…` specificity
   is required because the global `.btn` rule below sets
   `display: inline-flex` and would otherwise win on single-class equals.
   The list-filters toggle that used to live here has moved into the
   shared <ListFilters> component. */
.btn.list-actions-toggle { display: none; }

/* Neutral count chip used by list pages to surface the DB-side total
   matching the current filter ("1,234 records"). tabular-nums keeps the
   number visually steady as the filter narrows (1,234 → 87) instead of
   wobbling on every keystroke. Same rule rendered by <TotalCountChip>
   in both the ListFilters header and inline on filter-less list pages. */
.total-count-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem 0.55rem;
  background: var(--app-surface-2);
  color: var(--app-text-2);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  user-select: none;
}

/* List-page header search input. Sits inline between the H1 and the
   action cluster on desktop — constrained width so it reads as a search
   bar, not a stretched form field. Mobile rules override flex / margin
   so it expands to share the H1 row with the actions toggle. */
.list-page-search {
  flex: 0 1 480px;
  max-width: 480px;
  margin: 0;
}

/* Desktop polish for list-page headers. Bootstrap's `.justify-content-
   between` distributes three items (H1, search, actions) evenly which
   marooned the search in the middle with empty gutters either side.
   Cluster H1 + search on the left with a tight gap and let the actions
   cluster anchor itself to the right via auto margin. */
@media (min-width: 641px) {
  article.content > .d-flex.justify-content-between.align-items-center {
    justify-content: flex-start;
    gap: 0.75rem;
  }
  article.content > .d-flex.justify-content-between.align-items-center > .d-flex.list-actions {
    margin-left: auto;
  }
  /* Filter inputs sit one rung below the header search in the visual
     hierarchy on desktop — small density signals "refiners" rather than
     "primary find affordances". Targets the shared <ListFilters>
     component body. */
  .lf-body .form-control,
  .lf-body .form-select {
    font-size: 0.875rem;
    padding-top: 0.4rem;
    padding-bottom: 0.4rem;
  }
}

/* Helper to hide a button's text on mobile while keeping the icon visible.
   Use as `<i class="bi ..."></i><span class="btn-label-mobile-hidden ms-1">Customize</span>`. */
@media (max-width: 640.98px) {
  .btn-label-mobile-hidden { display: none; }
  /* Hide an entire element on mobile-sized viewports. Useful for desktop-
     only affordances that don't translate to phone use (e.g. dashboard
     Customize, drag handles). */
  .d-mobile-none { display: none !important; }
}

/* ── Mobile optimizations ─────────────────────────────────── */

@media (max-width: 640.98px) {
  /* Scrollable admin / profile tab bars */
  .admin-tab-bar {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    flex-wrap: nowrap;
  }
  .admin-tab-bar::-webkit-scrollbar { display: none; }
  .admin-tab { flex-shrink: 0; font-size: 0.82rem; padding: 0.5rem 0.85rem; }
  .admin-tab:last-child { margin-right: 1.5rem; }

  /* Mobile table density */
  .table-responsive .table th,
  .table-responsive .table td {
    white-space: nowrap;
    font-size: 0.82rem;
    padding: 0.5rem 0.65rem;
  }

  /* Opt-in card layout for list pages: add `table-mobile-cards` to the
     <table> and `data-label="..."` to each <td>. Header row is hidden;
     each row stacks as a card with column labels prefixed inline. */
  .table-responsive .table.table-mobile-cards {
    white-space: normal;
  }
  .table-responsive .table.table-mobile-cards thead { display: none; }
  .table-responsive .table.table-mobile-cards,
  .table-responsive .table.table-mobile-cards tbody,
  .table-responsive .table.table-mobile-cards tr,
  .table-responsive .table.table-mobile-cards td {
    display: block;
    width: 100%;
  }
  .table-responsive .table.table-mobile-cards tr {
    background: var(--app-surface);
    border: 1px solid var(--app-border);
    border-radius: 12px;
    padding: 0.85rem 1rem;
    margin-bottom: 0.65rem;
    box-shadow: var(--app-shadow-xs);
    white-space: normal;
  }
  .table-responsive .table.table-mobile-cards td {
    border: 0;
    padding: 0.2rem 0;
    font-size: 0.9rem;
    white-space: normal;
  }
  .table-responsive .table.table-mobile-cards td:empty { display: none; }
  .table-responsive .table.table-mobile-cards td[data-label]::before {
    content: attr(data-label) ": ";
    font-weight: 600;
    color: var(--app-text-3);
    margin-right: 0.4rem;
  }
  /* The first cell typically holds the row's primary label (account name,
     contact name, etc) — render it as the card title with no prefix. */
  .table-responsive .table.table-mobile-cards td.table-mobile-cards-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--app-text-1);
    margin-bottom: 0.25rem;
    /* Title leaves room for the absolutely-positioned action cell so the
       edit button doesn't collide with long names. */
    padding-right: 4.5rem !important;
  }
  .table-responsive .table.table-mobile-cards td.table-mobile-cards-title[data-label]::before {
    content: '';
    margin: 0;
  }
  /* Action cells (edit links) are hidden on mobile cards — users tap the
     card to open the detail page where the edit affordance lives. Saves
     a row of vertical space and removes the empty right-side gutter. */
  .table-responsive .table.table-mobile-cards td.table-mobile-cards-action {
    display: none;
  }
  /* Reset the title's reserved right padding now that no action sits there. */
  .table-responsive .table.table-mobile-cards td.table-mobile-cards-title {
    padding-right: 0 !important;
  }

  /* Chips cell — no label prefix; the chips are self-explanatory. */
  .table-responsive .table.table-mobile-cards td.tmc-chips {
    padding: 0.2rem 0 0.35rem;
  }
  .table-responsive .table.table-mobile-cards td.tmc-chips[data-label]::before {
    content: '';
    margin: 0;
  }

  /* Compact "meta" cell — no label prefix, smaller muted text, flows
     inline with separators between siblings (Email · Phone, City, ST). */
  .table-responsive .table.table-mobile-cards td.tmc-meta {
    display: inline;
    font-size: 0.85rem;
    color: var(--app-text-3);
    padding: 0;
    margin: 0;
  }
  .table-responsive .table.table-mobile-cards td.tmc-meta[data-label]::before {
    content: '';
    margin: 0;
  }
  .table-responsive .table.table-mobile-cards td.tmc-meta + td.tmc-meta::before {
    content: ' · ';
    color: var(--app-text-4);
  }
  /* Force a line break before the first meta cell so it doesn't run into
     the title or chip row above. */
  .table-responsive .table.table-mobile-cards td.tmc-meta-start {
    display: block;
    margin-top: 0.15rem;
  }
  .table-responsive .table.table-mobile-cards td.tmc-meta-start::before {
    content: '' !important;
  }
  .table-responsive .table.table-mobile-cards td.tmc-meta-start + td.tmc-meta::before {
    content: ' · ';
  }

  /* Subtitle cell — second-line context like "CFO at Crown Banana".
     No label prefix; sits just under the title. */
  .table-responsive .table.table-mobile-cards td.tmc-subtitle {
    font-size: 0.875rem;
    color: var(--app-text-2);
    padding: 0;
    margin-bottom: 0.2rem;
  }
  .table-responsive .table.table-mobile-cards td.tmc-subtitle[data-label]::before {
    content: '';
    margin: 0;
  }
  /* Empty subtitle/meta cells should collapse without leaving stray separators. */
  .table-responsive .table.table-mobile-cards td.tmc-subtitle:empty,
  .table-responsive .table.table-mobile-cards td.tmc-meta:empty {
    display: none;
  }

  /* Page header bar: H1 + action buttons cluster. Default desktop pattern
     uses justify-content: between which crashes on narrow viewports.
     On mobile the H1 shares its row with a single Actions toggle (⋮);
     the action buttons collapse to a second row revealed on tap.
     The bar pins to the viewport top so filters / actions / +New stay
     reachable without scrolling. */
  article.content > .d-flex.justify-content-between.align-items-center {
    flex-wrap: wrap;
    gap: 0.5rem;
    row-gap: 0.5rem;
    position: sticky;
    top: 0;
    z-index: 12;
    background: var(--app-bg);
    /* Negative margin + matching padding extends the strip to the article
       edges so content scrolling under it doesn't peek through the gap. */
    margin: -1.25rem -1rem 0.75rem;
    padding: 0.75rem 1rem 0.5rem;
    border-bottom: 1px solid var(--app-border);
  }
  /* Row 1 layout: [H1] [search] [⋮]. H1 sizes to content; search grows
     to fill the middle; ⋮ pins to the right. */
  article.content > .d-flex.justify-content-between.align-items-center > h1 {
    flex: 0 0 auto;
    margin-bottom: 0;
    font-size: 1.1rem;
    min-width: 0;
    order: 0;
  }
  article.content > .d-flex.justify-content-between.align-items-center > .list-page-search {
    flex: 1 1 0;
    margin: 0;
    max-width: none;
    min-width: 0;
    order: 1;
  }
  article.content > .d-flex.justify-content-between.align-items-center > .list-page-search input {
    font-size: 0.85rem;
    padding: 0.4rem 0.65rem;
    height: auto;
  }
  /* The action cluster is a `.d-flex.gap-2` div; pages opt-in to the
     mobile collapse behavior by adding `.list-actions`. Without the
     class (e.g. dashboard with only Customize), it just wraps below. */
  article.content > .d-flex.justify-content-between.align-items-center > .d-flex.list-actions {
    display: none !important;
    width: 100%;
    order: 3;
  }
  article.content > .d-flex.justify-content-between.align-items-center > .d-flex.list-actions.list-actions--open {
    display: flex !important;
    flex-wrap: wrap;
  }
  article.content > .d-flex.justify-content-between.align-items-center .list-actions .btn {
    flex: 1 1 auto;
    font-size: 0.85rem;
  }

  /* The Actions toggle (the ⋮ button) sits next to the search input.
     Hidden on desktop; shown when paired with `.list-actions`.
     Compound selector to beat `.btn.list-actions-toggle { display: none }`
     on the desktop default. */
  .btn.list-actions-toggle {
    display: inline-flex;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    padding: 0;
    order: 2;
  }

  /* Smaller page headings */
  article.content h1 { font-size: 1.45rem; }

  /* Tap-target floor: every interactive control gets at least 44px so
     thumbs land cleanly. Use `.btn-link-tight` to opt out (e.g. inline
     pencil/x icons inside dense rows where 44px would look broken). */
  .btn,
  label.btn-radio-chip,
  .filter-chip,
  a.nav-link {
    min-height: 44px;
  }
  /* A 44px floor on a checkbox stretched the box itself into a tall bar: make it a bigger square
     instead (its label, where there is one, is the rest of the target). Switches keep their shape. */
  .form-check-input[type="checkbox"]:not(.form-switch .form-check-input),
  .form-check-input[type="radio"] {
    width: 1.3em;
    height: 1.3em;
  }
  .btn:not(.btn-link-tight),
  label.btn-radio-chip,
  .filter-chip {
    min-width: 44px;
  }
  .btn-link-tight {
    min-height: 0;
    min-width: 0;
  }
  .form-check-input { width: 1.4rem; height: 1.4rem; }
  /* Switches keep their pill shape; the label beside them is the tap target. */
  .form-switch .form-check-input { width: 2.3em; height: 1.25em; min-height: 0; }
  .filter-chip,
  label.btn-radio-chip {
    padding: 0.55rem 0.85rem;
    font-size: 0.85rem;
  }
}

/* ── Member portal styles ───────────────────────────────────────────────────
   Used by MemberLayout pages. Kept in global app.css (not scoped per page) so
   the shared component patterns (.member-card, .member-pill) render the same
   on MemberHome, MemberProfile, and MemberAccountDetail. */

/* Page title row: crumbs and title on the left, actions on the right, wrapping on narrow screens.
   Markup: <div class="page-header"><div><div class="small text-muted">crumbs</div><h1>…</h1></div>…actions…</div> */
.page-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.75rem 1.25rem;
    margin-bottom: 1.5rem;
}
.page-header > :first-child { min-width: 0; }
.page-header h1 { margin: 0; }
.page-header > div > .small.text-muted { font-size: 0.8125rem; margin-bottom: 0.25rem; color: var(--app-text-3) !important; }
.page-header > div > .small.text-muted a { color: var(--app-text-2); }
.page-header > div > .small.text-muted a:hover { color: var(--app-link-hover); }

.back-link {
    display: inline-block;
    margin-bottom: 0.5rem;
    font-size: 0.85rem;
    color: var(--app-text-3);
    text-decoration: none;
}

.back-link:hover {
    color: var(--app-heading);
}

.member-greeting { margin-bottom: 2rem; }

.member-greeting-eyebrow,
.member-card-eyebrow {
    font-size: 0.72rem;
    color: var(--app-text-3);
    font-weight: 600;
    margin-bottom: 0.5rem;
}

.member-greeting-name {
    font-size: 2.25rem;
    font-weight: 700;
    color: var(--app-heading);
    margin: 0 0 0.25rem 0;
}

.member-section-heading {
    margin-top: 2.5rem;
    margin-bottom: 1rem;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--app-heading);
    letter-spacing: 0.02em;
}

.member-card {
    background: var(--app-surface);
    border: 1px solid var(--app-border);
    border-radius: 12px;
    padding: 1.5rem;
    box-shadow: var(--app-shadow-xs);
    height: 100%;
}

.member-card-title {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--app-heading);
    margin: 0 0 0.75rem 0;
}

.member-account-tile {
    display: block;
    background: var(--app-surface);
    border: 1px solid var(--app-border);
    border-radius: 12px;
    padding: 1.25rem;
    text-decoration: none;
    color: inherit;
    transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;
}

.member-account-tile:hover {
    transform: translateY(-1px);
    box-shadow: var(--app-shadow);
    border-color: var(--app-teal);
    color: inherit;
    text-decoration: none;
}

.member-account-name {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--app-heading);
    margin-bottom: 0.5rem;
}

.member-account-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.member-pill {
    display: inline-block;
    padding: 0.18rem 0.6rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    background: rgba(var(--app-navy-rgb, 20, 33, 61), 0.08);
    color: var(--app-heading);
}

.member-pill-admin {
    background: var(--app-teal-50);
    color: var(--app-accent-text);
}

/* Sortable list tables: drop thead padding so the SortableHeader button fills the cell. */
.bd-list-table thead th {
    padding: 0;
}

/* ── Archived row styling ────────────────────────────────────────────────────
   Applied on list pages when the "Show archived" toggle surfaces records that
   are archived. Dims the row so live records read more strongly, and pairs
   with the inline "Archived" badge in the name cell. Hover restores opacity
   so the user can still see what they're about to click into.
*/

/* Browser quirk: CSS `opacity` doesn't render on <tr> in most browsers
   because table rows don't form a stacking context. Target the cells
   directly so the dim applies to every td/th in the row. The tile/row
   variants used inside detail-page related sections are normal block/inline
   elements so the property applies fine. */
.archived-row > td,
.archived-row > th,
.cd-tile-archived,
.cd-row-archived,
.acp-other-card-archived,
.acp-wg-member-archived,
.vd-attendee-archived {
    opacity: 0.55;
    transition: opacity 0.15s ease;
}

.archived-row:hover > td,
.archived-row:hover > th,
.cd-tile-archived:hover,
.cd-row-archived:hover,
.acp-other-card-archived:hover,
.acp-wg-member-archived:hover,
.vd-attendee-archived:hover {
    opacity: 0.85;
}

.archived-list-badge {
    display: inline-block;
    background: var(--app-surface-2);
    color: var(--app-text-3);
    font-size: 0.7rem;
    font-weight: 600;
    padding: 0.1rem 0.4rem;
    border-radius: 0.25rem;
    margin-left: 0.4rem;
    vertical-align: middle;
}

/* Opt-in white plate behind a brand logo on dark surfaces (admin "Logo backdrop" toggle).
   Global so it applies inside scoped components (sign-in header). */
.logo-plate { background: var(--app-logo-plate); border-radius: 8px; padding: 4px; }

/* ── Rich-text editor (Quill snow theme) in dark mode ─────────────────────── */

[data-bs-theme="dark"] .ql-toolbar.ql-snow,
[data-bs-theme="dark"] .ql-container.ql-snow { border-color: var(--app-border-2); }
[data-bs-theme="dark"] .ql-toolbar.ql-snow { background: var(--app-surface-2); }
[data-bs-theme="dark"] .ql-editor { background: var(--app-surface); color: var(--app-text); }
[data-bs-theme="dark"] .ql-editor.ql-blank::before { color: var(--app-text-4); }
[data-bs-theme="dark"] .ql-snow .ql-stroke { stroke: var(--app-text-2); }
[data-bs-theme="dark"] .ql-snow .ql-fill,
[data-bs-theme="dark"] .ql-snow .ql-stroke.ql-fill { fill: var(--app-text-2); }
[data-bs-theme="dark"] .ql-snow .ql-picker { color: var(--app-text-2); }
[data-bs-theme="dark"] .ql-snow .ql-picker-options { background: var(--app-surface); border-color: var(--app-border); }
[data-bs-theme="dark"] .ql-snow.ql-toolbar button:hover .ql-stroke,
[data-bs-theme="dark"] .ql-snow.ql-toolbar button.ql-active .ql-stroke,
[data-bs-theme="dark"] .ql-snow .ql-picker-label:hover .ql-stroke { stroke: var(--app-link); }
[data-bs-theme="dark"] .ql-snow.ql-toolbar button:hover .ql-fill,
[data-bs-theme="dark"] .ql-snow.ql-toolbar button.ql-active .ql-fill { fill: var(--app-link); }
[data-bs-theme="dark"] .ql-snow.ql-toolbar button:hover,
[data-bs-theme="dark"] .ql-snow.ql-toolbar button.ql-active,
[data-bs-theme="dark"] .ql-snow .ql-picker-label:hover,
[data-bs-theme="dark"] .ql-snow .ql-picker-item:hover { color: var(--app-link); }
[data-bs-theme="dark"] .ql-snow .ql-tooltip {
  background: var(--app-surface);
  color: var(--app-text);
  border-color: var(--app-border);
  box-shadow: var(--app-shadow);
}
[data-bs-theme="dark"] .ql-snow .ql-tooltip input[type=text] {
  background: var(--app-surface-sunken);
  color: var(--app-text);
  border-color: var(--app-border-2);
}
[data-bs-theme="dark"] .ql-snow a { color: var(--app-link); }

/* ── Wsha.Platform.Ai.Ui (AI connections and the Connect AI Gateway wizard) ───────
   The package reads --wp-<token>, then --app-<token>. Its "white" means a panel and its "navy" a
   heading, which our themes call surface and heading, so map those two (and the accents) here.
   Two of its colours are light-only literals; they're themed below until the package uses tokens. */
:root {
  --wp-white:    var(--app-surface);
  --wp-navy:     var(--app-heading);
  --wp-navy-400: var(--app-link);
  --wp-teal-600: var(--app-accent-text);
}
[data-bs-theme="dark"] .gw-warn { color: var(--app-warning-fg); }
[data-bs-theme="dark"] .gw-class-table tr.is-over > td { background: var(--app-warning-bg); }

/* A jump to a section (#id, the step rail, Setup's list) lands below the pinned top bar, not under it. */
.settings-card[id], section[id], .job-section, [data-anchor] {
  scroll-margin-top: calc(var(--app-chrome-top, 4rem) + 0.75rem);
}

/* ─────────────────────────────────────────────────────────
   Stacked tables: on phones each row becomes a small card, each cell a "label  value" line
   (the label from data-label). For tables whose actions would otherwise scroll off-screen.
   ───────────────────────────────────────────────────────── */
@media (max-width: 767.98px) {
  .table-stack thead { display: none; }
  .table-stack, .table-stack tbody, .table-stack tr, .table-stack td { display: block; width: 100%; }
  .table-stack tr { padding: 0.6rem 0; border-bottom: 1px solid var(--app-border); }
  .table-stack td { display: flex; justify-content: space-between; gap: 1rem; padding: 0.15rem 0; border: 0; text-align: right; }
  .table-stack td::before { content: attr(data-label); color: var(--app-text-3); font-size: 0.8rem; text-align: left; flex-shrink: 0; }
  .table-stack td[data-label=""]::before, .table-stack td:not([data-label])::before { content: none; }
  .table-stack td.table-stack__title { display: block; text-align: left; font-weight: 600; }
  .table-stack td.table-stack__actions { justify-content: flex-start; flex-wrap: wrap; }
}

/* A dialog owns the screen: the assistant's button and panel step aside until it closes (some dialogs
   render inside stacking contexts that put them under the dock's fixed layer). */
body:has(.modal.show) .ai-dock { visibility: hidden; }

/* ─────────────────────────────────────────────────────────
   Shell: skip link, rail tooltips, keyboard keys
   ───────────────────────────────────────────────────────── */

/* Off-screen until focused (the first Tab on any page), then pinned top-left above everything. */
.skip-link {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 2100;
  padding: 0.5rem 0.9rem;
  border-radius: 8px;
  background: var(--app-primary-bg);
  color: var(--app-primary-fg);
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--app-shadow-lg);
  transform: translateY(-200%);
  transition: transform var(--app-fast) ease;
}
.skip-link:focus,
.skip-link:focus-visible {
  transform: none;
  color: var(--app-primary-fg);
  outline: 2px solid var(--app-focus);
  outline-offset: 2px;
}
#main-content:focus { outline: none; }

/* The collapsed sidebar's labels, beside each icon on hover or keyboard focus (hotkeys.js places
   one shared element; the sidebar clips anything drawn inside it). */
.rail-tip {
  position: fixed;
  z-index: 2050;
  transform: translateY(-50%);
  padding: 0.3rem 0.6rem;
  border-radius: 6px;
  background: var(--app-text);
  color: var(--app-bg);
  font-size: 0.78rem;
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--app-fast) ease;
}
.rail-tip.is-on { opacity: 1; }

kbd {
  display: inline-block;
  min-width: 1.5em;
  padding: 0.05em 0.4em;
  border: 1px solid var(--app-border-2);
  border-bottom-width: 2px;
  border-radius: 5px;
  background: var(--app-surface-2);
  color: var(--app-text);
  font-family: inherit;
  font-size: 0.82em;
  font-weight: 600;
  line-height: 1.4;
  text-align: center;
  vertical-align: baseline;
  box-shadow: none;
}
