/* ==========================================================================
   Taiga Cloud theme for MkDocs Material

   The --scalar-* tokens below are COPIED VERBATIM from static/scalar-theme.css
   and Material's variables are mapped onto them with var(). Keeping the tokens
   rather than inlining their values is what makes the two themes checkable:
   tests/unittests/test_docs_theme.py parses both files and fails if any token
   drifts.

   CANONICAL SOURCE. `make sync-theme` copies this into docs/public/assets/ and
   docs/internal/assets/, which are generated and gitignored. Edit this file.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Typography

   `font: false` in both configs stops Material fetching Google Fonts, matching
   the reference page, which vendors everything.

   Inter is named first but is not self-hosted yet, so both surfaces fall back
   to the system stack. Add static/fonts/Inter-Variable.woff2 and an @font-face
   here to light it up in both places at once.
   -------------------------------------------------------------------------- */

:root {
  --scalar-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
  --scalar-font-code: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --md-text-font-family: var(--scalar-font);
  --md-code-font-family: var(--scalar-font-code);
}

/* --------------------------------------------------------------------------
   Light -- tokens mirror .light-mode in scalar-theme.css
   -------------------------------------------------------------------------- */

[data-md-color-scheme="default"] {
  --scalar-background-1: #ffffff;
  --scalar-background-2: #f6f5f4;
  --scalar-background-3: #f1ede9;
  --scalar-background-accent: #0a85d10f;
  --scalar-color-1: #121212;
  --scalar-color-2: rgba(0, 0, 0, 0.6);
  --scalar-color-3: rgba(0, 0, 0, 0.4);
  --scalar-color-accent: #0a85d1;
  --scalar-border-color: rgba(0, 0, 0, 0.08);
}

/* --------------------------------------------------------------------------
   Dark -- tokens mirror .dark-mode
   -------------------------------------------------------------------------- */

[data-md-color-scheme="slate"] {
  --scalar-background-1: #1a1a1a;
  --scalar-background-2: #212121;
  --scalar-background-3: #2b2b2b;
  --scalar-background-accent: #6cb6ff1f;
  --scalar-color-1: rgba(255, 255, 255, 0.86);
  --scalar-color-2: rgba(255, 255, 255, 0.55);
  --scalar-color-3: rgba(255, 255, 255, 0.35);
  --scalar-color-accent: #6cb6ff;
  --scalar-border-color: rgba(255, 255, 255, 0.1);

  /* Material derives slate's own surfaces from a hue; pin them so the page
     matches the reference exactly rather than approximately. */
  --md-default-bg-color--light: var(--scalar-background-2);
  --md-default-bg-color--lighter: var(--scalar-background-3);
}

/* --------------------------------------------------------------------------
   Mapping -- Material variables onto the Scalar tokens above.
   Scheme-independent: each token already differs per scheme.
   -------------------------------------------------------------------------- */

[data-md-color-scheme] {
  --md-default-bg-color: var(--scalar-background-1);
  --md-default-fg-color: var(--scalar-color-1);
  --md-default-fg-color--light: var(--scalar-color-2);
  --md-default-fg-color--lighter: var(--scalar-color-3);
  --md-default-fg-color--lightest: var(--scalar-border-color);

  --md-primary-fg-color: var(--scalar-color-accent);
  --md-primary-bg-color: var(--scalar-background-1);
  --md-accent-fg-color: var(--scalar-color-accent);
  --md-typeset-a-color: var(--scalar-color-accent);

  --md-code-bg-color: var(--scalar-background-3);
  --md-code-fg-color: var(--scalar-color-1);
}

/* --------------------------------------------------------------------------
   Header

   Material's header is a solid primary-coloured bar; the reference page uses
   the page background with a hairline rule. Matching it is most of what makes
   the two surfaces read as one product.
   -------------------------------------------------------------------------- */

/* The reference page header is 56px; Material's is 48. BOTH the outer bar and
   the inner flex row need the height -- set only the bar and the row keeps
   centring its children on 24 inside a 56px box, leaving everything 4px high.
   One variable so they cannot drift apart. */
:root {
  --tc-header-height: 56px;
}

.md-header {
  height: var(--tc-header-height);
  background-color: var(--scalar-background-1);
  color: var(--scalar-color-1);
  border-bottom: 0px solid var(--scalar-border-color);
  box-shadow: none;
}

.md-header__inner,
.md-header__title {
  height: var(--tc-header-height);
}

.md-header__title {
  font-weight: 600;
}

.md-tabs {
  background-color: var(--scalar-background-1);
  color: var(--scalar-color-1);
  border-bottom: 1px solid var(--scalar-border-color);
}

/* With navigation.tabs the tabs bar renders directly beneath the title row
   and draws its own bottom rule, so the header's would split what should
   read as one bar. `.md-tabs` is a DOM child of the header, but the fixed
   header height means it lays out below the header box -- which is why that
   border appears between the two rows rather than under both. */
.md-header:has(.md-tabs) {
  border-bottom: 0;
}

/* Material hides the tabs below its own 76.25em breakpoint while leaving the
   element in the DOM, so :has() still matches. Put the rule back, or the
   header has nothing separating it from the content. */
@media (max-width: 76.1875em) {
  .md-header:has(.md-tabs) {
    border-bottom: 1px solid var(--scalar-border-color);
  }
}

.md-search__form {
  background-color: var(--scalar-background-2);
  border: 1px solid var(--scalar-border-color);
  border-radius: 8px;
}

.md-search__form:hover {
  background-color: var(--scalar-background-3);
}

/* --------------------------------------------------------------------------
   Logo

   partials/logo.html carries both SVGs; exactly one is shown, driven by the
   scheme attribute Material sets on <body>. Same approach as the reference
   page, which keys off .light-mode / .dark-mode instead.
   -------------------------------------------------------------------------- */

.md-header__button.md-logo {
  display: flex;
  align-items: center;
  padding: 0;
}

/* Scoped to .md-logo, NOT .md-header__button.md-logo: the swap rule below has
   to outrank this one, and a three-class sizing selector would beat it. */
.md-logo .tc-logo {
  display: block;
  width: auto;
  height: 28px;
}

/* Element selector included so this outranks the sizing rule above without
   depending on source order. Applies in the nav drawer too, not just the
   header -- the drawer copy is only hidden by its parent on desktop. */
[data-md-color-scheme="default"] .md-logo svg.tc-logo-dark,
[data-md-color-scheme="slate"] .md-logo svg.tc-logo-light {
  display: none;
}

/* --------------------------------------------------------------------------
   Content
   -------------------------------------------------------------------------- */

.md-typeset code {
  border-radius: 4px;
}

.md-typeset pre > code {
  border: 1px solid var(--scalar-border-color);
  border-radius: 8px;
}

.md-typeset table:not([class]) {
  border: 1px solid var(--scalar-border-color);
  border-radius: 8px;
  font-size: 0.75rem;
}

.md-typeset table:not([class]) th {
  background-color: var(--scalar-background-2);
  font-weight: 600;
}

.md-typeset table:not([class]) td {
  border-top: 1px solid var(--scalar-border-color);
}

.md-typeset h1,
.md-typeset h2 {
  font-weight: 600;
  letter-spacing: -0.01em;
}

.md-typeset h2 {
  border-top: 1px solid var(--scalar-border-color);
  padding-top: 1.2em;
}

.md-typeset h2:first-of-type {
  border-top: 0;
  padding-top: 0;
}

/* --------------------------------------------------------------------------
   Theme toggle

   The pill switch from the reference page, reused here so both surfaces carry
   the same control. Rules are lifted verbatim from static/scalar-theme.css --
   only the scheme hook is translated, because Scalar keys off
   body.light-mode / .dark-mode and Material off [data-md-color-scheme].

   Material's own mechanism is untouched: partials/palette.html still renders
   the radio inputs, and the label still drives them, so persistence and
   system-preference handling stay Material's. Only the label's contents are
   replaced. test_docs_theme.py asserts the geometry stays in step.
   -------------------------------------------------------------------------- */

.tc-theme {
  display: inline-flex;
  align-items: center;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.tc-theme *, .tc-theme-track {
  box-sizing: border-box;
}

.tc-theme-track {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  width: 46px;
  height: 24px;
  padding: 0 5px;
  border: 1px solid var(--scalar-border-color);
  border-radius: 999px;
  background: var(--scalar-background-2);
}

.tc-theme-icon {
  position: relative;
  z-index: 1;
  display: inline-flex;
  color: var(--scalar-color-3);
  transition: color 0.15s ease;
}

.tc-theme-icon svg {
  width: 12px;
  height: 12px;
  display: block;
}

.tc-theme-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: transform 0.18s ease;
}

[data-md-color-scheme="slate"] .tc-theme-knob {
  transform: translateX(22px);
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4);
}

[data-md-color-scheme="default"] .tc-theme-sun, [data-md-color-scheme="slate"] .tc-theme-moon {
  color: #1a1a1a;
}

[data-md-color-scheme="default"] .tc-theme-moon, [data-md-color-scheme="slate"] .tc-theme-sun {
  color: var(--scalar-color-3);
}

.tc-theme:hover .tc-theme-track {
  background: var(--scalar-background-3);
}

/* Honours the OS setting rather than disabling the animation outright --
   the wrapper matters, and was lost once already when these rules were
   lifted across from the reference theme. */
@media (prefers-reduced-motion: reduce) {
  .tc-theme-knob {
    transition: none;
  }
}

/* Material renders one label per palette option, each marked [hidden], and
   its JS unhides the active one. `.tc-theme` sets an explicit display, which
   OVERRIDES the user-agent `[hidden] { display: none }` -- so without this
   both pills render side by side. The reference page never needed it: there
   the control is a plain <button> that is always visible. */
.tc-theme[hidden] {
  display: none;
}

.md-header__option .tc-theme {
  padding: 0 0.4rem;
}

/* Sit next to the logo, as on the reference page, rather than out by search. */
.md-header__button.md-logo {
  order: -2;
}

.md-header__option {
  order: -1;
  margin-right: 0.4rem;
}

/* --------------------------------------------------------------------------
   Help menu

   Sits in the tabs bar after the nav tabs. Styled to match .md-tabs__link so
   it reads as another tab rather than a control dropped beside them.
   -------------------------------------------------------------------------- */

/* The tabs bar and its list are `overflow: auto` for horizontal scrolling,
   which CLIPS an absolutely positioned dropdown to the height of the bar --
   the panel renders but only the sliver inside the bar is visible.

   Scoped with :has() so only the bar carrying the menu loses its scrolling,
   and only on the site that defines extra.tab_menu. Safe here: Material
   hides the tabs entirely below 76.25em, and four tabs never overflow a
   desktop width. Add many more tabs and this is the rule to revisit. */
.md-tabs:has(.tc-tabmenu),
.md-tabs:has(.tc-tabmenu) .md-tabs__list {
  overflow: visible;
}

/* `overflow: visible` alone is not enough: Material sets `contain: content` on
   the list, which includes PAINT containment and clips descendants to the
   padding box whatever overflow says. The dropdown had layout and a correct
   bounding box, but was neither painted nor hit-tested outside the bar. */
.md-tabs:has(.tc-tabmenu) .md-tabs__list {
  contain: none;
}

.tc-tabmenu {
  position: relative;
}

/* `align: end` in the config. `auto` on the inline-start margin absorbs the
   free space in the flex row, so the trigger sits against the right edge of
   the grid column -- in line with the tabs, not with the page. */
.tc-tabmenu--end {
  margin-inline-start: auto;
}

.tc-tabmenu-trigger {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 0;
  background: none;
  cursor: pointer;

  /* NOT `font: inherit`. That resets font-size to the list's 10px and beats
     .md-tabs__link's 14px, leaving the label visibly smaller than the real
     tabs. Only the family needs inheriting -- a <button> does not take it
     from the page, but size and line-height should come from
     .md-tabs__link so the trigger matches its siblings. */
  font-family: inherit;

  /* A <button> also takes the UA's `line-height: normal` rather than the
     tabs' ratio. Inheriting is no good -- the parent's is a computed length
     against a 10px font -- so match the ratio the tab links resolve to. */
  line-height: 1.3;
}

/* SVGs sit on the text baseline by default, which rides high next to the
   label; block takes it out of inline layout so the flex row centres it. */
.tc-tabmenu-chevron {
  display: block;
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  transition: transform 0.15s ease;
}

.tc-tabmenu-trigger[aria-expanded='true'] .tc-tabmenu-chevron {
  transform: rotate(180deg);
}

.tc-tabmenu-panel {
  position: absolute;
  top: calc(100% - 4px);
  right: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  min-width: 180px;
  padding: 4px;
  border: 1px solid var(--scalar-border-color);
  border-radius: 8px;
  background: var(--scalar-background-1);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

.tc-tabmenu-panel[hidden] {
  display: none;
}

.tc-tabmenu-panel a {
  padding: 7px 10px;
  border-radius: 6px;
  color: var(--scalar-color-2);
  font-size: 0.7rem;
  white-space: nowrap;
}

.tc-tabmenu-panel a:hover {
  background: var(--scalar-background-2);
  color: var(--scalar-color-1);
}

@media (prefers-reduced-motion: reduce) {
  .tc-tabmenu-chevron {
    transition: none;
  }
}
