/* ============================================================================
   EBF Onboarder — shared header bridge (the navbar "name"/user dropdown)
   ----------------------------------------------------------------------------
   Page-agnostic redesign of the navbar user menu, applied across all app pages.
   It replicates the delivered .usermenu/.avatar look (ebf-onboarder.css) on the
   Bootstrap navbar toggle WITHOUT touching the delivered files, using the design
   tokens from the delivered colors_and_type.css (loaded alongside this file).

   The user-menu toggle has a different id per page (navbarDropdownMenuLink2 on
   some, Link3 on others), so we target it by content: the .nav-link.dropdown-
   toggle that *contains* a .user-icon span. :has() is well supported in the
   browsers this app targets (Bootstrap 5.3 / current Chromium, Safari, Firefox).

   The initials avatar (.user-avatar) is injected by renderUserAvatar() in
   migrator.js.
   ========================================================================== */

/* Stick the top app bar to the top of the viewport while the page scrolls.
   The navbar already has an opaque white background + bottom border, and none of
   its ancestors clip overflow, so sticky pins cleanly against the body scroll.
   z-index 1030 keeps it above page content and Bootstrap dropdowns (1000) but
   below modals/backdrops (1040+). Loaded after dashboard.css, so this wins. */
.navbar {
    position: sticky;
    top: 0;
    z-index: 1030;
    /* Fixed header bar on every page. box-sizing:border-box means min-height includes the
       1px bottom border, so 64px = a 63px bar + the border on top. Pins the total height
       regardless of whether the row is driven by the action pills (app pages) or just the
       logo (login/forgot), so all headers are identical. 8px top/bottom centres the logo. */
    padding-top: 8px;
    padding-bottom: 8px;
    min-height: 64px;
}

/* The legacy second-navigation bar (#navBar, present only on non-redesigned pages
   like instances.html) is NOT the sticky app bar — keep it in normal flow so it
   doesn't stack on top of the real navbar, and so it can be parallaxed. The ID
   selector outranks both .navbar (above) and the legacy .sticky class. */
#navBar {
    position: static;
}

/* The toggle becomes a rounded pill */
/* Navbar action links (Settings / Help). Pin the design font + size so the
   labels are identical on every page: project-details inherits Inter (it links
   ebf-onboarder.css which sets html,body{font-family:var(--font-body)}), while
   the dashboard/list pages would otherwise fall back to the default face and
   render the same px in a visibly smaller-looking typeface. */
.navbar .navbar-nav .nav-link {
  font-family: var(--font-body);
  font-size: 14px;
}

/* Settings / Help top-nav buttons — the design's .iconbtn: a 32px-tall labelled
   control (16px icon + 8px gap + label + chevron), 12px side inset, 8px radius and
   a subtle rounded hover fill. The height is fixed to 32px so the pill matches the
   mock exactly instead of drifting with the inherited line-height. Page-agnostic. */
.navbar .nav-link.dropdown-toggle:has(.settings-icon),
.navbar .nav-link.dropdown-toggle:has(.help-icon) {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  box-sizing: border-box;
  padding: 0 12px;
  border-radius: 8px;
  color: var(--fg-2);
  font-weight: 500;
  line-height: 1;
  transition: background 120ms ease-out, color 120ms ease-out;
}
.navbar .nav-link.dropdown-toggle:has(.settings-icon):hover,
.navbar .nav-link.dropdown-toggle:has(.help-icon):hover {
  background: var(--bg-subtle);
  color: var(--fg-1);
}
/* 16px icon glyph at the left, label 8px after it (legacy rule used a 20px offset
   → only ~4px gap). Overrides dashboard.css .settings-icon/.help-icon. */
.navbar .dropdown-toggle .settings-icon,
.navbar .dropdown-toggle .help-icon {
  display: inline-block;
  background-size: 16px 16px;
  line-height: 16px;
}
.navbar .dropdown-toggle .settings-icon::after,
.navbar .dropdown-toggle .help-icon::after {
  margin-left: 24px;
}
/* Action buttons 4px apart (design .nav-right gap) so hover fills never collide. */
.navbar .navbar-nav:has(.settings-icon) { gap: 4px; }
/* dashboard.css puts a 30px margin between nav items — kill it for the header
   action list so only the 4px flex gap remains (design .nav-right). */
.navbar .navbar-nav:has(.settings-icon) .nav-item + .nav-item { margin-left: 0; }

.navbar .nav-link.dropdown-toggle:has(.user-icon) {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px 6px 6px;
  /* Reserve the final pill height up front (avatar 28px + 6+6 padding = 40px).
     The .user-avatar and email label are injected by renderUserAvatar() AFTER
     load; without a fixed min-height the pill — and the whole navbar row — would
     grow once they appear, causing the navbar to jump. */
  min-height: 40px;
  box-sizing: border-box;
  border-radius: 9999px;
  border: 1px solid var(--border-subtle);
  background: transparent;
  transition: background 120ms ease-out, border-color 120ms ease-out;
}
.navbar .nav-link.dropdown-toggle:has(.user-icon):hover {
  background: var(--bg-subtle);
  border-color: var(--border-default);
}
/* Top-menu twisties. Bootstrap's default caret is a filled CSS triangle; the
   design uses an open chevron-down (feather "chevron-down", stroked + rounded).
   Replace the triangle with a masked SVG chevron tinted via --fg-3 so it matches
   the design and follows light/dark mode. Applies to all navbar dropdown toggles
   (Settings / Help / user pill). */
.navbar .nav-link.dropdown-toggle::after {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 0;                 /* drop Bootstrap's solid-triangle borders */
  vertical-align: middle;
  background-color: var(--fg-3);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat center / contain;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat center / contain;
}
.navbar .nav-link.dropdown-toggle:has(.user-icon)::after {
  /* Sit the chevron inside the pill after the label */
  margin-left: 2px;
}

/* Avatar width placeholder. renderUserAvatar() injects .user-avatar AFTER load;
   until then the pill is missing the 28px circle (and its 10px gap), so the pill
   — and the navbar — would widen once the avatar appears. This ::before reserves
   exactly that space as a neutral circle, and is dropped the moment the real
   .user-avatar exists (:not(:has(.user-avatar))), so there is never a double
   circle and the width is correct from first paint. */
.navbar .nav-link.dropdown-toggle:has(.user-icon):not(:has(.user-avatar))::before {
  content: "";
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 9999px;
  background: var(--bg-subtle);
}

/* Initials avatar (JS-injected). Solid EBF blue for normal users, EBF gradient
   for EBF/internal users (.ebf modifier set by renderUserAvatar). */
.navbar .user-avatar {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 9999px;
  background: var(--ebf-blue-500);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-title);
  font-weight: 600;
  font-size: 12px;
  line-height: 1;
  text-transform: uppercase;
}
.navbar .user-avatar.ebf {
  background: linear-gradient(135deg, var(--ebf-blue-500) 0%, var(--ebf-green-500) 100%);
}
/* Role-coloured avatar — overrides the default blue→green gradient above. The body
   role classes are set server-side (HandleHtmlRequest): admin-ebf / sales-ebf.
   The extra `body` element raises specificity above `.user-avatar.ebf`. */
body.admin-ebf .navbar .user-avatar {
  background: linear-gradient(135deg, var(--ebf-red-500) 0%, var(--ebf-red-700) 100%);
}
body.sales-ebf .navbar .user-avatar {
  background: linear-gradient(135deg, var(--ebf-yellow-600) 0%, var(--ebf-yellow-800) 100%);
}

/* Role banner at the top of the user dropdown — same colour as the avatar, white text.
   Targets only the user dropdown (its toggle is the one with .user-icon). Source order
   (support, admin, sales) mirrors the avatar so multi-role users stay consistent. */
body.support-ebf .navbar .nav-link.dropdown-toggle:has(.user-icon) + .dropdown-menu::before,
body.admin-ebf .navbar .nav-link.dropdown-toggle:has(.user-icon) + .dropdown-menu::before,
body.sales-ebf .navbar .nav-link.dropdown-toggle:has(.user-icon) + .dropdown-menu::before {
  display: block;
  margin: -6px -6px 6px;          /* offset the menu's 6px padding → flush top + full width */
  padding: 9px 12px 9px 36px;     /* EBF mark at 11px (under the avatar); text aligns with the items' label column */
  border-radius: 7px 7px 0 0;
  color: #fff;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
body.support-ebf .navbar .nav-link.dropdown-toggle:has(.user-icon) + .dropdown-menu::before {
  content: 'Support Administrator';
  background: url("../img/ebf-heart-white.svg") no-repeat 11px center / auto 14px,
              linear-gradient(135deg, var(--ebf-blue-500) 0%, var(--ebf-green-500) 100%);
}
body.admin-ebf .navbar .nav-link.dropdown-toggle:has(.user-icon) + .dropdown-menu::before {
  content: 'Administrator';
  background: url("../img/ebf-heart-white.svg") no-repeat 11px center / auto 14px,
              linear-gradient(135deg, var(--ebf-red-500) 0%, var(--ebf-red-700) 100%);
}
body.sales-ebf .navbar .nav-link.dropdown-toggle:has(.user-icon) + .dropdown-menu::before {
  content: 'Sales-Administrator';
  background: url("../img/ebf-heart-white.svg") no-repeat 11px center / auto 14px,
              linear-gradient(135deg, var(--ebf-yellow-600) 0%, var(--ebf-yellow-800) 100%);
}

/* Reset the delivered circle-user icon: drop the SVG background, render the
   ::after label as a plain text label sitting next to the avatar. */
.navbar .nav-link.dropdown-toggle:has(.user-icon) .user-icon,
.navbar .nav-link.dropdown-toggle:has(.user-icon) .user-icon:hover {
  background: none;
  height: auto;
  max-width: 220px;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-1);
  vertical-align: middle;
}
.navbar .nav-link.dropdown-toggle:has(.user-icon) .user-icon::after {
  margin-left: 0;
}

/* ---- Dropdown / popup menus ----------------------------------------------
   Make every Bootstrap dropdown/popup menu (navbar Settings/Help/user menu AND
   the in-page action / context menus) look the same on every page. On
   project-details the delivered ebf-onboarder.css already rounds ALL
   .dropdown-menu to 10px; everywhere else dashboard.css renders them at 2px
   (near-square), which is why popups looked different off project-details.
   These values mirror the delivered design system, so the menus are identical
   across pages. Intentionally NOT scoped to .navbar — the previous navbar-only
   scope left context/action popups square. We deliberately do NOT set
   position/top/left — dashboard.css (navbar) and per-page CSS own dropdown
   positioning; we only restyle the box (corners, border, shadow, padding). */
.dropdown-menu {
  border-radius: var(--radius-tile, 10px);
  border: 1px solid var(--border-default);
  background: var(--bg-page);
  box-shadow: var(--shadow-md);
  padding: 6px;
  /* Pin the design font + size so menu text is identical on every page. Without
     this, project-details inherits Inter (it links ebf-onboarder.css which sets
     html,body{font-family:var(--font-body)}) while the dashboard/list pages
     inherit the old default face — same px, but a different typeface reads as a
     different text size. --font-body comes from the shared colors_and_type.css. */
  font-family: var(--font-body);
  font-size: 14px;
}
.dropdown-menu .dropdown-item {
  border-radius: 6px;
  padding: 8px 12px;
}
/* User + help dropdowns: pull the items' icon column left so it sits under the toggle
   icon / the role-banner EBF mark (6px menu padding + 5px → 11px), instead of the
   default inset. */

/* Leading icons on the header menu items. Rendered via mask + currentColor so the
   icon takes the menu-text colour automatically (dark in light mode, light in dark).
   Scoped to the specific items so generic .dropdown-item menus (sort/category/…)
   stay icon-free. Each item supplies its glyph via the --di-icon custom property. */
#manageSettings::before,
#manageAdmins::before,
#editProfileLink::before,
#changePassLink::before,
#changePassLinkMobile::before,
#registerPasskeyLink::before,
.dropdown-menu a.dropdown-item[href="logout.html"]::before,
.dropdown-menu a.dropdown-item[href*="youtube.com"]::before,
.dropdown-menu a.dropdown-item[href*="ebf-onboarder"]::before,
.dropdown-menu a.dropdown-item[href*="docs.ebf.com"]::before {
  content: "";
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-right: 0;
  flex: 0 0 auto;
  background-color: currentColor;
  opacity: 0.7;
  -webkit-mask: var(--di-icon) center / contain no-repeat;
          mask: var(--di-icon) center / contain no-repeat;
}
/* One consistent Lucide stroke family (stroke-width 2). ux-settings/ux-user are
   already Lucide files; the rest are inline Lucide paths in the same style. As
   masks they all render as currentColor outlines → uniform look. */
#manageSettings { --di-icon: url(../img/props-black.svg); }   /* customers 'Properties' sliders icon */
#manageAdmins { --di-icon: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232D353E'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M12%2022s8-4%208-10V5l-8-3-8%203v7c0%206%208%2010%208%2010z'/%3E%3C/svg%3E"); }
#editProfileLink { --di-icon: url(../img/ux-user.svg); }
#changePassLink,
#changePassLinkMobile { --di-icon: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232D353E'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Crect%20x='3'%20y='11'%20width='18'%20height='11'%20rx='2'/%3E%3Cpath%20d='M7%2011V7a5%205%200%200%201%2010%200v4'/%3E%3C/svg%3E"); }
#registerPasskeyLink { --di-icon: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232D353E'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='7.5'%20cy='15.5'%20r='5.5'/%3E%3Cpath%20d='m21%202-9.6%209.6'/%3E%3Cpath%20d='m15.5%207.5%203%203L22%207l-3-3'/%3E%3C/svg%3E"); }
.dropdown-menu a.dropdown-item[href="logout.html"] { --di-icon: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232D353E'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M9%2021H5a2%202%200%200%201-2-2V5a2%202%200%200%201%202-2h4'/%3E%3Cpath%20d='m16%2017%205-5-5-5'/%3E%3Cpath%20d='M21%2012H9'/%3E%3C/svg%3E"); }

/* Sign-out is the danger action: red text + icon (currentColor mask turns it red),
   red-tinted hover. Mirrors the design system's .dropdown-menu .item.danger. */
.dropdown-menu a.dropdown-item[href="logout.html"] { color: var(--ebf-red-600); }
.dropdown-menu a.dropdown-item[href="logout.html"]::before { opacity: 1; }
.dropdown-menu a.dropdown-item[href="logout.html"]:hover,
.dropdown-menu a.dropdown-item[href="logout.html"]:focus {
  background: var(--ebf-red-100);
  color: var(--ebf-red-700);
}
.dark .dropdown-menu a.dropdown-item[href="logout.html"] { color: var(--ebf-red-400); }
.dark .dropdown-menu a.dropdown-item[href="logout.html"]:hover,
.dark .dropdown-menu a.dropdown-item[href="logout.html"]:focus {
  background: rgba(250,126,117,0.14);
  color: var(--ebf-red-400);
}

/* ---- Navbar menus (Settings / Help / user) — the design's .dropdown-menu:
   flex rows with a 16px icon, 10px gap, 8px/10px inset and clean vertical
   centring; 220px min width (Help 280px); brand-tint hover. Scoped to .navbar so
   in-page context/action menus keep their own compact styling. */
/* Navbar menus: 220px min width, open 6px below the button and right-aligned to its
   edge (design .dropdown-menu: top calc(100%+6px), right:0). The child combinator gives
   0,3,0 so it beats dashboard.css (.navbar .dropdown-menu top:100%/left:0) AND
   ebf-onboarder.css (.dropdown-menu) on every page regardless of load order. */
.navbar .nav-item.dropdown > .dropdown-menu {
  min-width: 220px;
  position: absolute;
  top: 100%;
  left: auto;
  right: 0;
  margin-top: 6px;
}
.navbar .nav-link.dropdown-toggle:has(.help-icon) + .dropdown-menu { min-width: 280px; }
.navbar .dropdown-menu .dropdown-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 6px;
  color: var(--fg-1);
}
.navbar .dropdown-menu .dropdown-item:hover,
.navbar .dropdown-menu .dropdown-item:focus {
  background: var(--ebf-blue-100);
  color: var(--ebf-blue-600);
}
/* The Help menu's YouTube row carries a multi-line note — keep it a block so the
   note stacks below, and restore its inline icon gap (flex/gap don't apply here). */
.navbar .dropdown-menu .dropdown-item:has(.menuitem-note) { display: block; }
.navbar .dropdown-menu .dropdown-item:has(.menuitem-note)::before { margin-right: 10px; vertical-align: -3px; }
/* Dividers in the Help menu → the design's hairline .sep. */
.navbar .dropdown-menu hr {
  height: 1px;
  margin: 4px 4px;
  border: 0;
  background: var(--border-subtle);
  opacity: 1;
}
/* Version line → non-interactive muted static row (design .item.static). */
.navbar .dropdown-menu .dropdown-item-version {
  display: block;
  padding: 8px 10px;
  font-size: 12px;
  color: var(--fg-3);
}
/* Open state (menu expanded) keeps the button filled, like the design's .is-open. */
.navbar .nav-link.dropdown-toggle:has(.settings-icon).show,
.navbar .nav-link.dropdown-toggle:has(.help-icon).show {
  background: var(--bg-subtle);
  color: var(--fg-1);
}
/* Keep the toggle icon neutral on hover/open — the design's button icon follows the
   label (dark), never a blue accent. Overrides dashboard.css .settings-icon:hover /
   .help-icon:hover, which swap to blue/filled SVGs. */
.navbar .dropdown-toggle:hover .settings-icon,
.navbar .dropdown-toggle.show .settings-icon { background-image: url(../img/general-settings.svg); }
.navbar .dropdown-toggle:hover .help-icon,
.navbar .dropdown-toggle.show .help-icon { background-image: url(../img/help.svg); }
.dropdown-menu a.dropdown-item[href*="youtube.com"] { --di-icon: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232D353E'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='12'%20r='10'/%3E%3Cpath%20d='m10%208%206%204-6%204z'/%3E%3C/svg%3E"); }
.dropdown-menu a.dropdown-item[href*="ebf-onboarder"] { --di-icon: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232D353E'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='12'%20r='10'/%3E%3Cpath%20d='M12%2016v-4'/%3E%3Cpath%20d='M12%208h.01'/%3E%3C/svg%3E"); }
.dropdown-menu a.dropdown-item[href*="docs.ebf.com"] { --di-icon: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%232D353E'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M14%202H6a2%202%200%200%200-2%202v16a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2V8z'/%3E%3Cpath%20d='M14%202v6h6'/%3E%3Cpath%20d='M16%2013H8'/%3E%3Cpath%20d='M16%2017H8'/%3E%3Cpath%20d='M10%209H8'/%3E%3C/svg%3E"); }
.dropdown-menu hr {
  margin: 4px 4px;
  border-top: 1px solid var(--border-subtle);
  opacity: 1;
}

/* ---- Dialog (modal) corners ----------------------------------------------
   Round modal surfaces to match the card system (12px) so dialogs feel part of
   the same design language on every page. Our own dashboard.css sets
   .modal-content { border-radius: 2px } (near-square); we raise it here without
   touching the delivered files. This used to be scoped to #projectDetails (it
   loads the delivered ebf-onboarder.css which already rounds its surfaces); it
   now lives in this shared bridge so dashboard and the other pages that link
   ebf-header.css get the same rounded popups instead of square 2px ones.
   Fullscreen modals are excluded — they fill the viewport, so rounding would
   leave gaps at the screen edges. The header/footer corners are rounded too for
   modals whose .modal-content uses overflow:visible (dashboard.css) and would
   otherwise expose square corners under the rounded content box. */
.modal:not(.modal-fullscreen) .modal-content {
  border-radius: var(--radius-card, 12px);
}
.modal:not(.modal-fullscreen) .modal-header {
  border-top-left-radius: 12px;
  border-top-right-radius: 12px;
}
.modal:not(.modal-fullscreen) .modal-footer {
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
}

/* ============================================================================
   Dark mode — toggle button + page-shell application
   ----------------------------------------------------------------------------
   The token overrides live in colors_and_type.css (`.dark, [data-theme="dark"]`);
   js/theme.js writes data-theme onto <html> and injects the `.theme-toggle`
   button (below) into the navbar. This file loads AFTER dashboard.css, so the
   shell overrides here win over the light canvas defined there.
   ========================================================================== */

/* ---- Toggle button -------------------------------------------------------
   A round icon button matching the navbar action pills. It shows the moon in
   light mode (click → dark) and the sun in dark mode (click → light). */
.theme-toggle-item {
  display: flex;
  align-items: center;
}
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--icon-default);
  cursor: pointer;
  transition: opacity 120ms ease-out, color 120ms ease-out;
}
.theme-toggle:hover {
  opacity: 0.7;
}
.theme-toggle:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}
/* Fixed variant: pinned to the top-right of the viewport, outside the page's
   grid/navbar columns, so the toggle sits in the same spot on every page.
   Transparent (no surface/shadow) — just the icon. z-index sits above the
   (sticky) navbar but below the off-canvas menu / modals (Bootstrap:
   offcanvas-backdrop 1040, modal-backdrop 1050) so it never floats over a dialog. */
.theme-toggle--fixed {
  position: fixed;
  bottom: 10px;
  right: 10px;
  top: auto;
  margin: 0;
  z-index: 1035;
  /* Floating circular button (Google-style), pinned bottom-right. */
  width: 40px;
  height: 40px;
  border-radius: 999px;
  background: var(--bg-page);
  border: 1px solid var(--border-default);
  box-shadow: var(--shadow-md, 0 4px 16px rgba(0, 0, 0, 0.18));
}
.theme-toggle--fixed:hover {
  opacity: 1;
  background: var(--bg-subtle);
  border-color: var(--fg-3);
}

/* Festive-theme off-switch: small round button left of the dark/light toggle,
   only present (injected by theme.js) while a festive skin is active. Its centre
   lines up vertically with the 40px toggle (toggle: bottom:10 -> centre 30px;
   this 30px button at bottom:15 -> centre 30px). */
.festive-off {
  position: fixed;
  bottom: 15px;
  right: 58px;            /* toggle is right:10 + 40px wide -> left edge at 50; +8 gap */
  width: 30px;
  height: 30px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: var(--bg-page);
  border: 1px solid var(--border-default);
  box-shadow: var(--shadow-md, 0 4px 16px rgba(0, 0, 0, 0.18));
  color: var(--fg-2);
  cursor: pointer;
  z-index: 1035;
  transition: background 120ms ease-out, color 120ms ease-out, border-color 120ms ease-out;
}
.festive-off:hover {
  background: var(--bg-subtle);
  border-color: var(--fg-3);
  color: var(--fg-1);
}
.festive-off:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}
.theme-toggle .ti {
  display: block;
  pointer-events: none;
}
/* Light mode: offer the moon. Dark mode: offer the sun. */
.theme-toggle .ti-sun  { display: none; }
.theme-toggle .ti-moon { display: block; }
[data-theme="dark"] .theme-toggle .ti-sun  { display: block; }
[data-theme="dark"] .theme-toggle .ti-moon { display: none; }

/* ---- Page-shell application ----------------------------------------------
   Flip the base canvas to the dark tokens. Component-level surfaces that still
   carry hardcoded light colours (legacy dashboard.css) are intentionally not
   re-themed here — that is a separate, full component pass. */
[data-theme="dark"] body {
  background: var(--bg-page);
  color: var(--fg-1);
}
/* ---- Grey page shell (dashboard + customers) -----------------------------
   Mirror project-details, where ebf-onboarder.css paints .app-shell with
   var(--bg-subtle) (grey) while the navbar, footer and cards stay var(--bg-page)
   (black) — that contrast is what lifts the chrome off the canvas. Dashboard &
   customers had it inverted (black canvas, grey cards), so the navbar/footer
   blended in. Flip the canvas to grey and the .project-container tiles to the
   page surface so they read as cards on it, matching project-details. */
[data-theme="dark"] body.grey-shell {
  background: var(--bg-subtle);
}
[data-theme="dark"] body.grey-shell .project-container {
  background: var(--bg-page);
}
/* The decorative corner artwork is baked for the light canvas; drop it in dark
   so it does not sit as a light block on the dark background. */
[data-theme="dark"] body:not(.white):not(.settingsPage),
[data-theme="dark"] body:not(.white):not(.settingsPage) .content-wrap {
  background-image: none;
}

/* ---- Navbar --------------------------------------------------------------
   dashboard.css paints the navbar white (#fff) with dark ink text; remap the
   surfaces and text to the dark tokens. The prefix raises specificity above the
   originals so these win without !important. */
[data-theme="dark"] .navbar-light {
  background: var(--bg-page);
  color: var(--fg-2);
}
[data-theme="dark"] .navbar-lightgray {
  background: var(--bg-subtle);
}
[data-theme="dark"] .navbar-light .navbar-nav .nav-link {
  color: var(--fg-1);
}
[data-theme="dark"] .navbar-light .navbar-nav .nav-link:hover {
  color: var(--fg-link);
}
[data-theme="dark"] .navbar-settings {
  background: var(--bg-page);
  color: var(--fg-1);
}
/* The Settings / Help glyphs are background-image SVGs stroked in dark ink
   (#2b3e51), so they vanish on a dark navbar. Filter them to a light tone.
   The user pill (.user-icon) is already re-themed via tokens in this file. */
[data-theme="dark"] .settings-icon,
[data-theme="dark"] .help-icon {
  filter: brightness(0) invert(0.85);
}
/* Megaphone (notifications) + bell (errors) are dark background-image SVGs that
   vanish on the dark navbar. We can't `filter` the element itself — it also
   carries the red notification/error dot child, which would be greyed too. So
   render the icon via a filtered ::before overlay and leave the dot untouched. */
[data-theme="dark"] .notifications-spark,
[data-theme="dark"] .errors-spark {
  background-image: none;
}
[data-theme="dark"] .notifications-spark::before,
[data-theme="dark"] .errors-spark::before {
  content: "";
  position: absolute;
  inset: 0;
  background-position: 50%;
  background-size: contain;
  background-repeat: no-repeat;
  /* Match the softer gear/help glyphs' tone (they use invert(0.85)). */
  filter: brightness(0) invert(0.85);
}
[data-theme="dark"] .notifications-spark::before { background-image: url("../img/megaphone.svg"); }
[data-theme="dark"] .errors-spark::before        { background-image: url("../img/bell.svg"); }
[data-theme="dark"] .notifications-spark:hover::before { background-image: url("../img/megaphone-filled.svg"); }
[data-theme="dark"] .errors-spark:hover::before        { background-image: url("../img/bell-filled.svg"); }

/* Page loading overlay (db-loader / fake-loader): the default white scrim flashes
   bright on the dark theme — use a dark scrim instead (the spinner stays blue). */
[data-theme="dark"] .db-loader-wrap,
[data-theme="dark"] .fake-loader-wrap,
.dark .db-loader-wrap,
.dark .fake-loader-wrap {
  background-color: rgba(10, 14, 20, 0.78);
}
/* The logo SVG carries a near-black wordmark; render it as a clean white mark. */
[data-theme="dark"] .migrator-logo img {
  filter: brightness(0) invert(1);
}
/* xxebf: the mark is swapped to a gradient-heart SVG whose letter colour is already baked
   per mode (theme.js swapEbfLogo). The dark-mode white-out filter above must NOT touch it,
   or the blue->teal heart would be flattened to white. */
:root.theme-ebf .migrator-logo img {
  filter: none;
}

/* ---- Footer (footer.html: <footer class="footer">) ----------------------- */
[data-theme="dark"] .footer {
  background: var(--bg-page);
}
[data-theme="dark"] .footer ul li a {
  color: var(--fg-2);
}
[data-theme="dark"] .footer ul li a:hover {
  color: var(--fg-link);
}

/* ---- Tiles (.project-container — used by both migration & customer items) -
   The card box, its header gradient, the field text, links and progress bar
   are all hardcoded light in dashboard.css; remap to the dark tokens. */
[data-theme="dark"] .project-container {
  background: var(--bg-subtle);
  border-color: var(--border-default);
}
[data-theme="dark"] .project-container:hover {
  box-shadow: 0 6px 10px rgba(0, 0, 0, 0.5);
}
[data-theme="dark"] .project-container-header {
  background: linear-gradient(to bottom, var(--bg-muted) 0%, var(--bg-subtle) 100%);
  filter: none;   /* drop the legacy IE gradient filter (white→#f1f3f7) */
}
[data-theme="dark"] .project-cell-input p {
  color: var(--fg-3);
}
[data-theme="dark"] .project-cell-input p span {
  color: var(--fg-1);
}
[data-theme="dark"] .project-links a {
  color: var(--fg-1);
  text-shadow: none;
}
[data-theme="dark"] .progress {
  background-color: var(--bg-muted);
}

/* Customer-tile internals: the tab strip and the inline-editable fields. The
   originals use !important, so these must too (and the prefix out-specifies). */
[data-theme="dark"] .project-container ul {
  border-bottom-color: var(--border-subtle);
}
[data-theme="dark"] .project-container ul li a {
  color: var(--fg-2) !important;
}
[data-theme="dark"] .project-container ul li a.active {
  color: var(--fg-link) !important;
}
[data-theme="dark"] .customer-item select.editCustomer,
[data-theme="dark"] .customer-item input.editCustomer,
[data-theme="dark"] .customer-item .licCount,
[data-theme="dark"] .customer-item-flat input.editCustomer,
[data-theme="dark"] .customer-item .form-control {
  background: transparent;
  color: var(--fg-1);
}
[data-theme="dark"] .project-container-header input.editCustomer,
[data-theme="dark"] .project-container-header input.editInstance {
  color: var(--fg-link) !important;
}
[data-theme="dark"] .customer-item-flat .flat-field {
  color: var(--fg-3);
  border-left-color: var(--border-subtle);
}
[data-theme="dark"] .customer-item-flat .flat-actions {
  border-left-color: var(--border-subtle);
}

/* ---- Tables (.details-table card + device/list tables, incl. userRow) -----
   The table card is painted white (#fff) by dashboard.css, and rows are either
   transparent (showing that white card) or zebra-striped #f8f9fb; the header
   row (.thead-inverse) is white too. Remap them to the dark tokens. The
   redesigned project-details device rows are already token-based and disable
   zebra, so they simply ride on the dark card below. */
[data-theme="dark"] .details-table {
  background: var(--bg-subtle);
  border-color: var(--border-default);
  color: var(--fg-1);
}
[data-theme="dark"] .details-table .caption {
  background: var(--bg-muted);
  filter: none;   /* drop the legacy IE white→grey gradient filter */
}
[data-theme="dark"] .details-table .caption h3 {
  color: var(--fg-1);
}
[data-theme="dark"] .thead-inverse th {
  background: var(--bg-muted);
  color: var(--fg-3);
}
[data-theme="dark"] table tr:nth-child(even) {
  background: var(--bg-muted);
}
/* Bootstrap 5 paints every cell via --bs-table-bg (= white --bs-body-bg) and
   --bs-table-color (dark) — that's the white body on tablesorter tables like
   the licenses Order History. Remap Bootstrap's own table variables so cells
   are transparent (the dark card/zebra shows through) with light text. */
[data-theme="dark"] .table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--fg-1);
  --bs-table-striped-color: var(--fg-1);
  --bs-table-hover-color: var(--fg-1);
  --bs-table-border-color: var(--border-subtle);
  color: var(--fg-1);
}

/* ---- Search bars ---------------------------------------------------------
   input.search-bar (customer search) is hardcoded white with a black magnifier
   SVG that would vanish on dark. Remap the surface and swap in a light inline
   magnifier. (#projectDetails .search-bar-user is already token-based, but its
   black icon needs the same swap.) */
[data-theme="dark"] input.search-bar {
  background-color: var(--bg-subtle);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23C7C9CC' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
  color: var(--fg-1);
  border-color: var(--border-default);
}
[data-theme="dark"] input.search-bar::placeholder,
[data-theme="dark"] #projectDetails input.search-bar-user::placeholder {
  color: var(--fg-3);
}
[data-theme="dark"] #projectDetails input.search-bar-user {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23C7C9CC' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
}

/* ---- Dropdowns -----------------------------------------------------------
   Bootstrap dropdown menus already get a dark surface from the .dropdown-menu
   rule above, but the items keep Bootstrap's dark default text. */
[data-theme="dark"] .dropdown-menu .dropdown-item {
  color: var(--fg-1);
}
[data-theme="dark"] .dropdown-menu .dropdown-item:hover,
[data-theme="dark"] .dropdown-menu .dropdown-item:focus {
  background: var(--bg-subtle);
  color: var(--fg-1);
}

/* select2 widgets (used for filters/pickers across the app). Remap the closed
   control, the open dropdown, options and the in-dropdown search field. */
[data-theme="dark"] .select2-dropdown {
  background: var(--bg-page);
  border-color: var(--border-default);
}
[data-theme="dark"] .select2-container--default .select2-selection--single,
[data-theme="dark"] .select2-container--default .select2-selection--multiple {
  background: var(--bg-subtle);
  border-color: var(--border-default);
}
[data-theme="dark"] .select2-container--default .select2-selection--single .select2-selection__rendered {
  color: var(--fg-1);
}
[data-theme="dark"] .select2-results__option {
  color: var(--fg-1);
}
[data-theme="dark"] .select2-container--default .select2-results__option--highlighted[aria-selected] {
  background: var(--ebf-blue-600);
  color: var(--ebf-white);
}
[data-theme="dark"] .select2-container--default .select2-results__option[aria-selected="true"] {
  background: var(--bg-muted);
}
[data-theme="dark"] .select2-search--dropdown .select2-search__field {
  background: var(--bg-subtle);
  border-color: var(--border-default);
  color: var(--fg-1);
}

/* ---- Category / OS chips (catBox, osBox, source-selection pills) ----------
   Generic chips are hardcoded translucent-black; the #projectDetails ONE-DESIGN
   chips fill with var(--ebf-white) (a primitive that does not flip). */
[data-theme="dark"] span.catBox,
[data-theme="dark"] span.osBox {
  background-color: var(--bg-muted);
  border-color: var(--border-subtle);
  color: var(--fg-2);
  box-shadow: none;
  text-shadow: none;
}
[data-theme="dark"] #projectDetails span.catBox,
[data-theme="dark"] #projectDetails #sourceSelection .sel-group,
[data-theme="dark"] #projectDetails #sourceSelection .osBox {
  background: var(--bg-muted);
  color: var(--fg-2);
}

/* ============================================================================
   Dark mode — round 2: remaining cases
   (native <select> / .migrator-select, select2 edge cases, modals + editor)
   ========================================================================== */

/* Declare that this page handles BOTH schemes itself. This is the signal that
   makes Chrome's "Auto Dark Mode for Web Contents"
   (chrome://flags/#enable-force-dark) defer to our own theme instead of
   algorithmically inverting the page — so the look is always our designed
   light/dark, never the browser's heuristic version. (Trade-off: on a dark OS,
   a user who explicitly forces LIGHT may see native form controls in dark; rare
   and mostly cosmetic since the app's pickers are select2, not native.) */
:root {
  color-scheme: light dark;
}

/* Let the UA paint native form controls (incl. <select> option popups),
   scrollbars and spin buttons in their dark variant. */
[data-theme="dark"] {
  color-scheme: dark;
}


/* ---- Native selects (.migrator-select / .select-style wrap a real <select>;
   the "Responsible"/"Currency" customer-tile fields are these). ------------- */
[data-theme="dark"] .migrator-select select,
[data-theme="dark"] .select-style select,
[data-theme="dark"] select.customer-responsible-field,
[data-theme="dark"] select.customer-currency-field {
  background: var(--bg-subtle);
  color: var(--fg-1);
}

/* A bare .migrator-select is a borderless, transparent control in light mode
   (just the <select> text + the ::after arrow). The dark fill above alone is
   invisible against the grey page shell, so promote the wrapper to the same
   bordered dark-grey field box as the search bar / .select-style pickers and
   let the native <select> sit transparent inside it. Excludes:
   - .select-style (its wrapper already carries the border), and
   - select2-upgraded wrappers (:has(.select2) — the .select2-selection box gets
     its own border from the select2 rules), to avoid a double border. */
[data-theme="dark"] .migrator-select:not(.select-style):not(:has(.select2)) {
  background: var(--bg-subtle);
  border: 1px solid var(--border-default);
  border-radius: 8px;
}
[data-theme="dark"] .migrator-select:not(.select-style):not(:has(.select2)) > select {
  background: transparent;
}

/* ---- select2 edge cases not covered by round 1 --------------------------
   .select-style forces the closed control to #fff !important (Responsible /
   Currency pickers in customer tiles), and the in-dropdown search field has no
   explicit background so it falls back to white — both need !important here. */
[data-theme="dark"] .select-style .select2-selection {
  background-color: var(--bg-subtle) !important;
}
[data-theme="dark"] .select2-search__field {
  background: var(--bg-subtle) !important;
  border-color: var(--border-default) !important;
  color: var(--fg-1);
}
[data-theme="dark"] .select2-selection__placeholder {
  color: var(--fg-3);
}
[data-theme="dark"] .select2-container--default .select2-selection--single .select2-selection__rendered,
[data-theme="dark"] .select2-container--default .select2-selection--multiple .select2-selection__rendered {
  color: var(--fg-1);
}
/* The caret (drawn as a CSS triangle via border colors). */
[data-theme="dark"] .select2-container--default .select2-selection--single .select2-selection__arrow b {
  border-top-color: var(--fg-3);
}

/* ---- Modals / dialogs ----------------------------------------------------
   .modal-content has no explicit background, so Bootstrap paints it white;
   .modal-header carries a white→grey gradient. Remap the surfaces, the inner
   form controls and the (dark-glyph) close button. */
[data-theme="dark"] .modal-content {
  background: var(--bg-subtle);
  color: var(--fg-1);
}
[data-theme="dark"] .modal-header {
  background: var(--bg-muted);
  filter: none;   /* drop the legacy IE white→grey gradient filter */
}
[data-theme="dark"] .modal-header h1,
[data-theme="dark"] .modal-header h2,
[data-theme="dark"] .modal-header h3,
[data-theme="dark"] .modal-header h4,
[data-theme="dark"] .modal-header h5,
[data-theme="dark"] .modal-title,
[data-theme="dark"] .modal-header p {
  color: var(--fg-1);
}
[data-theme="dark"] .modal-footer {
  border-top-color: var(--border-subtle);
}
[data-theme="dark"] .modal .form-control,
[data-theme="dark"] .modal input[type="text"],
[data-theme="dark"] .modal input[type="email"],
[data-theme="dark"] .modal input[type="number"],
[data-theme="dark"] .modal input[type="search"],
[data-theme="dark"] .modal input[type="password"],
[data-theme="dark"] .modal textarea,
[data-theme="dark"] .modal select {
  background: var(--bg-page);
  color: var(--fg-1);
  border-color: var(--border-default);
}
/* Bootstrap's close button is a dark SVG; invert it to read on dark. */
[data-theme="dark"] .btn-close {
  filter: invert(1) grayscale(1) brightness(1.6);
}

/* ---- Trumbowyg rich-text editor (registration-wizard / mail-body modals) - */
[data-theme="dark"] .trumbowyg-box {
  background: var(--bg-page);
  color: var(--fg-1);
  border-color: var(--border-default);
}
/* The mail body (.mail-body) is an email canvas — authored for a WHITE background (black body text,
   inline red/blue colours, a logo on white). Keep it light even in dark mode, or that black text is
   invisible against a dark canvas; only the frame + toolbar go dark, so the WYSIWYG surface still
   matches what the recipient will actually see. The .trumbowyg-textarea (source/HTML view) gets the
   same treatment. The enrollment-wizard editor (.wiz-body) is deliberately NOT included: its pages
   carry their OWN designed background image + light text, so forcing it white would hide both — it
   keeps its own styling, exactly as in light mode. */
[data-theme="dark"] .mail-body,
[data-theme="dark"] .trumbowyg-textarea {
  background: #ffffff;
  color: #1f2328;
}
/* Trumbowyg builds its own visible contentEditable canvas (.trumbowyg-editor) and does NOT copy the
   source .mail-body class onto it, so the rule above never reaches the actual editing surface. Worse,
   the mail editor's own layout rules are ID-scoped —
     #mailModalFullscreen .trumbowyg-box    { background: var(--bg-page) }  (dark canvas)
     #mailModalFullscreen .trumbowyg-editor { color: var(--fg-1) }         (theme-following text)
   — so a class-only override (specificity 30) loses to them (110): the black mail text sat on a dark
   canvas, and a class-level background:#fff would only have flipped it to white-on-white. Re-light the
   content canvas with a MATCHING #mailModalFullscreen scope (specificity 120) so it wins, pinning BOTH
   the background and the default text colour to the light-mode look — this is the email canvas, always
   authored for white, so the WYSIWYG surface matches what the recipient sees. Frame + toolbar stay
   dark. Inline colours in the mail body still win (inline styles), so coloured text is unaffected. */
[data-theme="dark"] #mailModalFullscreen .trumbowyg-editor,
[data-theme="dark"] #mailModalFullscreen .trumbowyg-editor-box {
  background: #ffffff;
  color: #1f2328;
}
/* NOTE: the enrollment-wizard editor is deliberately NOT re-lit here. Unlike the mail canvas (authored
   for white), a wizard page carries its OWN design (background image + light text), and the editor's
   #wizModalFullscreen .trumbowyg-editor { color: var(--fg-1) } already renders LIGHT text on that dark
   page background in dark mode — which matches the enrollment-page preview. Forcing it light/dark broke
   exactly that. So the wizard editor keeps the stock theme behaviour. */
[data-theme="dark"] .trumbowyg-button-pane {
  background: var(--bg-muted);
  border-bottom-color: var(--border-subtle);
}
[data-theme="dark"] .trumbowyg-button-pane::after {
  background: var(--border-subtle);
}
/* Toolbar glyphs are dark SVGs — lighten them. */
[data-theme="dark"] .trumbowyg-button-pane button svg {
  filter: invert(0.9);
}
[data-theme="dark"] .trumbowyg-button-pane .trumbowyg-button-group::after {
  background: var(--border-subtle);
}
[data-theme="dark"] .trumbowyg-dropdown {
  background: var(--bg-subtle);
  border-color: var(--border-default);
  box-shadow: var(--shadow-md);
}
[data-theme="dark"] .trumbowyg-dropdown button {
  background: var(--bg-subtle);
  color: var(--fg-1);
}
[data-theme="dark"] .trumbowyg-dropdown button:hover {
  background: var(--bg-muted);
}

/* ---- Modal left-column option buttons (mail-step / wizard-page pills) -----
   .email-option-buttons / .wizard-option-buttons render white pills with dark
   ink; the active one fills #f1f3f7, and the section divider label sits on a
   white chip. Remap all three to the dark tokens. */
[data-theme="dark"] .modal-fullscreen .email-option-buttons button,
[data-theme="dark"] .modal-fullscreen .wizard-option-buttons button {
  background-color: var(--bg-page);
  color: var(--fg-1);
  border-color: var(--border-default);
}
[data-theme="dark"] .modal-fullscreen .email-option-buttons button:hover,
[data-theme="dark"] .modal-fullscreen .wizard-option-buttons button:hover {
  background: transparent;
  border-color: var(--border-brand);
}
[data-theme="dark"] .modal-fullscreen .email-option-buttons button.email-active-button,
[data-theme="dark"] .modal-fullscreen .wizard-option-buttons button.wizard-active-button {
  background: var(--bg-muted);
}
/* The "Wizard Pages" / "Erinnerungs-Aktionen" label chip overlapping the
   divider line — match the modal surface so it blends instead of glowing white. */
[data-theme="dark"] section.reminder-actions h2,
[data-theme="dark"] section.wizard-actions h2 {
  background-color: var(--bg-subtle);
  color: var(--fg-2);
}

/* ---- Native <select> option lists ----------------------------------------
   Leave the popup to the UA via color-scheme:dark (set on the root above).
   We deliberately do NOT force `option { color }`: many browsers honour the
   option text colour but ignore its background, which would paint light text
   on the UA's white popup (unreadable). UA rendering stays readable either way.
   The app's visible filter/sort pickers are select2 (themed below), not native. */

/* ---- Second navigation / stats bar (Customers & Migrations summary) -------
   .second-navigation h5 is hardcoded #333c48 (dark) — unreadable on the dark
   navbar; its toolbar buttons (.toolsflat-button) hold dark-SVG <img> icons
   that vanish, leaving empty boxes. Lift the text/links/separator and brighten
   the icons. */
[data-theme="dark"] .second-navigation h5 {
  color: var(--fg-1);
}
[data-theme="dark"] .second-navigation h5 a {
  color: var(--fg-link);
}
[data-theme="dark"] .second-navigation .navbar-separator {
  color: var(--fg-3);
}
[data-theme="dark"] .second-navigation img,
[data-theme="dark"] .toolsflat-button img,
[data-theme="dark"] li.toolsflat-button img,
[data-theme="dark"] .show-mailwatch img {
  filter: brightness(0) invert(0.85);
}
/* …but the language flags are meaningful colour images, not monochrome glyphs —
   keep them untouched (id selector beats the rule above). */
[data-theme="dark"] #ad-lang img {
  filter: none;
}

/* Dark-glyph section/title icons that sit on now-dark surfaces:
   the support modal header icon (support.svg) and the licenses page
   section titles (shopping.svg / history.svg). They are dark artwork
   with no -white variant, so invert them like the toolbar glyphs above. */
[data-theme="dark"] #supportModal .modal-header img,
[data-theme="dark"] .caption-admins h3 img,
[data-theme="dark"] .newsTest img,
[data-theme="dark"] .newsEdit img,
[data-theme="dark"] .newsDelete img,
[data-theme="dark"] .schedEdit img,
[data-theme="dark"] .schedDelete img {
  filter: brightness(0) invert(0.85);
}

/* ---- Toolbar dropdown captions + values (List type / Sort by) -------------
   The little labels and the selected value both read dim; pin them to the
   light tokens (native <select> and the select2 rendering both covered). */
[data-theme="dark"] .select-caption p {
  color: var(--fg-2);
}
[data-theme="dark"] .migrator-select select {
  color: var(--fg-1) !important;
}
[data-theme="dark"] .select2-selection__rendered {
  color: var(--fg-1) !important;
}

/* ---- SMS "test" append button (white box + dark envelope SVG, !important) - */
[data-theme="dark"] .smsNotificationTest {
  background-color: var(--bg-muted);
  border-color: var(--border-default);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23C7C9CC' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Cpath d='m3 7 9 6 9-6'/%3E%3C/svg%3E") !important;
}

/* ============================================================================
   Dark mode — round 4: dropdown popups that were still light/unreadable
   ----------------------------------------------------------------------------
   These come LAST and use !important on purpose: the select2 results list and
   the trumbowyg item list both carry hardcoded white/#333 that the earlier
   (non-important) rules don't reliably beat across the whole popup.
   ========================================================================== */

/* select2 open popup — force the entire popup dark (container + results list +
   options), not just the search field. */
[data-theme="dark"] .select2-dropdown,
[data-theme="dark"] .select2-container--default .select2-dropdown,
[data-theme="dark"] .select2-results,
[data-theme="dark"] .select2-results__options {
  background-color: var(--bg-subtle) !important;
  border-color: var(--border-default) !important;
}
[data-theme="dark"] .select2-results__option {
  color: var(--fg-1) !important;
  background-color: transparent !important;
}
[data-theme="dark"] .select2-container--default .select2-results__option--highlighted,
[data-theme="dark"] .select2-container--default .select2-results__option--highlighted[aria-selected] {
  background-color: var(--ebf-blue-600) !important;
  color: var(--ebf-white) !important;
}
[data-theme="dark"] .select2-container--default .select2-results__option[aria-selected="true"] {
  background-color: var(--bg-muted) !important;
  color: var(--fg-1) !important;
}
[data-theme="dark"] .select2-search__field {
  background-color: var(--bg-page) !important;
  border-color: var(--border-default) !important;
  color: var(--fg-1) !important;
}

/* trumbowyg "{...}" / formatting dropdown — items are #FFF bg + #333 !important
   text; both need overriding (the text colour with !important). */
[data-theme="dark"] .trumbowyg-dropdown {
  background: var(--bg-subtle) !important;
  border-color: var(--border-default) !important;
}
[data-theme="dark"] .trumbowyg-dropdown button {
  background: var(--bg-subtle) !important;
  color: var(--fg-1) !important;
}
[data-theme="dark"] .trumbowyg-dropdown button:hover,
[data-theme="dark"] .trumbowyg-dropdown button:focus {
  background: var(--bg-muted) !important;
}

/* ---- Trumbowyg insert-image / upload / link modal box --------------------
   The modal-box is hardcoded #FFF with a #fbfcfc title bar, #DEDEDE-bordered
   inputs and a light-grey reset button. Remap the whole surface; the green
   submit button stays as-is (brand colour reads fine on dark). */
[data-theme="dark"] .trumbowyg-modal-box {
  background-color: var(--bg-page);
  color: var(--fg-1);
  border: 1px solid var(--border-default);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
}
[data-theme="dark"] .trumbowyg-modal-box .trumbowyg-modal-title {
  background: var(--bg-muted);
  color: var(--fg-1);
  border-bottom-color: var(--border-subtle);
}
[data-theme="dark"] .trumbowyg-modal-box label {
  color: var(--fg-1);
}
[data-theme="dark"] .trumbowyg-modal-box label .trumbowyg-input-infos span {
  color: var(--fg-2);
  background-color: var(--bg-muted);
  border-color: var(--border-default);
}
[data-theme="dark"] .trumbowyg-modal-box label input {
  background: var(--bg-subtle);
  color: var(--fg-1);
  border-color: var(--border-default);
}
[data-theme="dark"] .trumbowyg-modal-box label input:hover,
[data-theme="dark"] .trumbowyg-modal-box label input:focus {
  border-color: var(--border-brand);
  background: var(--bg-subtle);
}
[data-theme="dark"] .trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-reset {
  background: var(--bg-muted);
  color: var(--fg-1);
}
[data-theme="dark"] .trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-reset:hover,
[data-theme="dark"] .trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-reset:focus {
  background: var(--bg-subtle);
}

/* ---- Mail-templates Sent/Pending/Failed counter box -----------------------
   #messageSendDiv is a hardcoded #f1f3f7 box at opacity:0.6 — on dark it washes
   out to an unreadable grey patch. Give it a real dark surface at full opacity. */
[data-theme="dark"] #messageSendDiv {
  background-color: var(--bg-subtle);
  border-color: var(--border-default);
  color: var(--fg-1);
  opacity: 1;
}

/* ---- Help dropdown version footer -----------------------------------------
   .dropdown-item-version is near-black text (rgba(0,0,0,.4)) on a black tint
   band — invisible on dark. Lift the text and use a light tint for the band. */
[data-theme="dark"] span.dropdown-item-version {
  background-color: rgba(255, 255, 255, 0.2 );
  color: var(--fg-3);
}

/* The closed select2 control box itself — select2 paints `.select2-selection`
   `#fff` at the same specificity as the round-1 rule, so order alone is
   fragile; pin the base class with !important (covers single + multiple, and
   the .select-style-wrapped Responsible/Currency pickers). */
[data-theme="dark"] .select2-selection {
  background-color: var(--bg-subtle) !important;
  border-color: var(--border-default) !important;
}

/* Active / open / hovered trumbowyg toolbar buttons turn #FFF (e.g. the open
   "{...}" placeholder dropdown, the code-view button); keep them dark. */
[data-theme="dark"] .trumbowyg-button-pane button:not(.trumbowyg-disable):hover,
[data-theme="dark"] .trumbowyg-button-pane button:not(.trumbowyg-disable):focus,
[data-theme="dark"] .trumbowyg-button-pane button.trumbowyg-active,
[data-theme="dark"] .trumbowyg-button-pane button.trumbowyg-open-dropdown {
  background-color: var(--bg-muted) !important;
}

/* ============================================================================
   Dark mode — licenses.html / settings-style pages (body.settingsPage)
   ----------------------------------------------------------------------------
   licenses.html now links this file + colors_and_type.css + theme.js. The
   generic navbar/footer/table/select2/modal rules above already cover most of
   it; these handle the page-specific surfaces. */

/* Order-type cards: the unselected (white) card → dark surface. :not(.active)
   so the selected card keeps its own brand-blue fill (and its green hover). */
[data-theme="dark"] .payment-cards:not(.active) {
  background: var(--bg-subtle);
  border-color: var(--border-default);
  color: var(--fg-1);
}

/* Form fields (text/date/email/number etc.) across all dark pages. Bootstrap's
   .form-control defaults to a white background, which left inputs white on the
   detail/edit pages (news-details "Bezeichnung", schedule-details dates/e-mail,
   …). General rule; the customer-tile / modal field rules above are more (or
   equally) specific where they need different treatment. */
[data-theme="dark"] .form-control {
  background: var(--bg-subtle);
  color: var(--fg-1);
  border-color: var(--border-default);
}
[data-theme="dark"] .form-control::placeholder {
  color: var(--fg-3);
}

/* The mail-subject / push / sms fields in the "Message to all" send dialog
   (dashboard + project-details) hardcode `color:#2b3e51 !important` (dark navy)
   in dashboard.css, so the generic .form-control rule above can't beat it and
   the subject/push/sms text rendered near-invisible on dark. Re-assert the
   token, matching the !important. */
[data-theme="dark"] .form-email-subject,
[data-theme="dark"] .form-push,
[data-theme="dark"] .form-sms,
[data-theme="dark"] .form-pn {
  color: var(--fg-1) !important;
}

/* Same trap on the shared form chrome: dashboard.css `.migration-form input`
   hardcodes `color:#2b3e51 !important` (dark navy). This form class is reused on
   the whole SETTINGS page (and the new-migration wizard), so every text/password/
   number input rendered dark-navy on the dark field background = unreadable. The
   token-based .wz-page/.form-control colours are non-!important and can't beat it.
   Re-assert the token with a more specific !important selector. */
[data-theme="dark"] .migration-form input {
  color: var(--fg-1) !important;
}

/* Settings tab bar (Buy Licenses / Buy Services / Order History + the injected
   theme toggle). The current tab is hardcoded #2b3e51 (dark) → unreadable. */
[data-theme="dark"] .navbar-nav-settings ul li a {
  color: var(--fg-3);
}
[data-theme="dark"] .navbar-nav-settings ul li.current a {
  color: var(--fg-1);
}

/* ============================================================================
   Dark mode — modal-internal light elements
   (file-picker button, info/status boxes, export-format cards)
   ========================================================================== */

/* The grey "Datei wählen" pill on custom file inputs (#e8eaec). */
[data-theme="dark"] .file-upload-button-blue {
  background: var(--bg-muted);
  color: var(--fg-1);
}

/* Mobileconfig / plist status box (#eef0f5). */
[data-theme="dark"] .file-plist {
  background-color: var(--bg-muted);
  color: var(--fg-1);
}

/* "Important note" info box — bg/text/border now come from tokens that flip in
   dark (--bg-brand-subtle / --fg-2 / --border-default in dashboard.css), so the
   box follows automatically. Only the red heading needs help: its light value
   (#9c3e3c) is too dark to read on the dark box — brighten to the EBF red. */
[data-theme="dark"] .importantNote span {
  color: var(--ebf-red-500);
}

/* Dialog warning box (.dlgalert): the pale-yellow bg (#ffffd3) glares on dark.
   Drop it onto a muted surface and brighten the red border/text to the EBF red. */
[data-theme="dark"] .dlgalert {
  background-color: var(--bg-muted);
  border-color: var(--ebf-yellow-700);
  border-left-color: var(--ebf-yellow-500);
  color: var(--ebf-yellow-300);
}

/* Wizard step labels (Name / Quelle / Ziel / … / Speichern) above the line are
   hardcoded dark navy (#2b3e51) — unreadable on the dark canvas. Lift the base
   step text to a light token; the current step is the brightest text (the brand
   blue would be too low-contrast on black — the filled dot already marks it). */
[data-theme="dark"] .migrator-multi-steps li > * {
  color: var(--fg-2);
}
[data-theme="dark"] .migrator-multi-steps li.current > * {
  color: var(--fg-1);
}

/* ============================================================================
   Dark mode — login / splash pages (register.css: login, login_master, intro)
   ----------------------------------------------------------------------------
   These only now link theme.js, so the `[data-theme="dark"]` prefix already
   limits the rules to them (register.html / forgot-password have no toggle).
   body bg/text + the logo whitening come from the generic rules above; the
   login form inputs are `.migrator-form input/select` (white by default). */
[data-theme="dark"] .migrator-form input,
[data-theme="dark"] .migrator-form select,
[data-theme="dark"] .migrator-form textarea {
  background: var(--bg-subtle);
  color: var(--fg-1);
  border-color: var(--border-default);
}
[data-theme="dark"] .migrator-form input::placeholder {
  color: var(--fg-3);
}
/* The login/splash canvas: register.css hardcodes body { background:#fff }. The
   generic rule sets it, but pin it here too in case register.css loads later. */
[data-theme="dark"] body.white,
[data-theme="dark"] body.intro-page {
  background: var(--bg-page);
  color: var(--fg-1);
}

/* ---- Login/splash layout quirks (register.css pages) ---------------------
   Scoped via :has(.container-align) so ONLY the register.css pages are touched
   (app pages have no .container-align, so their toggle stays at z-index 1035,
   below modals). Two fixes, independent of light/dark:
   1) register.css gives the centered content cell .container-align
      z-index:1000000, which buries the fixed top-right toggle — lift the toggle
      above it (these pages have no Bootstrap modal, so no conflict).
   2) Their `body{overflow:auto;width:100%;height:100%}` + `main{display:table}`
      full-height layout yields a stray horizontal scrollbar; clip the x-axis on
      body (does not clip the fixed toggle, whose containing block is the viewport). */
body:has(.container-align) .theme-toggle--fixed,
body:has(.container-align) .festive-off,
body:has(.container-align) .mcf-peek {
  z-index: 1000001;
}
/* The raining-icons overlay must fall over everything (footer at 1000000 + the lifted
   controls), as it does on app pages. It is pointer-events:none, so the controls below
   it stay clickable. Above the controls (1000001) so confetti renders in front of them. */
body:has(.container-align) .festive-layer {
  z-index: 1000002;
}
body:has(.container-align) {
  overflow-x: hidden;
}

/* ============================================================================
   Brand lockup — uniform EBF logo + "Onboarder" wordmark in the app header.
   The header <img> now points directly at ebf-logo-dark.svg in each page's HTML
   (no CSS `content:` swap); this rule only sizes it and appends the "Onboarder"
   wordmark so all headers stay identical (matches the design template).
   ============================================================================ */
.migrator-logo a {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
}
.migrator-logo a img {
  width: auto !important;
  height: 24px !important;
  padding: 0 !important;
}
.migrator-logo a::after {
  content: "Onboarder";
  font-family: var(--font-title);
  font-weight: var(--fw-medium, 600);
  font-size: 18px;
  letter-spacing: -0.01em;
  color: var(--fg-1);
  border-left: 1px solid var(--border-default);
  padding-left: 11px;
  line-height: 1;
  white-space: nowrap;
}

/* Vertically centre the logo lockup with the right-hand nav actions. */
.navbar .row-relative {
  align-items: center;
}
.navbar .migrator-logo {
  display: flex;
  align-items: center;
  float: none;
}

/* Full-width header bar with 32px side padding (template layout), applied to
   every page that loads this stylesheet so all headers are identical. */
.navbar .container {
  max-width: none;
  padding-left: 32px;
  padding-right: 32px;
}

/* ---- Primary button brand-gradient hover -----------------------------------
   Mirrors the EBF template (app.css .btn-primary::after): every primary button
   keeps its solid blue background and, on hover, fades in a blue→green brand
   gradient via a pseudo overlay behind the label. Uses the existing token
   var(--gradient-brand) (colors_and_type.css: linear-gradient(90deg,
   --ebf-blue-500 0%, --ebf-green-500 100%); flips per theme). Placed here so it
   applies app-wide (this file is loaded on every ONE-DESIGN page). Light/outline
   .btn-primary variants opt out via `.btn-primary::after { display: none }`
   (e.g. the list-view "open" button). */
.btn-primary { position: relative; isolation: isolate; }
.btn-primary::after {
  content: ""; position: absolute; inset: -1px; border-radius: inherit;
  z-index: -1; background: var(--gradient-brand); opacity: 0;
  transition: opacity 140ms ease-out; pointer-events: none;
}
.btn-primary:hover { border-color: transparent; }
.btn-primary:hover::after { opacity: 1; }
.btn-primary:disabled::after,
.btn-primary.cat-disabled::after { display: none; }
