/* ==========================================================================
   Portal Visual Refresh — "Engineered Depth"
   --------------------------------------------------------------------------
   Single override sheet, loaded AFTER the vendored Color-Admin theme bundle
   (facebook/app.css light, transparent/app.css dark). The whole theme is
   driven by CSS custom properties, so redefining --bs-* and --app-* here
   reskins every page without editing templates.

   Light tokens live under :root; dark tokens under html.dark-mode (the class
   is set server-side per userprofile.dark_mode). html.dark-mode (0,0,1,1)
   outranks :root (0,0,1,0), so dark always wins when the class is present.

   Palette + component direction verified for WCAG 2.1 AA (>=4.5:1 text,
   >=3:1 non-text/focus) by the design council. Semantic hues are split into
   -text vs -surface/-fill tokens because the raw brand hues fail as text.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. LIGHT tokens
   -------------------------------------------------------------------------- */
:root {
  /* Accent */
  --bs-primary: #4361ee;
  --bs-primary-rgb: 67, 97, 238;
  --portal-primary-hover: #324ccc;
  --bs-link-color: #0062cc;            /* darkened for >=4.5:1 as inline text */
  --bs-link-color-rgb: 0, 98, 204;
  --bs-link-hover-color: #004a99;
  --app-theme: #4361ee;
  --app-component-active-bg: #4361ee;
  --app-component-focus-border-color: #4361ee;

  /* Semantic — fill hue (for solid fills / icons) */
  --bs-success: #12b76a;  --bs-success-rgb: 18, 183, 106;
  --bs-info:    #0ea5e9;  --bs-info-rgb: 14, 165, 233;
  --bs-warning: #f79009;  --bs-warning-rgb: 247, 144, 9;
  --bs-danger:  #f04438;  --bs-danger-rgb: 240, 68, 56;
  /* Semantic — accessible TEXT hue (>=4.5:1 on white / body bg) */
  --portal-success-text: #0a7a2f;
  --portal-info-text:    #0b6d8f;
  --portal-warning-text: #8a5a00;
  --portal-danger-text:  #c81e2e;
  /* Semantic — soft chip surface + border */
  --portal-success-surface: #e6f4ea; --portal-success-border: #0a7d30;
  --portal-info-surface:    #e2f2f8; --portal-info-border:    #0b6d8f;
  --portal-warning-surface: #fff3e0; --portal-warning-border: #8a5a00;
  --portal-danger-surface:  #fdeaea; --portal-danger-border:  #c81e2e;
  --portal-neutral-surface: #eef1f6; --portal-neutral-border: #cbd3e0;
  --portal-neutral-text:    #475569;

  /* Surfaces + text */
  --bs-body-bg: #eef1f6;   --bs-body-bg-rgb: 238, 241, 246;
  --bs-body-color: #1e293b; --bs-body-color-rgb: 30, 41, 59;
  --portal-surface: #ffffff;
  --portal-surface-elevated: #ffffff;
  --portal-inset: #f6f8fb;
  --bs-secondary-color: #64748b;   /* muted text */
  --portal-text-muted: #64748b;
  --bs-border-color: #e2e7ef;
  --bs-border-color-translucent: rgba(15, 23, 42, 0.08);

  /* Chrome */
  --app-header-bg: rgba(255, 255, 255, 0.72);
  --app-header-color: #1e293b;
  --app-sidebar-bg: #0f1729;
  --app-component-bg: #ffffff;
  --app-component-color: #1e293b;
  --app-component-dropdown-bg: #ffffff;

  /* Shape */
  --bs-border-radius: 0.5rem;      /* 8px base */
  --bs-border-radius-sm: 0.375rem; /* 6px */
  --bs-border-radius-lg: 0.75rem;  /* 12px */
  --portal-radius-card: 0.75rem;   /* 12px */
  --portal-radius-chip: 0.375rem;  /* 6px */

  /* Elevation (soft, cool, low-alpha) */
  --portal-shadow-1: 0 1px 2px rgba(16,24,40,.04), 0 1px 3px rgba(16,24,40,.06);
  --portal-shadow-2: 0 4px 8px -2px rgba(16,24,40,.08), 0 2px 4px -2px rgba(16,24,40,.06);
  --portal-shadow-3: 0 12px 24px -6px rgba(16,24,40,.12), 0 4px 8px -4px rgba(16,24,40,.08);

  /* Focus (dual-ring halo — inner light, outer dark) */
  --portal-focus-ring: 0 0 0 2px #ffffff, 0 0 0 4px #4361ee;

  /* Typography */
  --bs-body-font-family: "Inter", "Open Sans", system-ui, "Segoe UI", Roboto, sans-serif;
  --bs-body-font-size: 0.8125rem;  /* 13px */
  --bs-body-line-height: 1.5;
}

/* --------------------------------------------------------------------------
   2. DARK tokens
   -------------------------------------------------------------------------- */
html.dark-mode {
  --bs-primary: #5c7cff;
  --bs-primary-rgb: 92, 124, 255;
  --portal-primary-hover: #7089ff;
  --bs-link-color: #66a8ff;            /* passes >=3:1 on cards */
  --bs-link-color-rgb: 102, 168, 255;
  --bs-link-hover-color: #8bbcff;
  --app-theme: #5c7cff;
  --app-component-active-bg: #5c7cff;
  --app-component-focus-border-color: #5c7cff;

  --bs-success: #32d583; --bs-success-rgb: 50, 213, 131;
  --bs-info:    #38bdf8; --bs-info-rgb: 56, 189, 248;
  --bs-warning: #fdb022; --bs-warning-rgb: 253, 176, 34;
  --bs-danger:  #f97066; --bs-danger-rgb: 249, 112, 102;
  /* dark: bright hues pass as text on the card surface */
  --portal-success-text: #32d583;
  --portal-info-text:    #38bdf8;
  --portal-warning-text: #fdb022;
  --portal-danger-text:  #ff7a5e;
  --portal-success-surface: rgba(50,213,131,.14);  --portal-success-border: rgba(50,213,131,.40);
  --portal-info-surface:    rgba(56,189,248,.14);   --portal-info-border:    rgba(56,189,248,.40);
  --portal-warning-surface: rgba(253,176,34,.14);   --portal-warning-border: rgba(253,176,34,.40);
  --portal-danger-surface:  rgba(249,112,102,.14);  --portal-danger-border:  rgba(249,112,102,.40);
  --portal-neutral-surface: rgba(255,255,255,.06);  --portal-neutral-border: rgba(255,255,255,.18);
  --portal-neutral-text:    #94a1b2;

  --bs-body-bg: #0b1120;   --bs-body-bg-rgb: 11, 17, 32;
  --bs-body-color: #e6ebf4; --bs-body-color-rgb: 230, 235, 244;
  --portal-surface: #131a2b;
  --portal-surface-elevated: #1a2338;
  --portal-inset: #0f1729;
  --bs-secondary-color: #94a1b2;
  --portal-text-muted: #94a1b2;
  --bs-border-color: rgba(255, 255, 255, 0.08);
  --bs-border-color-translucent: rgba(255, 255, 255, 0.08);

  --app-header-bg: rgba(11, 17, 32, 0.72);   /* fixes the white-header-in-dark bug */
  --app-header-color: #e6ebf4;
  --app-sidebar-bg: #0a0f1c;
  --app-component-bg: #131a2b;
  --app-component-color: #e6ebf4;
  --app-component-dropdown-bg: #1a2338;

  /* Dark: shadows read poorly; lean on the surface ramp + a hairline border. */
  --portal-shadow-1: 0 1px 2px rgba(0,0,0,.40);
  --portal-shadow-2: 0 4px 12px rgba(0,0,0,.50);
  --portal-shadow-3: 0 16px 32px rgba(0,0,0,.60);
  --portal-focus-ring: 0 0 0 2px #0b1120, 0 0 0 4px #5c7cff;
}

/* --------------------------------------------------------------------------
   2b. securemail-v2 (--sm-*) tokens folded into the global system.
   Defined once as aliases to the unified tokens — because they reference
   custom properties that change per mode (:root vs html.dark-mode), each
   --sm-* resolves to the correct light/dark value automatically. The local
   light/dark --sm-* blocks were removed from the securemessage_*_v2 templates
   so that track stops maintaining a divergent palette.
   -------------------------------------------------------------------------- */
:root {
  --sm-bg: var(--portal-surface);
  --sm-bg-secondary: var(--portal-inset);
  --sm-bg-hover: var(--portal-neutral-surface);
  --sm-border: var(--bs-border-color);
  --sm-border-light: var(--bs-border-color);
  --sm-text: var(--bs-body-color);
  --sm-text-muted: var(--portal-text-muted);
  --sm-text-secondary: var(--bs-secondary-color);
  --sm-primary: var(--bs-primary);
  --sm-success: var(--portal-success-text);
  --sm-warning: var(--portal-warning-text);
  --sm-danger: var(--portal-danger-text);
  --sm-info: var(--portal-info-text);
  --sm-drop-bg: var(--portal-surface-elevated);
  --sm-drop-border: var(--bs-border-color);
  --sm-drop-hover-bg: rgba(var(--bs-primary-rgb), 0.10);
  --sm-drop-hover-border: var(--bs-primary);
  --sm-file-bg: var(--portal-inset);
  --sm-file-border: var(--bs-border-color);
  --sm-input-bg: var(--portal-inset);
  --sm-input-focus: rgba(var(--bs-primary-rgb), 0.25);
}

/* --------------------------------------------------------------------------
   2c. App background — a modern accent "aurora" gradient replacing the flat fill
   (light) and the stock mountain photo cover (dark). .app-content is transparent
   so this shows on every page; opaque cards pop against it.
   -------------------------------------------------------------------------- */
body {
  background-color: var(--bs-body-bg) !important;
  background-image:
    radial-gradient(1200px 760px at 88% 6%, rgba(99, 102, 241, 0.30), transparent 58%),
    radial-gradient(1000px 680px at 2% 22%, rgba(139, 92, 246, 0.22), transparent 58%),
    radial-gradient(950px 660px at 55% 112%, rgba(56, 189, 248, 0.18), transparent 58%) !important;
  background-repeat: no-repeat !important;
  background-attachment: fixed !important;
}
/* Dark: override the fixed .app-cover photo layer with a brighter aurora over blue-black.
   Glows sit inside the content area (not up behind the frosted header) and are punchy
   enough to actually read as an aurora on the dark base. */
html.dark-mode .app-cover {
  background-image:
    radial-gradient(1300px 820px at 85% 8%, rgba(92, 124, 255, 0.45), transparent 55%),
    radial-gradient(1100px 720px at 3% 24%, rgba(124, 92, 255, 0.30), transparent 55%),
    radial-gradient(1000px 700px at 55% 110%, rgba(56, 189, 248, 0.18), transparent 55%),
    linear-gradient(180deg, #0b1120 0%, #0a0f1c 100%) !important;
  background-size: cover !important;
  background-repeat: no-repeat !important;
}
html.dark-mode .app-cover:before { display: none !important; }  /* drop the photo's dark overlay */

/* --------------------------------------------------------------------------
   3. Base typography / body
   -------------------------------------------------------------------------- */
body {
  font-family: var(--bs-body-font-family);
  font-size: var(--bs-body-font-size);
  line-height: var(--bs-body-line-height);
  color: var(--bs-body-color);
}
.text-muted, .text-secondary { color: var(--portal-text-muted) !important; }
table, .datatable, .stat-number, .portal-stat__value { font-variant-numeric: tabular-nums; }

/* Page header: signature indigo underline */
.page-header {
  font-size: 1.375rem; font-weight: 600; letter-spacing: -0.01em;
  color: var(--bs-body-color); margin-bottom: 1.25rem; position: relative;
}
.page-header::after {
  content: ""; position: absolute; left: 0; bottom: -6px;
  width: 32px; height: 3px; border-radius: 3px; background: var(--bs-primary);
}

/* --------------------------------------------------------------------------
   4. Chrome — header (frosted glass) + sidebar
   -------------------------------------------------------------------------- */
.app-header {
  background: var(--app-header-bg) !important;
  color: var(--app-header-color);
  -webkit-backdrop-filter: blur(12px) saturate(180%);
  backdrop-filter: blur(12px) saturate(180%);
  border-bottom: 1px solid var(--bs-border-color);
}
/* Topbar light/dark toggle — a <button> styled to match the header icon links */
.app-header .navbar-nav .navbar-item .theme-toggle {
  background: transparent; border: 0; box-shadow: none;
  color: var(--app-header-color); display: flex; align-items: center;
  height: 100%; padding: 0 1rem; font-size: 1.125rem; line-height: 1;
  transition: color .15s ease;
}
.app-header .navbar-nav .navbar-item .theme-toggle:hover { color: var(--bs-primary); }
.app-header .navbar-nav .navbar-item form { display: flex; height: 100%; margin: 0; }

/* "Ctrl K" hint inside the topbar search box (which opens the command palette) */
.app-header .navbar-form .form-group { position: relative; }
.portal-search-kbd {
  position: absolute; right: 2.25rem; top: 50%; transform: translateY(-50%);
  font-size: .625rem; line-height: 1; color: var(--portal-text-muted);
  background: var(--portal-inset); border: 1px solid var(--bs-border-color);
  border-radius: 4px; padding: .15rem .35rem; pointer-events: none; white-space: nowrap;
}
#portal-search-input { cursor: pointer; }

/* Sidebar is theme-aware so the toggle visibly flips it:
   - LIGHT mode: base.html adds `app-with-light-sidebar` -> the theme paints a solid
     white sidebar with legible gray text (handled entirely by the vendored theme).
   - DARK mode: force a solid dark surface (the theme's gradient mode otherwise leaves
     the bar transparent) plus custom hover/active polish.
   Custom rules are scoped to html.dark-mode so they never fight the light sidebar. */
html.dark-mode .app-sidebar { background: var(--app-sidebar-bg) !important; }
html.dark-mode .app-sidebar .menu .menu-item > .menu-link { transition: background-color .15s ease, color .15s ease; }
html.dark-mode .app-sidebar .menu .menu-item > .menu-link:hover {
  background-color: rgba(255, 255, 255, 0.05);
  color: #e6ebf4;
}
/* Active nav item — leaf marked by JS from the current URL. Works in both the light
   (white) and dark sidebar, and for nested submenu items (indigo accent + left bar). */
.app-sidebar .menu .menu-item.active > .menu-link,
.app-sidebar .menu .menu-item.active > .menu-link .menu-text { color: var(--bs-primary) !important; font-weight: 600; }
.app-sidebar .menu .menu-item.active > .menu-link .menu-icon,
.app-sidebar .menu .menu-item.active > .menu-link .menu-icon > i { color: var(--bs-primary) !important; }
.app-sidebar .menu > .menu-item.active > .menu-link { box-shadow: inset 3px 0 0 var(--bs-primary); background: rgba(var(--bs-primary-rgb), .10); }
html.dark-mode .app-sidebar .menu > .menu-item.active > .menu-link { background: rgba(var(--bs-primary-rgb), .16); }

/* --------------------------------------------------------------------------
   5. Cards + surfaces
   -------------------------------------------------------------------------- */
.card {
  background-color: var(--portal-surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--portal-radius-card);
  box-shadow: var(--portal-shadow-1);
}
.card .card-header {
  background: transparent;
  border-bottom: 1px solid var(--bs-border-color);
  font-weight: 600;
  color: var(--bs-body-color);
}
.dropdown-menu, .modal-content { background-color: var(--portal-surface-elevated); }

/* Lift only interactive cards; static data cards must not jitter. */
a.card, .card[role="button"], .card[data-tab], .card.stat-card[data-tab] {
  transition: transform .15s ease, box-shadow .15s ease;
}
a.card:hover, .card[role="button"]:hover, .card[data-tab]:hover {
  transform: translateY(-2px); box-shadow: var(--portal-shadow-2);
}

/* Unified stat tile (partials/stat_tile.html) — replaces the per-page reinventions
   (office_detail .stat-card gradient, device_list gap tiles). */
.portal-stat {
  display: block; height: 100%; text-decoration: none;
  background: var(--portal-surface); color: var(--bs-body-color);
  border: 1px solid var(--bs-border-color); border-radius: var(--portal-radius-card);
  box-shadow: var(--portal-shadow-1); padding: 1rem 1.25rem;
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
a.portal-stat, .portal-stat[role="button"] { cursor: pointer; }
a.portal-stat:hover, .portal-stat[role="button"]:hover { transform: translateY(-2px); box-shadow: var(--portal-shadow-2); }
.portal-stat--active { border-color: var(--bs-primary); box-shadow: 0 0 0 1px var(--bs-primary), var(--portal-shadow-1); }
.portal-stat__body { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.portal-stat__value { font-size: 1.75rem; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; color: var(--bs-primary); }
.portal-stat__label { font-size: .6875rem; text-transform: uppercase; letter-spacing: .4px; font-weight: 600; color: var(--portal-text-muted); margin-top: .4rem; }
.portal-stat__icon {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center; font-size: 1.1rem;
  background: rgba(var(--bs-primary-rgb), .12); color: var(--bs-primary);
}
.portal-stat--success .portal-stat__value, .portal-stat--success .portal-stat__icon { color: var(--portal-success-text); }
.portal-stat--success .portal-stat__icon { background: var(--portal-success-surface); }
.portal-stat--warning .portal-stat__value, .portal-stat--warning .portal-stat__icon { color: var(--portal-warning-text); }
.portal-stat--warning .portal-stat__icon { background: var(--portal-warning-surface); }
.portal-stat--danger .portal-stat__value, .portal-stat--danger .portal-stat__icon { color: var(--portal-danger-text); }
.portal-stat--danger .portal-stat__icon { background: var(--portal-danger-surface); }
.portal-stat--info .portal-stat__value, .portal-stat--info .portal-stat__icon { color: var(--portal-info-text); }
.portal-stat--info .portal-stat__icon { background: var(--portal-info-surface); }
.portal-stat--muted .portal-stat__value, .portal-stat--secondary .portal-stat__value { color: var(--portal-text-muted); }
.portal-stat--muted .portal-stat__icon, .portal-stat--secondary .portal-stat__icon { background: var(--portal-neutral-surface); color: var(--portal-text-muted); }

/* --------------------------------------------------------------------------
   6. Unified status chip — zero-churn aliases over the 3 legacy badge idioms
   Existing markup keeps working; it just renders with the new recipe.
   -------------------------------------------------------------------------- */
.badge {
  border-radius: var(--portal-radius-chip);
  font-weight: 600;
  font-size: 0.6875rem;               /* 11px */
  letter-spacing: .2px;
  padding: 0.25rem 0.5rem;
}
/* outline-pill idiom (adinfo status_badges) + solid bg idiom -> soft chip */
.badge.border.border-success.text-success, .badge.bg-success {
  background: var(--portal-success-surface) !important;
  color: var(--portal-success-text) !important;
  border: 1px solid var(--portal-success-border) !important;
}
.badge.border.border-info.text-info, .badge.bg-info {
  background: var(--portal-info-surface) !important;
  color: var(--portal-info-text) !important;
  border: 1px solid var(--portal-info-border) !important;
}
.badge.border.border-warning.text-warning, .badge.bg-warning {
  background: var(--portal-warning-surface) !important;
  color: var(--portal-warning-text) !important;
  border: 1px solid var(--portal-warning-border) !important;
}
.badge.border.border-danger.text-danger, .badge.bg-danger {
  background: var(--portal-danger-surface) !important;
  color: var(--portal-danger-text) !important;
  border: 1px solid var(--portal-danger-border) !important;
}
.badge.border.border-secondary.text-secondary, .badge.bg-secondary,
.badge.bg-light.text-dark, .badge.rounded-pill.border {
  background: var(--portal-neutral-surface) !important;
  color: var(--portal-neutral-text) !important;
  border: 1px solid var(--portal-neutral-border) !important;
}
.badge.bg-primary {
  background: rgba(var(--bs-primary-rgb), .14) !important;
  color: var(--bs-primary) !important;
  border: 1px solid rgba(var(--bs-primary-rgb), .30) !important;
}
.badge.bg-dark {
  background: var(--portal-neutral-surface) !important;
  color: var(--bs-body-color) !important;
  border: 1px solid var(--bs-border-color) !important;
}

/* --------------------------------------------------------------------------
   7. Buttons — rationalized; legacy sizes/variants aliased
   -------------------------------------------------------------------------- */
.btn { border-radius: var(--bs-border-radius); font-weight: 500; transition: background-color .15s ease, border-color .15s ease, color .15s ease, transform .15s ease, box-shadow .15s ease; }
.btn-primary { --bs-btn-bg: var(--bs-primary); --bs-btn-border-color: var(--bs-primary); --bs-btn-hover-bg: var(--portal-primary-hover); --bs-btn-hover-border-color: var(--portal-primary-hover); }
.btn-primary:hover { transform: translateY(-1px); }
.btn-xs { --bs-btn-padding-y: .25rem; --bs-btn-padding-x: .5rem; --bs-btn-font-size: .75rem; border-radius: var(--bs-border-radius-sm); }  /* -> sm */
.btn-xl { --bs-btn-padding-y: .625rem; --bs-btn-padding-x: 1.25rem; --bs-btn-font-size: 1rem; }  /* -> lg */
.btn-flat { box-shadow: none; }  /* -> ghost-ish */
.btn-default { --bs-btn-bg: var(--portal-inset); --bs-btn-border-color: var(--bs-border-color); --bs-btn-color: var(--bs-body-color); }

/* --------------------------------------------------------------------------
   8. Tables + inputs
   -------------------------------------------------------------------------- */
.table { --bs-table-bg: transparent; color: var(--bs-body-color); }
.table > thead th, .table > thead > tr > th {
  text-transform: uppercase; font-size: 0.6875rem; letter-spacing: .4px;
  font-weight: 600; color: var(--portal-text-muted);
  border-bottom: 2px solid var(--bs-border-color);
}
.table > tbody > tr { border-color: var(--bs-border-color); }
.table.table-hover > tbody > tr:hover > * { background-color: rgba(var(--bs-primary-rgb), 0.05); }

.form-control, .form-select {
  background-color: var(--portal-inset);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  color: var(--bs-body-color);
}
.form-control:focus, .form-select:focus {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 3px rgba(var(--bs-primary-rgb), 0.25);
}
.form-label { font-size: 0.75rem; font-weight: 600; color: var(--portal-text-muted); }

/* --------------------------------------------------------------------------
   8b. DataTables controls — the search / length / pagination / info chrome that
   wraps ~40 list pages. Themed to match the refreshed inputs + buttons.
   -------------------------------------------------------------------------- */
.dataTables_wrapper { padding-top: .25rem; }
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select {
  background-color: var(--portal-inset);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  color: var(--bs-body-color);
  padding: .3rem .6rem; margin-left: .4rem;
}
.dataTables_wrapper .dataTables_filter input:focus,
.dataTables_wrapper .dataTables_length select:focus {
  outline: none; border-color: var(--bs-primary);
  box-shadow: 0 0 0 3px rgba(var(--bs-primary-rgb), .25);
}
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_info { color: var(--portal-text-muted); font-size: .75rem; }
.dataTables_wrapper .dataTables_paginate .page-link { color: var(--bs-link-color); border-color: var(--bs-border-color); background: transparent; }
.dataTables_wrapper .dataTables_paginate .page-item.active .page-link { background: var(--bs-primary); border-color: var(--bs-primary); color: #fff; }
.dataTables_wrapper .dataTables_paginate .page-link:hover { background: rgba(var(--bs-primary-rgb), .10); }
.dataTables_wrapper .dataTables_paginate .page-item.disabled .page-link { color: var(--portal-text-muted); opacity: .55; }
/* legacy (non-bootstrap5) DataTables pagination buttons, just in case */
.dataTables_wrapper .dataTables_paginate .paginate_button.current { background: var(--bs-primary) !important; border-radius: var(--bs-border-radius-sm); color: #fff !important; border: 0; }

/* --------------------------------------------------------------------------
   9. Focus-visible — accessible dual-ring on every interactive element
   -------------------------------------------------------------------------- */
a:focus-visible, button:focus-visible, .btn:focus-visible,
.form-control:focus-visible, .form-select:focus-visible,
[tabindex]:focus-visible, .nav-link:focus-visible, .page-link:focus-visible,
.dropdown-item:focus-visible, [data-tab]:focus-visible {
  outline: none;
  box-shadow: var(--portal-focus-ring);
  border-radius: var(--bs-border-radius-sm);
}

/* --------------------------------------------------------------------------
   10. Toast container (Django messages -> toasts; markup added in base.html)
   -------------------------------------------------------------------------- */
.portal-toast-container { z-index: 1090; top: 4rem; }  /* clear the fixed app-header (z-index 1020) so toasts are readable */
.portal-toast { background: var(--portal-surface-elevated); color: var(--bs-body-color); border: 1px solid var(--bs-border-color); box-shadow: var(--portal-shadow-3); border-radius: var(--bs-border-radius); }
.portal-toast .toast-body { display: flex; align-items: center; gap: .5rem; }
.portal-toast--success { border-left: 3px solid var(--portal-success-border); }
.portal-toast--info    { border-left: 3px solid var(--portal-info-border); }
.portal-toast--warning { border-left: 3px solid var(--portal-warning-border); }
.portal-toast--danger  { border-left: 3px solid var(--portal-danger-border); }

/* --------------------------------------------------------------------------
   11. Command palette (Ctrl/Cmd-K) — base.html markup + JS
   -------------------------------------------------------------------------- */
.portal-cmdk { position: fixed; inset: 0; z-index: 1200; }
.portal-cmdk[hidden] { display: none; }
.portal-cmdk__backdrop { position: absolute; inset: 0; background: rgba(11, 17, 32, 0.55); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
.portal-cmdk__panel {
  position: relative; margin: 12vh auto 0; width: min(880px, calc(100vw - 2rem));
  background: var(--portal-surface-elevated); color: var(--bs-body-color);
  border: 1px solid var(--bs-border-color); border-radius: var(--bs-border-radius-lg);
  box-shadow: var(--portal-shadow-3); overflow: hidden;
}
.portal-cmdk__inputwrap { display: flex; align-items: center; gap: .625rem; padding: .875rem 1rem; border-bottom: 1px solid var(--bs-border-color); }
.portal-cmdk__searchicon { color: var(--portal-text-muted); font-size: 1rem; }
.portal-cmdk__input { flex: 1 1 auto; border: 0; outline: none; background: transparent; color: var(--bs-body-color); font-size: 1rem; }
.portal-cmdk__input::placeholder { color: var(--portal-text-muted); }
.portal-cmdk kbd, .portal-cmdk__esc { background: var(--portal-inset); border: 1px solid var(--bs-border-color); border-radius: 4px; padding: .05rem .35rem; font-size: .6875rem; color: var(--portal-text-muted); }
.portal-cmdk__results { max-height: 52vh; overflow-y: auto; padding: .375rem; }
.portal-cmdk__empty { padding: 1.25rem 1rem; color: var(--portal-text-muted); text-align: center; font-size: .8125rem; }
.portal-cmdk__item { display: flex; align-items: center; gap: .625rem; padding: .5rem .625rem; border-radius: var(--bs-border-radius); color: var(--bs-body-color); text-decoration: none; }
.portal-cmdk__item.is-active { background: rgba(var(--bs-primary-rgb), .14); }
.portal-cmdk__itemicon { width: 1.25rem; text-align: center; color: var(--bs-primary); }
.portal-cmdk__itemtitle { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.portal-cmdk__itemsub { color: var(--portal-text-muted); font-size: .75rem; white-space: nowrap; }
.portal-cmdk__itemtype { font-size: .625rem; text-transform: uppercase; letter-spacing: .3px; font-weight: 600; color: var(--portal-text-muted); background: var(--portal-neutral-surface); border: 1px solid var(--bs-border-color); border-radius: 4px; padding: .1rem .35rem; }
.portal-cmdk__footer { display: flex; gap: 1rem; align-items: center; padding: .5rem 1rem; border-top: 1px solid var(--bs-border-color); color: var(--portal-text-muted); font-size: .6875rem; }
body.portal-cmdk-open { overflow: hidden; }

/* --------------------------------------------------------------------------
   12. Motion — subtle, gated by prefers-reduced-motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  #content > .page-header, #content .card { animation: portalFadeInUp .28s ease both; }
  @keyframes portalFadeInUp { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
}
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ==========================================================================
   14. Bold visual pass — sectioned sidebar, active pill, richer cards/buttons
   ========================================================================== */

/* -- Sidebar: submenu parents become uppercase SECTION LABELS (grouped nav).
   pointer-events:none keeps them as pure labels (submenus stay open); scoped to
   the non-minified sidebar so icon-only/flyout mode still works when collapsed. -- */
.app:not(.app-sidebar-minified) .app-sidebar .menu > .menu-item.has-sub > .menu-link {
  pointer-events: none;
  padding: 1.05rem 20px 0.3rem;
  min-height: 0;
}
.app-sidebar .menu > .menu-item.has-sub > .menu-link .menu-icon,
.app-sidebar .menu > .menu-item.has-sub > .menu-link .menu-caret { display: none !important; }
.app-sidebar .menu > .menu-item.has-sub > .menu-link .menu-text {
  font-size: .625rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--portal-text-muted) !important; opacity: .8;
}

/* -- Sidebar: every nav link is a rounded pill with hover/active fill -- */
.app-sidebar .menu .menu-item > .menu-link {
  border-radius: 9px; margin: 1px 8px; padding: .5rem .65rem;
  transition: background-color .14s ease, color .14s ease;
}
.app-sidebar .menu .menu-item:not(.has-sub) > .menu-link:hover {
  background: rgba(var(--bs-primary-rgb), .09) !important;
}
.app-sidebar .menu .menu-item.active > .menu-link {
  background: rgba(var(--bs-primary-rgb), .16) !important;
  color: var(--bs-primary) !important;
  box-shadow: none;
}
.app-sidebar .menu .menu-item.active > .menu-link .menu-icon,
.app-sidebar .menu .menu-item.active > .menu-link .menu-icon > i,
.app-sidebar .menu .menu-item.active > .menu-link .menu-text { color: var(--bs-primary) !important; }

/* -- Cards: subtle accent-tinted header + a touch more elevation -- */
.card { box-shadow: var(--portal-shadow-2); }
.card > .card-header {
  background: linear-gradient(180deg, rgba(var(--bs-primary-rgb), .05), transparent);
}

/* -- Primary buttons: soft top sheen + accent glow for depth -- */
.btn-primary {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, 0));
  box-shadow: 0 1px 2px rgba(16, 24, 40, .10), 0 2px 8px -2px rgba(var(--bs-primary-rgb), .45);
}
.btn-primary:hover {
  box-shadow: 0 2px 4px rgba(16, 24, 40, .12), 0 6px 14px -3px rgba(var(--bs-primary-rgb), .55);
}

/* -- Page header: bigger, more presence -- */
.page-header { font-size: 1.5rem; letter-spacing: -.015em; }
.page-header::after { width: 40px; height: 3px; }

/* ==========================================================================
   15. DataTables loading polish — fade the table in once initialized (instead of
   flashing the raw, full-height unpaginated table), with a shimmer skeleton while
   it initializes. Guarded by html.js + a JS safety-net so a table is never left
   hidden if DataTables fails; the :has() shimmer is a progressive enhancement.
   ========================================================================== */
html.js table.datatable:not(.dataTable) { opacity: 0; }
table.datatable { transition: opacity .3s ease; }
table.datatable.dataTable { opacity: 1; }

html.js :is(.table-responsive, .card-body):has(> table.datatable:not(.dataTable)) {
  position: relative;
  min-height: 160px;
}
html.js :is(.table-responsive, .card-body):has(> table.datatable:not(.dataTable))::after {
  content: ""; position: absolute; inset: 0; border-radius: var(--bs-border-radius);
  background: linear-gradient(100deg, var(--portal-inset) 30%, rgba(var(--bs-primary-rgb), .10) 50%, var(--portal-inset) 70%) 0 0 / 200% 100%;
  animation: portalShimmer 1.2s linear infinite;
}
@keyframes portalShimmer { to { background-position: -200% 0; } }

/* ==========================================================================
   16. Mail Tracking page utilities — replace per-element inline styles.
   (The section-row tint was hardcoded rgba(255,255,255,.06), invisible in light
   mode; a token fixes it in both modes.)
   ========================================================================== */
.mail-section > td { background: var(--portal-inset); }
.mail-raw { max-height: 400px; overflow-y: auto; white-space: pre-wrap; word-break: break-word; }
.mail-col-narrow { width: 1%; white-space: nowrap; }
.mail-ls { letter-spacing: .05em; }
.mail-w-80 { width: 80px; } .mail-w-100 { width: 100px; } .mail-w-120 { width: 120px; }
.mail-w-180 { width: 180px; } .mail-w-220 { width: 220px; }
.mail-mw-160 { max-width: 160px; } .mail-mw-180 { max-width: 180px; } .mail-mw-200 { max-width: 200px; }
.mail-mw-220 { max-width: 220px; } .mail-mw-560 { max-width: 560px; }
