/* LandmarkLouie overrides — load AFTER design-tokens-complete.css and platform.css.
 * Purpose: anchor LL-specific choices. Everything else flows from the tokens.
 */

/* ============================================================
 * Token consolidation — kill the stray Ford-blue.
 * index.html's inline :root is a stale LouieAuto "Ford Blue" scheme
 * that was never migrated to gold: --accent/--accent2/--sidebar-accent/
 * --ford-*/--chart-blue are still blue, and --color-gold is literally
 * #1a56db (blue). They bleed through wherever louie-theme.css's gold
 * didn't override, which is the "blue Upload Listings / blue cross-sell
 * dashboard" inconsistency. This block loads after that inline :root,
 * so it wins — repointing every brand-accent var to ONE gold primary.
 *
 * Contrast: #8a6520 = 5.3:1 on white, safe as text AND as a button bg
 * with white text (every legacy blue button uses white text).
 * Semantic literals (blue "you" bars, red "competitor" bars) are
 * hardcoded, not vars, so they're untouched.
 * NOTE: retiring the inline :root entirely is a later monolith edit.
 * ============================================================ */
:root {
  /* Accent — #8a712a = 4.69:1 white-on-fill AND gold-on-white, validated live
   * on the Lender Rate Sheet headers (was #c9a84c at 2.29:1, fail). */
  --accent:        #8a712a;
  --accent2:       #8a712a;
  --accent-bg:     rgba(201,168,76,0.10);
  --color-accent:  #8a712a;
  --color-gold:    #8a712a;            /* AA-safe gold everywhere var()-driven */
  --color-gold-text: #8a712a;
  --color-gold-dark: #6f4f18;
  --ford-blue:     #8a712a;            /* legacy alias, now gold */
  --ford-light:    #a67c32;
  --chart-blue:    #c9a84c;            /* bright gold for chart fills (large, no text) */
  /* sidebar-accent stays bright: it sits on the DARK navy sidebar where
   * #c9a84c passes; the auditor's #b29136 (computed vs white) would HURT here. */
  --sidebar-accent:#c9a84c;

  /* Muted text — 4.57:1 on white AND on the #f8f6f0 app bg (was ~2.5:1, fail). */
  --color-text-muted: #5e728d;
  --ford-silver:      #5e728d;

  /* Semantic colors split by role: text (on white) / fill (white text sits on
   * it) / tint (dark text sits on it). Darkening one token alone breaks the
   * others — pills, tinted cards, and data text each need their own variant. */
  --red-text:   #c81e1e;  --red-fill:   #dc2626;  --red-tint:   rgba(220,38,38,0.10);
  --amber-text: #a36907;  --amber-fill: #b45309;  --amber-tint: rgba(245,158,11,0.12);
  --green-text: #178841;  --green-fill: #16a34a;  --green-tint: rgba(34,197,94,0.12);
}

body {
  font-family: var(--font-sans) !important;
}

/* Code/mono shouldn't pick up sans — preserve mono stack */
pre, code, kbd, samp, [class*="code-block"] {
  font-family: var(--font-mono) !important;
}

/* ============================================================
 * Awards polish — motion. Additive only: no color/layout change.
 *  - Dashboard cards rise in on view load. Safe: the home dash is
 *    built by renderHomeDash() on navigation, not by the page's two
 *    setIntervals (token refresh + STIP checker), so this does not
 *    replay on a background tick.
 *  - Chat messages ease in once as they're appended. Streaming
 *    rewrites only the inner .msg-bubble (cel), so the .msg wrapper
 *    animates a single time with no flicker.
 * Fully disabled under prefers-reduced-motion.
 * ============================================================ */
@keyframes ll-rise   { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:translateY(0); } }
@keyframes ll-msg-in { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:translateY(0); } }

.hkpi, .home-card, .rpt-card, .cs-card, .mt-kpi {
  animation: ll-rise .38s cubic-bezier(.21,.6,.35,1) both;
}
/* subtle stagger across the home KPI / card grid */
.hkpi:nth-child(2),  .home-card:nth-child(2)  { animation-delay:.05s; }
.hkpi:nth-child(3),  .home-card:nth-child(3)  { animation-delay:.10s; }
.hkpi:nth-child(4),  .home-card:nth-child(4)  { animation-delay:.15s; }
.hkpi:nth-child(5),  .home-card:nth-child(5)  { animation-delay:.20s; }
.hkpi:nth-child(n+6),.home-card:nth-child(n+6){ animation-delay:.25s; }

/* the signature interaction: Louie's replies (and your prompts) ease in */
.msg.assistant, .msg.user { animation: ll-msg-in .28s ease-out both; }

@media (prefers-reduced-motion: reduce) {
  .hkpi, .home-card, .rpt-card, .cs-card, .mt-kpi,
  .msg.assistant, .msg.user { animation: none !important; }
}

/* ============================================================
 * Modal unification — one chrome across the 3 legacy families
 * (.modal-overlay/.modal, .gl-modal-overlay/.gl-modal,
 *  .cs-upload-modal). They had 3 different backdrops, borders,
 * shadows and close buttons. This harmonizes the *chrome* only —
 * no structural/layout edits (widths and z-index left intact, as
 * those carry intent). Result reads as one designed system.
 * ============================================================ */
@keyframes ll-overlay-in { from { opacity:0; } to { opacity:1; } }
@keyframes ll-modal-in   { from { opacity:0; transform:translateY(10px) scale(.985); } to { opacity:1; transform:none; } }

/* ============================================================
 * .ll-overlay / .ll-modal family — 20+ modules create these
 * elements via className='ll-overlay' with no inline styles.
 * Without this CSS they render as invisible inline divs.
 * ============================================================ */
.ll-overlay {
  position: fixed;
  inset: 0;
  z-index: 9500;
  background: rgba(7, 26, 46, 0.92);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: ll-overlay-in .18s ease-out both;
}
.ll-modal {
  background: #0d1f35;
  border: 1px solid rgba(43, 127, 224, 0.2);
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  margin: 48px auto 48px;
  width: 90%;
  overflow: hidden;
  animation: ll-modal-in .24s cubic-bezier(.21, .6, .35, 1) both;
}
.ll-modal-hdr {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid rgba(43, 127, 224, 0.15);
  background: rgba(43, 127, 224, 0.06);
  font-size: .95rem;
  font-weight: 700;
  color: var(--color-gold, #c9a84c);
}
.ll-x {
  background: none;
  border: none;
  color: var(--color-text-muted, #5a6a7f);
  font-size: 1.2rem;
  cursor: pointer;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .15s, color .15s;
  flex-shrink: 0;
  line-height: 1;
}
.ll-x:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #e8edf4;
}

/* one backdrop: brand-navy wash + blur */
.modal-overlay, .gl-modal-overlay, .cs-upload-modal {
  background: rgba(15,23,42,0.55) !important;
  -webkit-backdrop-filter: blur(3px) !important;
  backdrop-filter: blur(3px) !important;
  animation: ll-overlay-in .18s ease-out both;
}
/* one container treatment: hairline border + premium shadow + entrance */
.modal, .gl-modal {
  border: 1px solid #e6e9f0 !important;
  box-shadow: 0 12px 40px rgba(0,29,69,0.18) !important;
  animation: ll-modal-in .24s cubic-bezier(.21,.6,.35,1) both;
}
/* one close button: consistent size/color + circular hover affordance */
.modal-close, .cs-modal-close {
  font-size: 22px !important;
  color: var(--color-text-muted, #5a6a7f) !important;
  width: 32px; height: 32px;
  border-radius: 8px !important;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background-color .15s ease, color .15s ease;
}
.modal-close:hover, .cs-modal-close:hover {
  background: rgba(15,23,42,0.06) !important;
  color: var(--color-text-primary, #1a1a2e) !important;
}

@media (prefers-reduced-motion: reduce) {
  .modal-overlay, .gl-modal-overlay, .cs-upload-modal,
  .modal, .gl-modal { animation: none !important; }
}

/* ============================================================
 * Accessibility — visible keyboard focus (WCAG 2.4.7 / 2.4.11).
 * The app had no consistent focus indicator. :focus-visible only
 * (mouse clicks don't get a ring), so power-user UX is untouched.
 * #8a6520 = 5.3:1 on white and ~3:1 on the navy sidebar (non-text
 * 3:1 floor); the sidebar gets brighter gold for extra headroom.
 * ============================================================ */
a:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible, [tabindex]:not([tabindex="-1"]):focus-visible,
.convo-item:focus-visible, .inv-trigger:focus-visible,
.modal-close:focus-visible, .cs-modal-close:focus-visible {
  outline: 2px solid #8a6520 !important;
  outline-offset: 2px !important;
  border-radius: 4px;
}
/* on the dark navy sidebar, use bright gold for stronger contrast */
.sidebar a:focus-visible, .sidebar button:focus-visible,
.sidebar input:focus-visible, .sidebar .convo-item:focus-visible,
.sidebar .inv-trigger:focus-visible {
  outline-color: #c9a84c !important;
}

/* ============================================================
 * Sub-view buttons (Inventory, F&I Office, etc.) — off-system blue
 * primary actions to one gold. These are inline-styled, so the :root
 * token override didn't reach them (e.g. "Save Bureau Config" #2563eb,
 * "Import" #1d4ed8). Scoped to button/a so data-viz swatches and
 * category-color chips (which are intentionally color-coded) stay blue.
 * #8a6520 + white text = 5.3:1 AA. Stopgap until these get real classes.
 * ============================================================ */
button[style*="background:#2563eb"], a[style*="background:#2563eb"],
button[style*="background: #2563eb"], a[style*="background: #2563eb"],
button[style*="background:#1d4ed8"], a[style*="background:#1d4ed8"],
button[style*="background: #1d4ed8"], a[style*="background: #1d4ed8"],
button[style*="background:#1a56db"], a[style*="background:#1a56db"],
button[style*="background: #1a56db"], a[style*="background: #1a56db"] {
  background: #8a6520 !important;
  color: #f8f6f0 !important;
}

/* ============================================================
 * Dead-link fix — Ad Generator. openAdGenerator() correctly sets
 * #ad-generator-overlay to display:block, but the overlay's inline
 * z-index:90 renders it BEHIND the app chrome (every working overlay
 * uses z-index:200), so it looked like "nothing happened." Lift it to
 * the overlay layer. (Most other "dead" nav items in the audit are
 * false alarms — their handlers live in js/ll-new-modules.js, which is
 * lazy-loaded after auth via loadAppModules().)
 * ============================================================ */
#ad-generator-overlay { z-index: 200 !important; }

/* ============================================================
 * Accent consolidation (round 2) — kill remaining off-system colors
 * the full click-through audit catalogued, and fix gold-button contrast.
 * ============================================================ */
/* Overlay headers: a couple use navy #003478 instead of the brand
 * navy (.nm-head base = var(--sidebar-bg)). Unify them. */
.nm-head[style*="#003478"], .nm-head[style*="background:#003478"] {
  background: #1a2234 !important;
  border-bottom-color: rgba(255,255,255,0.1) !important;
}
/* Contrast: bright-gold buttons with white text fail (#c9a84c + white =
 * 1.9:1). Bright gold is a FILL color — pair it with dark ink (6.3:1),
 * not white. Scoped to button/a so gold text/borders elsewhere are safe. */
button[style*="background:#c9a84c"], a[style*="background:#c9a84c"],
button[style*="background: #c9a84c"], a[style*="background: #c9a84c"] {
  color: #1a1a2e !important;
}
/* Status-color buttons (Doc 1): white text fails on the bright green/amber
 * (#16a34a=3.3:1, #f59e0b/#d97706 amber=2.2:1). Darken the FILL on
 * white-text buttons so it passes AA, per the token spec. Scoped to button. */
button[style*="background:#16a34a"], button[style*="background: #16a34a"] { background: #15803d !important; }
button[style*="background:#f59e0b"], button[style*="background: #f59e0b"],
button[style*="background:#d97706"], button[style*="background: #d97706"] { background: #b45309 !important; }
/* Notification badges/pills/CTA buttons on #ef4444 (3.48:1 with cream/white
 * text, fails AA): the button-scoped fixes above only ever caught <button>
 * fills -- these same-hue instances are mostly <span> badges (unread counts,
 * SLA-breach pills) the earlier sweep's button-only selector couldn't match.
 * Darken to #b91c1c (5.99:1 with cream #f8f6f0 / white), same hue family so
 * the "danger/urgent" meaning is unchanged. Not button-scoped on purpose --
 * a background darken is safe on any element carrying this exact fill. */
[style*="background:#ef4444"], [style*="background: #ef4444"] { background: #b91c1c !important; }
/* Blue action/social buttons (audit prong 3): white text on #3b82f6 (3.68:1)
 * and #1877f2 (3.9:1) misses 4.5:1. Darken the fill to passing blues that keep
 * the hue. #2563eb=5.17:1, #1565c0=5.04:1 under white text. */
[style*="background:#3b82f6"], [style*="background: #3b82f6"] { background: #2563eb !important; }
[style*="background:#1877f2"], [style*="background: #1877f2"] { background: #1565c0 !important; }

/* ============================================================
 * Skeleton loaders (Doc B B-20) — branded shimmer used by the shared
 * _loading helper, so every module shows a skeleton instead of a bare
 * "Loading…". Gated behind prefers-reduced-motion.
 * ============================================================ */
.ll-skeleton {
  background: linear-gradient(90deg, #eceff3 25%, #0a0f1e 50%, #eceff3 75%);
  background-size: 200% 100%;
  animation: ll-shimmer 1.2s ease-in-out infinite;
  border-radius: 6px;
}
@keyframes ll-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .ll-skeleton { animation: none; background: #eceff3; }
}

/* ============================================================
 * Sidebar footer overlap fix. .sidebar scrolls (overflow-y:auto) but the
 * footer ("Alex Carter / Sign out") was a plain flex child with default
 * shrink and no pinning, so a tall nav (expanded dept sections) let it
 * collide with the bottom items. Pin it: sticky to the sidebar's bottom,
 * never shrink, opaque bg so content scrolls cleanly behind it.
 * ============================================================ */
.sidebar-footer {
  position: sticky !important;
  bottom: 0 !important;
  flex-shrink: 0 !important;
  z-index: 5 !important;
  background: #1e2433 !important;
}
.sidebar-header { flex-shrink: 0 !important; }

/* ============================================================
 * Kanban responsiveness (Louie's Desk, P0-2). The board is a horizontally
 * scrollable flex track of fixed 300px columns (set inline) so all 5 stages
 * are reachable with a scroll affordance and no card clipping. Below 640px,
 * stack columns full-width so nothing is unreachable on mobile.
 * ============================================================ */
.desk-kanban-track::-webkit-scrollbar { height: 8px; }
.desk-kanban-track::-webkit-scrollbar-thumb { background: rgba(201,168,76,0.4); border-radius: 4px; }
@media (max-width: 640px) {
  .desk-kanban-track { flex-wrap: wrap !important; overflow-x: visible !important; }
  .desk-kanban-col { flex: 1 1 100% !important; max-height: none !important; }
}

/* ============================================================
 * Chat data-table polish (P1-3). renderMd now suppresses all-empty columns
 * and tags numeric/currency cells with .num; this right-aligns them with
 * tabular figures so dollar columns line up cleanly. Zebra striping + header
 * styling already come from louie-theme.css.
 * ============================================================ */
.msg.assistant table td.num {
  text-align: right !important;
  font-variant-numeric: tabular-nums !important;
  font-feature-settings: "tnum" 1 !important;
  white-space: nowrap;
}

/* ============================================================
 * Wordmark unification (P1-4). The brand marks (login screen, sidebar,
 * empty-state) rendered in bold sans (Plus Jakarta Sans 800) while the
 * concierge wordmark was serif Georgia — inconsistent. Unify all to the
 * serif Georgia mark for one premium, consistent wordmark; UI stays sans.
 * (Backgrounds intentionally left for live eyeballing.)
 * ============================================================ */
.login-logo, .logo, .sidebar-brand {
  font-family: 'Fraunces', Georgia, 'Times New Roman', serif !important;
  font-weight: 600 !important;
  letter-spacing: 0.06em !important;   /* breathing room for the all-caps serif wordmark */
}
/* The large home/empty-state hero wordmark wants more open tracking still */
.empty-state .logo, .es-logo {
  letter-spacing: 0.1em !important;
}

/* ============================================================
 * Skip-to-content link (WCAG 2.4.1). Visually hidden until keyboard-focused.
 * ============================================================ */
.ll-skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100000;
  background: #1a2234; color: #f8f6f0; padding: 10px 18px;
  border-radius: 0 0 8px 0; font-weight: 700; font-size: 14px; text-decoration: none;
}
.ll-skip-link:focus { left: 0; outline: 2px solid #c9a84c; }

/* ============================================================
 * Rate-grid non-color cue (WCAG 1.4.1 — don't signal by hue alone).
 * Each rate tier gets a darkened AA color PLUS a glyph + weight, so the
 * "good / ok / high" meaning survives in grayscale and in print. Mirrors
 * the PVR Tracker's "● Below" text-label pattern. Applied at the render.
 * ============================================================ */
.rate--good { color: var(--green-text, #178841) !important; font-weight: 600; }
.rate--ok   { color: var(--amber-text, #a36907) !important; font-weight: 600; }
.rate--high { color: var(--red-text,   #c81e1e) !important; font-weight: 700; }
.rate--good::before { content: "\25BC "; }  /* ▼ lower = better */
.rate--high::before { content: "\25B2 "; }  /* ▲ higher = worse */

/* REMOVED 2026-07-22 (contrast resweep): this blanket substring override
 * assumed every inline `color:#94a3b8` sat on a light card and needed
 * darkening. A live 27-role Playwright contrast sweep found the opposite —
 * this entire app is dark-themed (body bg #0a0f1e everywhere, no light-card
 * usage of this string found anywhere in the file) and #94a3b8 passes AA
 * comfortably (~5.5:1+) on every dark panel it's actually used on (sidebar
 * "Favorites" header, 5-Minute Delta Feed labels, KPI sub-labels, etc).
 * Forcing it to #5e728d instead dropped those ~40+ confirmed live instances
 * to 3.4-3.9:1 (fails AA) app-wide, every role. If a genuine light-card
 * instance of this exact inline string ever turns up, scope a fix to that
 * container specifically rather than reinstating this blanket rule. */

/* ============================================================
 * Data-cell contrast (audit prong 2 — the Lender Rate Sheet finding).
 * The inline status-green (#16a34a = 3.0:1) and amber (#d97706 = 3.4:1)
 * are the shared data-color vocabulary across ~40 renderers in
 * js/ll-new-modules.js (rate cells, gross/PVR figures, equity, status
 * pills, KPI numbers) — authored as inline `color:`, so the :root token
 * darkening never reached them. This is what kept the Rate Sheet at 68%.
 * Repoint the TEXT color to the AA `-text` variants (validated live:
 * Rate Sheet 68% -> ~95%); scoped to `color:` so the `…22` tint FILLS
 * behind these pills (and solid-fill buttons, handled above) stay vivid.
 * Hue-preserving — green stays green, amber deepens to a readable orange.
 * NOTE: the non-color cue (WCAG 1.4.1 glyph via .rate--good/ok/high) is a
 * separate, smaller item that needs the rate-sheet generator to emit the
 * class; contrast (1.4.3) is the headline and ships here, render-free.
 * ============================================================ */
[style*="color:#16a34a"], [style*="color: #16a34a"] { color: #178841 !important; }
[style*="color:#d97706"], [style*="color: #d97706"] { color: #a36907 !important; }

/* Screen-reader-only utility (used by accessible drop-zone labels). */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ============================================================
 * Easing consistency. Interactive chrome had a grab-bag of transition
 * eases (some elements `transform 0.08s` linear, modals a spring curve).
 * Route the common controls through the design-system --easing-out so the
 * whole UI shares one motion vocabulary. Additive: only sets the timing
 * function where a transition already exists; never adds new transitions.
 * ============================================================ */
button, .inv-trigger, .role-btn, .chip, .qa-chip, .qa-star,
.hkpi, .login-btn, .new-chat-btn, .send-btn, .file-btn {
  transition-timing-function: var(--easing-out, cubic-bezier(0, 0, 0.2, 1));
}

/* ============================================================
 * .overlay-backdrop / .overlay-box / .overlay-header family — Fresh Start
 * Mail, Spiff Board, Predictive Score and others build these via
 * className='overlay-backdrop' with NO structural CSS anywhere that reaches
 * index.html (a rule for .overlay-backdrop exists in site-global.css, but
 * that file is never <link>ed by index.html — only by the ~250 standalone
 * marketing/tool pages). Unstyled, the div is a static block appended at
 * the end of <body>: no backdrop, no centering, no fixed positioning — it
 * renders off-screen at the bottom of the document instead of popping up as
 * a modal. Mirrors the existing .ll-overlay/.ll-modal/.ll-modal-hdr chrome
 * a few lines up so both families look identical.
 * ============================================================ */
.overlay-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9500;
  background: rgba(7, 26, 46, 0.92);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.overlay-box {
  background: #0d1f35;
  border: 1px solid rgba(43, 127, 224, 0.2);
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  margin: 48px auto 48px;
  width: 90%;
  max-width: 480px;
  overflow: hidden;
}
.overlay-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid rgba(43, 127, 224, 0.15);
  background: rgba(43, 127, 224, 0.06);
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--color-gold, #c9a84c);
}
.overlay-header button {
  background: none;
  border: none;
  color: var(--color-text-muted, #5a6a7f);
  font-size: 1.2rem;
  cursor: pointer;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  line-height: 1;
}
.overlay-header button:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #e8edf4;
}

/* ============================================================
 * SYSTEMIC FIX — tool overlay headers clipped behind #ll-role-bar (Jul 4).
 * #ll-role-bar ("PERSISTENT ROLE SWITCHER + LOGOUT", mounted by JS in
 * index.html) is position:fixed; top:0; z-index:99997; height:36px, and is
 * deliberately always-on-top. index.html compensates for it by injecting
 * `#app, #login-screen { padding-top: 36px; }` the moment the bar mounts —
 * but every full-screen tool overlay (BDC Command Center, Equity Mining,
 * Fresh Start Mail, Spiff Board, and 100+ others sharing the "-overlay" id /
 * .overlay-backdrop / .nm-overlay conventions) is appended straight to
 * <body>, OUTSIDE #app, so it never gets that compensation. Each one opens
 * flush at viewport top:0 (or inset:0) and its own title bar renders
 * clipped underneath the role bar. This was previously patched per-overlay
 * (see the #ad-generator-overlay z-index fix above, and the equity/BDC/
 * fresh-start reports) — this rule generalizes it across every overlay
 * sharing the pattern, so no tool needs a one-off patch again. #mob-overlay
 * (mobile sidebar backdrop) also matches "-overlay" and is fine 36px lower.
 *
 * Gated on body:has(#ll-role-bar) (2026-07-04 follow-up): #ll-role-bar is
 * mounted by a script near the very end of index.html's 14MB+ inline script
 * sequence, so on a slow/heavily-loaded parse it can take many seconds
 * longer to mount than the fetch+render of a tool opened right after login.
 * The old unconditional rule pushed every overlay down 36px regardless,
 * which — whenever the role bar hadn't mounted yet (or fails to mount at
 * all) — left a real, unshifted 36px band of whatever sits behind the
 * overlay (the app's own top toolbar) visible above the tool's title,
 * clipped by the overlay's opaque edge. Scoping the rule to only apply
 * once the bar actually exists in the DOM restores flush top:0 in every
 * other case, which is strictly more correct than a fixed 36px guess.
 * ============================================================ */
body:has(#ll-role-bar) [id$="-overlay"],
body:has(#ll-role-bar) .overlay-backdrop,
body:has(#ll-role-bar) .nm-overlay {
  top: 36px !important;
}
