:root {
  --theme-palette-primary: #ff2945;
  --theme-palette-secondary: #262626;
  --theme-palette-light: #FFFFFF;
  --theme-palette-soft-light: #F5F5F5;
  --theme-palette-dark: #161616;
  --theme-palette-soft-dark: #7C7C7C;
  --theme-palette-light-borders: #DDDDDD;
  --theme-palette-dark-borders: #242424;
  --theme-palette-error: #E3000F;
  --theme-palette-warning: #F3BE02;
  --theme-palette-success: #008A00;
}

/* Dark-mode spike: mirror of :root with the per-instance dark palette
   (THEME_DARK_PALETTE_*, settings/style/theme.py). Cascades over :root whenever
   <html data-theme="dark"> is set by the theme controller in base.html. Every
   legacy surface that reads --theme-palette-* / --Color* flips for free; surfaces
   still using compile-time LESS hex (@brand-primary etc.) won't and need a
   per-surface override or a LESS->var migration (the spike inventory). */
[data-theme="dark"] {
  --theme-palette-primary: #1686FF;
  --theme-palette-secondary: #8252FF;
  --theme-palette-light: #292C39;
  --theme-palette-soft-light: #4D546A;
  --theme-palette-dark: #FFFFFF;
  --theme-palette-soft-dark: #F6F9FB;
  --theme-palette-light-borders: #7C8A9C;
  --theme-palette-dark-borders: #E4ECF3;
  --theme-palette-error: #E3000F;
  --theme-palette-warning: #F3BE02;
  --theme-palette-success: #008A00;
}

/* Dark-mode spike overrides: legacy chrome (navbar, search card) is compiled-LESS
   with authored/hardcoded colors that don't read the tokens, so the flip above can't
   reach it. Re-point the obvious surfaces at the (now dark) neutral tokens at runtime
   — no bundle rebuild. This is the "authored colors need per-surface handling"
   finding, same as next/. Not exhaustive; the real work is a LESS->var migration. */
[data-theme="dark"] header.navs,
[data-theme="dark"] header.navs .navbar,
[data-theme="dark"] header.navs .navbar-secondary {
  background-color: var(--theme-palette-light) !important;
  border-color: var(--theme-palette-light-borders) !important;
}

[data-theme="dark"] header.navs a,
[data-theme="dark"] header.navs button,
[data-theme="dark"] header.navs [class*="Text"],
[data-theme="dark"] header.navs [class*="label"] {
  color: var(--theme-palette-dark) !important;
}

[data-theme="dark"] [class*="SearchBar"] {
  background-color: var(--theme-palette-light) !important;
  color: var(--theme-palette-dark) !important;
}

[data-theme="dark"] [class*="SearchBar"] input {
  background-color: var(--theme-palette-soft-light) !important;
  color: var(--theme-palette-dark) !important;
}

/* Page surface + Bootstrap content containers. The legacy <body> and Bootstrap
   panels/wells hardcode white (Bootstrap defaults / brand LESS), so the token flip
   can't reach them. Re-point the broad content surfaces at the dark neutral ramp:
   page + cards both sit on --theme-palette-light and stay delineated by their
   border (BDS: cards keep their border at every elevation). */
[data-theme="dark"] body {
  background-color: var(--theme-palette-light) !important;
  color: var(--theme-palette-dark) !important;
}

[data-theme="dark"] .panel,
[data-theme="dark"] .panel-default,
[data-theme="dark"] .panel-heading,
[data-theme="dark"] .panel-footer,
[data-theme="dark"] .well,
[data-theme="dark"] .card {
  background-color: var(--theme-palette-light) !important;
  border-color: var(--theme-palette-light-borders) !important;
  color: var(--theme-palette-dark) !important;
}

/* Chapter directory map: the map container/gutters hardcode a light neutral
   (#f6f9fb) behind the tiles. Darken the container so the seams match. */
[data-theme="dark"] [class*="ChapterMap"],
[data-theme="dark"] .image-map {
  background-color: var(--theme-palette-light) !important;
}

/* Bootstrap form inputs hardcode white. Treat them as inset surfaces (soft-light)
   with light text, same role as the SearchBar input above. */
[data-theme="dark"] .form-control,
[data-theme="dark"] select.form-control,
[data-theme="dark"] textarea.form-control {
  background-color: var(--theme-palette-soft-light) !important;
  border-color: var(--theme-palette-light-borders) !important;
  color: var(--theme-palette-dark) !important;
}

[data-theme="dark"] .form-control::placeholder {
  color: var(--theme-palette-soft-dark) !important;
}

/* Homepage landing hero + location widget. These sections hardcode white and the
   text already flips to white via the token, so in dark mode they render white-on-
   white (invisible). Scope to body.homepage and darken the surfaces. */
[data-theme="dark"] body.homepage .holder,
[data-theme="dark"] body.homepage .intro-text,
[data-theme="dark"] body.homepage .location-widget,
[data-theme="dark"] body.homepage [class*="LocationWidget"],
[data-theme="dark"] body.homepage [class*="IconBlock"] {
  background-color: var(--theme-palette-light) !important;
  color: var(--theme-palette-dark) !important;
}

/* Homepage "groups by region" + location-carousel cards. Unlike the surfaces above,
   these are painted white by per-instance ADMIN style settings in generalstyles.css
   (HOMEPAGE_MAP_GROUPS_BY_REGION_BACKGROUND_COLOR, the carousel card color) rendered
   at high specificity with !important. The real fix is a dark-variant of those admin
   settings (cf. THEME_DARK_PALETTE_*); for the spike we out-specify them at runtime.
   Selectors mirror the admin rules + a [data-theme] prefix so dark wins. */
[data-theme="dark"] .main-dashboard.on-home-page #react-main-chapter-list-root > .holder {
  background-color: var(--theme-palette-light) !important;
}

[data-theme="dark"] .location-widget .location-carousel .slider-frame .slider-list .slider-slide a.icon-block {
  background-color: var(--theme-palette-light) !important;
  color: var(--theme-palette-dark) !important;
}

/* Legacy text color. Like the surfaces above, legacy typography color is driven by
   per-instance ADMIN settings (GENERAL_HEADING_FONT_COLOUR, GENERAL_PARAGRAPH_FONT_
   COLOR, …) baked as fixed dark values with !important — no dark variant — so in dark
   mode headings collapse into the bg and body grays drop below contrast. Re-point the
   "general" typography families at the light neutral ramp. Paragraph rules carry ID-
   level specificity via body:not(#main-dashboard), so the override mirrors that. The
   real fix is dark-variant admin color settings (cf. THEME_DARK_PALETTE_*). */
[data-theme="dark"] .general-h1,
[data-theme="dark"] .general-h1 > a,
[data-theme="dark"] .general-body h1,
[data-theme="dark"] .general-body h2,
[data-theme="dark"] .general-body--color h1,
[data-theme="dark"] .general-body--color h2,
[data-theme="dark"] .section-header,
[data-theme="dark"] .chapters-title,
[data-theme="dark"] .page-title {
  color: var(--theme-palette-dark) !important;
}

[data-theme="dark"] body:not(#main-dashboard) .general-body,
[data-theme="dark"] body:not(#main-dashboard) .general-body--color,
[data-theme="dark"] body:not(#main-dashboard) .general-body--color h4,
[data-theme="dark"] .about-message {
  color: var(--theme-palette-soft-dark) !important;
}

[data-theme="dark"] .date,
[data-theme="dark"] .post-timestamp,
[data-theme="dark"] .blog-live-author,
[data-theme="dark"] .blog-live-time {
  color: var(--theme-palette-light-borders) !important;
}

/* High-specificity admin color rules need same-or-higher specificity to override.
   The blocks below mirror the exact generalstyles.css / homepage admin selectors
   (which carry IDs and/or :not(#main-dashboard) and !important) with a [data-theme]
   prefix so the dark override wins on specificity, not just source order. These exist
   because per-widget admin color settings have no dark variant — the scalable fix is
   to add dark-variant admin settings, not to mirror every selector here. */

/* Homepage intro hero (HOMEPAGE intro title/paragraph) */
[data-theme="dark"] .intro-text .section-header,
[data-theme="dark"] .intro-text .general-h1 {
  color: var(--theme-palette-dark) !important;
}
[data-theme="dark"] .intro-text .about-message {
  color: var(--theme-palette-soft-dark) !important;
}

/* Homepage "groups by region" heading + region cards */
[data-theme="dark"] .main-dashboard.on-home-page #react-main-chapter-list-root > .holder .chapters-title {
  color: var(--theme-palette-dark) !important;
}
[data-theme="dark"] #react-main-chapter-list-root .row.regions-list .chapter-item strong {
  color: var(--theme-palette-dark) !important;
}
[data-theme="dark"] #react-main-chapter-list-root .row.regions-list .chapter-item span {
  color: var(--theme-palette-light-borders) !important;
}

/* General tabs (List / Calendar) inherit the general-body link color; mirror that
   selector chain + one extra class so the dark override out-specifies it. */
[data-theme="dark"] body:not(#main-dashboard) .general-body a.general-tab:not(.general-body--exclude):not(.btn),
[data-theme="dark"] body:not(#main-dashboard) .general-body--color a.general-tab:not(.general-body--exclude):not(.btn) {
  color: var(--theme-palette-light-borders) !important;
}

/* Blog post titles (compiled brand gray, not admin-driven) */
[data-theme="dark"] .blog-posts .blog-live-title > a,
[data-theme="dark"] .blog-live-title > a {
  color: var(--theme-palette-dark) !important;
}

/* Bootstrap dropdown panels — the user-menu dropdown and the per-item ⋮ (kebab)
   menus (notifications, etc.) render a Bootstrap `.dropdown-menu` panel that is
   compiled-LESS white (Bootstrap default) and is not reached by the chrome/token
   overrides above, so it's white-on-white in dark (DM-023, DM-030). Re-point the
   panel, its items, hover state and dividers at the dark neutral ramp. */
[data-theme="dark"] .dropdown-menu {
  background-color: var(--theme-palette-light) !important;
  border-color: var(--theme-palette-light-borders) !important;
}
[data-theme="dark"] .dropdown-menu > li > a,
[data-theme="dark"] .dropdown-menu > li > button,
[data-theme="dark"] .dropdown-menu li > a,
[data-theme="dark"] .dropdown-menu [class*="Text"] {
  color: var(--theme-palette-dark) !important;
}
[data-theme="dark"] .dropdown-menu > li > a:hover,
[data-theme="dark"] .dropdown-menu > li > a:focus,
[data-theme="dark"] .dropdown-menu > li > button:hover,
[data-theme="dark"] .dropdown-menu > li > button:focus {
  background-color: var(--theme-palette-soft-light) !important;
  color: var(--theme-palette-dark) !important;
}
[data-theme="dark"] .dropdown-menu .divider {
  background-color: var(--theme-palette-light-borders) !important;
}

/* Dark-mode toggle in the user menu (pages/menus/dark-mode-toggle.html). A visual
   twin of the Next.js header's ThemeToggle (label + Sun · switch · Moon) so the two
   headers match. Replicates ThemeToggle.module.scss with the --theme-palette-* tokens
   (1:1 with the Next version's --Color* tokens) and drives state from <html data-theme>
   instead of React. Not theme-scoped — it's a real control that renders in both modes;
   the [data-theme="dark"] rules below flip its active state. */
.top-nav-dragon .main-menu.dropdown-menu > li.theme-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 8px;
  color: var(--theme-palette-soft-dark);
  font-size: 14px;
  font-weight: 400;
  line-height: 136%;
}

.theme-toggle__label {
  flex: 1;
}
.theme-toggle__label--dark {
  display: none;
}
[data-theme="dark"] .theme-toggle__label--light {
  display: none;
}
[data-theme="dark"] .theme-toggle__label--dark {
  display: block;
}

.theme-toggle__control {
  display: flex;
  flex: none;
  align-items: center;
  gap: 8px;
}

.theme-toggle__icon {
  width: 16px;
  height: 16px;
  color: var(--theme-palette-soft-dark);
  opacity: 0.4;
  transition: opacity 120ms linear, color 120ms linear;
}
/* Sun is the active icon in light, Moon in dark. */
.theme-toggle__icon--sun {
  color: var(--theme-palette-primary);
  opacity: 1;
}
[data-theme="dark"] .theme-toggle__icon--sun {
  color: var(--theme-palette-soft-dark);
  opacity: 0.4;
}
[data-theme="dark"] .theme-toggle__icon--moon {
  color: var(--theme-palette-primary);
  opacity: 1;
}

.theme-toggle__switch {
  position: relative;
  width: 38px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--theme-palette-light-borders);
  border-radius: 999px;
  background-color: var(--theme-palette-soft-light);
  cursor: pointer;
  transition: background-color 160ms ease, border-color 160ms ease;
}
[data-theme="dark"] .theme-toggle__switch {
  border-color: var(--theme-palette-primary);
  background-color: var(--theme-palette-primary);
}
.theme-toggle__switch:focus-visible {
  outline: 2px solid var(--theme-palette-primary);
  outline-offset: 2px;
}

.theme-toggle__knob {
  position: absolute;
  top: 50%;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background-color: var(--theme-palette-light);
  box-shadow: 0 1px 2px rgb(0 0 0 / 25%);
  transform: translateY(-50%);
  transition: transform 160ms ease;
}
[data-theme="dark"] .theme-toggle__knob {
  transform: translate(16px, -50%);
}
