/* Kyvero → MkDocs Material.
 *
 * Everything Material-specific about the theme lives here. `kyvero-tokens.css`
 * is the design system verbatim and is replaced wholesale when it changes; this
 * file is the adapter, and is the only place that knows Material exists.
 *
 * Two things it does, in this order:
 *
 *   1. Point Material's `--md-*` variables at Kyvero tokens, per colour scheme.
 *      Material derives most of its component colours from about thirty
 *      variables, so this alone gets the site most of the way there.
 *   2. Restate the handful of components whose *shape* is wrong rather than
 *      their colour — Material floats things on shadow, Kyvero draws hairlines
 *      and keeps corners nearly square.
 *
 * The design system ships one palette: ink type on a paper ground. The dark
 * counterparts below are derived here rather than in the token file, because
 * they are this site's invention and must not be mistaken for design tokens on
 * the next re-sync.
 */

/* ─────────────────────────────────────────────────────────────────────────────
 * Typefaces
 *
 * `theme.font` is `false` in mkdocs.yml, so Material loads nothing from Google
 * Fonts itself, and the `@font-face` blocks in the token file — pointing at
 * `assets/fonts/` in this repository — are the only place the webfonts are
 * requested. Material still composes its own fallback stacks out of these two
 * hooks.
 * ────────────────────────────────────────────────────────────────────────── */

:root {
  --md-text-font: "Instrument Sans";
  --md-code-font: "IBM Plex Mono";

  /* The token layer ships nine cuts and no more: Instrument Sans stops at 600,
     IBM Plex Mono at 500. Material asks for 700 in about a dozen places, and
     `<strong>` inherits 700 from the browser's own stylesheet — with no such
     face to load, the browser would smear the 600 into a fake bold. This turns
     that off, so a weight the design system did not draw resolves to the
     nearest one it did rather than to a synthesised approximation. The token
     file states the same rule for its own side: never let the browser
     synthesise a weight. Unsupported browsers fall back to synthesising, which
     is the behaviour without this line. */
  font-synthesis-weight: none;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Colour scheme: light
 * ────────────────────────────────────────────────────────────────────────── */

[data-md-color-scheme="default"] {
  /* Material asks for a foreground at four opacities: body text, secondary
     text, icons and disabled state, and hairlines. Ink at descending alpha. */
  --md-default-fg-color: var(--ink-900);
  --md-default-fg-color--light: rgba(20, 22, 26, 0.62);
  --md-default-fg-color--lighter: rgba(20, 22, 26, 0.32);
  --md-default-fg-color--lightest: rgba(20, 22, 26, 0.10);
  --md-default-bg-color: var(--surface-page);
  --md-default-bg-color--light: rgba(250, 249, 247, 0.70);
  --md-default-bg-color--lighter: rgba(250, 249, 247, 0.32);
  --md-default-bg-color--lightest: rgba(250, 249, 247, 0.12);

  /* "Primary" is the brand control colour, which for Kyvero is ink — not the
     accent. The header is deliberately not painted with it; see below. */
  --md-primary-fg-color: var(--control-primary-bg);
  --md-primary-fg-color--light: var(--ink-700);
  --md-primary-fg-color--dark: #0E1013;
  --md-primary-bg-color: var(--paper);
  --md-primary-bg-color--light: rgba(250, 249, 247, 0.70);

  --md-accent-fg-color: var(--accent-600);
  --md-accent-fg-color--transparent: rgba(58, 99, 214, 0.10);
  --md-accent-bg-color: var(--paper);
  --md-accent-bg-color--light: rgba(250, 249, 247, 0.70);

  --md-typeset-color: var(--text-primary);
  --md-typeset-a-color: var(--text-link);
  --md-typeset-mark-color: var(--warning-100);
  --md-typeset-del-color: rgba(196, 54, 47, 0.15);
  --md-typeset-ins-color: rgba(46, 125, 91, 0.15);
  --md-typeset-table-color: var(--line-subtle);
  --md-typeset-kbd-color: var(--white);
  --md-typeset-kbd-accent-color: var(--neutral-100);
  --md-typeset-kbd-border-color: var(--neutral-300);

  --md-code-fg-color: var(--ink-800);
  --md-code-bg-color: var(--surface-sunk);

  --md-admonition-fg-color: var(--text-primary);
  --md-admonition-bg-color: var(--surface-card);

  /* The footer is the marketing site's closing band: ink, full bleed. */
  --md-footer-bg-color: var(--ink-900);
  --md-footer-bg-color--dark: #0E1013;
  --md-footer-fg-color: var(--paper);
  --md-footer-fg-color--light: rgba(250, 249, 247, 0.70);
  --md-footer-fg-color--lighter: rgba(250, 249, 247, 0.45);

  --md-shadow-z1: var(--shadow-1);
  --md-shadow-z2: var(--shadow-2);
  --md-shadow-z3: var(--shadow-3);

  --kyv-header-bg: rgba(250, 249, 247, 0.88);
  --kyv-search-bg: var(--neutral-100);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Colour scheme: dark
 *
 * The semantic layer is restated first, so that every component rule further
 * down can be written once against `--text-primary`, `--line-subtle` and
 * friends without caring which scheme is active.
 * ────────────────────────────────────────────────────────────────────────── */

[data-md-color-scheme="slate"] {
  --text-primary: var(--paper);
  --text-secondary: rgba(250, 249, 247, 0.68);
  --text-muted: rgba(250, 249, 247, 0.55);
  --text-faint: rgba(250, 249, 247, 0.40);
  --text-inverse: var(--ink-900);
  --text-link: var(--accent-400);
  --text-link-hover: var(--paper);

  --surface-page: var(--ink-900);
  --surface-card: var(--ink-800);
  --surface-sunk: #1B1E23;
  --surface-inverse: var(--paper);
  --surface-accent-soft: rgba(58, 99, 214, 0.18);

  /* The hairline the design system already uses on its one inverse surface. */
  --line-subtle: rgba(250, 249, 247, 0.12);
  --line-default: rgba(250, 249, 247, 0.20);
  --line-strong: var(--paper);

  /* Ink-on-ink is invisible, so the primary control takes the accent here. */
  --control-primary-bg: var(--accent-500);
  --control-primary-bg-hover: var(--accent-600);
  --control-secondary-border: rgba(250, 249, 247, 0.24);

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.40);
  --shadow-2: 0 4px 14px rgba(0, 0, 0, 0.45);
  --shadow-3: 0 18px 48px rgba(0, 0, 0, 0.55);
  --ring-accent: 0 0 0 3px rgba(108, 140, 228, 0.35);

  --md-default-fg-color: rgba(250, 249, 247, 0.94);
  --md-default-fg-color--light: rgba(250, 249, 247, 0.66);
  --md-default-fg-color--lighter: rgba(250, 249, 247, 0.36);
  --md-default-fg-color--lightest: rgba(250, 249, 247, 0.13);
  --md-default-bg-color: var(--surface-page);
  --md-default-bg-color--light: rgba(20, 22, 26, 0.70);
  --md-default-bg-color--lighter: rgba(20, 22, 26, 0.32);
  --md-default-bg-color--lightest: rgba(20, 22, 26, 0.12);

  --md-primary-fg-color: var(--control-primary-bg);
  --md-primary-fg-color--light: var(--accent-400);
  --md-primary-fg-color--dark: var(--accent-700);
  --md-primary-bg-color: var(--paper);
  --md-primary-bg-color--light: rgba(250, 249, 247, 0.70);

  --md-accent-fg-color: var(--accent-400);
  --md-accent-fg-color--transparent: rgba(108, 140, 228, 0.14);
  --md-accent-bg-color: var(--ink-900);
  --md-accent-bg-color--light: rgba(20, 22, 26, 0.70);

  --md-typeset-color: var(--text-primary);
  --md-typeset-a-color: var(--text-link);
  --md-typeset-mark-color: rgba(183, 121, 31, 0.35);
  --md-typeset-del-color: rgba(196, 54, 47, 0.28);
  --md-typeset-ins-color: rgba(46, 125, 91, 0.28);
  --md-typeset-table-color: var(--line-default);
  --md-typeset-kbd-color: var(--ink-800);
  --md-typeset-kbd-accent-color: var(--ink-700);
  --md-typeset-kbd-border-color: var(--ink-600);

  --md-code-fg-color: var(--neutral-300);
  --md-code-bg-color: var(--surface-sunk);

  --md-admonition-fg-color: var(--text-primary);
  --md-admonition-bg-color: var(--surface-card);

  --md-footer-bg-color: #0E1013;
  --md-footer-bg-color--dark: #08090B;

  --md-shadow-z1: var(--shadow-1);
  --md-shadow-z2: var(--shadow-2);
  --md-shadow-z3: var(--shadow-3);

  --kyv-header-bg: rgba(20, 22, 26, 0.88);
  --kyv-search-bg: rgba(250, 249, 247, 0.08);
}

/* Admonition tints. One alpha over the tone colour reads correctly on both the
   paper and the ink ground, which is why these are not per-scheme. */
:root {
  --kyv-tint-accent: rgba(58, 99, 214, 0.12);
  --kyv-tint-success: rgba(46, 125, 91, 0.13);
  --kyv-tint-warning: rgba(183, 121, 31, 0.15);
  --kyv-tint-danger: rgba(196, 54, 47, 0.13);
  --kyv-tint-neutral: rgba(124, 121, 115, 0.13);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Header
 *
 * Material paints the header with the primary colour. The marketing site does
 * the opposite: the header is the page ground at 88% with a blur behind it and
 * a single hairline holding it off the content, and the only shadow on the page
 * belongs to things that genuinely float. Match that.
 * ────────────────────────────────────────────────────────────────────────── */

.md-header {
  background-color: var(--kyv-header-bg);
  color: var(--text-primary);
  border-bottom: 1px solid var(--line-subtle);
  backdrop-filter: blur(8px);
  box-shadow: none;
}

.md-header--shadow {
  box-shadow: none;
}

.md-header__title {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-heading);
}

/* The lockup is 3.5:1, so it needs the width Material already leaves it; only
   the drawer copy is oversized for a wordmark of this proportion. */
.md-nav__title .md-nav__button.md-logo .kyvero-logo {
  height: 1.6rem;
}

/* The lockup is live text, so it needs the display face and the two fills that
   turn the ink-on-paper mark into the paper-on-ink one. */
.kyvero-logo {
  font-family: var(--font-display);
}

.kyvero-logo__tile {
  fill: var(--surface-inverse);
}

.kyvero-logo__mark {
  fill: var(--surface-page);
}

.kyvero-logo__word {
  fill: var(--text-primary);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Search
 *
 * Material tints the field with 26% black, which is a hole punched in a dark
 * header. On paper it has to be a filled control with a border instead.
 * ────────────────────────────────────────────────────────────────────────── */

.md-search__form {
  background-color: var(--kyv-search-bg);
  border: 1px solid var(--line-subtle);
  border-radius: var(--radius-md);
  box-shadow: none;
  transition: var(--transition-control);
}

.md-search__form:hover {
  background-color: var(--kyv-search-bg);
  border-color: var(--line-default);
}

.md-search__input {
  font-size: var(--text-sm);
}

.md-search__input::placeholder {
  color: var(--text-faint);
}

.md-search__input ~ .md-search__icon,
.md-search__options > .md-icon {
  color: var(--text-muted);
}

.md-search__output {
  border-radius: 0 0 var(--radius-md) var(--radius-md);
}

.md-search-result__meta {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Navigation
 *
 * The sidebar's top level is one collapsed row per extension, each linking to
 * that extension's overview — see the `features` block in mkdocs.yml for why.
 * It used to be `navigation.sections`, whose top-level entries are unclickable
 * group labels and were set as the marketing site's eyebrows: mono, uppercase,
 * wide tracking. Those rows are ordinary links now, so they are lettered like
 * the rest of the nav and only carry extra weight to mark the level.
 * ────────────────────────────────────────────────────────────────────────── */

.md-nav {
  font-size: var(--text-sm);
}

.md-nav__title {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

.md-nav--primary .md-nav__title {
  /* Titles in the primary nav name a page or a section rather than labelling a
     list, so they are set like a heading and not like an eyebrow. */
  font-family: var(--font-display);
  font-size: var(--text-md);
  letter-spacing: var(--tracking-heading);
  text-transform: none;
  color: var(--text-primary);
  border-bottom: 1px solid var(--line-subtle);
}

/* Below Material's drawer breakpoint the root title becomes a filled band with
   the lockup on it. Material fills it with the primary colour; Kyvero's is ink
   in both schemes, which means this is the one place the reversed lockup is
   always the right one. Scoped to the same media query Material uses, because
   above it the very same element is the plain sidebar title. */
@media screen and (max-width: 76.1875em) {
  .md-nav--primary .md-nav__title[for="__drawer"] {
    background-color: var(--ink-900);
    color: var(--paper);
    font-weight: var(--weight-semibold);
    border-bottom: 0;
  }

  .md-nav--primary .md-nav__title[for="__drawer"] .kyvero-logo__tile {
    fill: var(--paper);
  }

  .md-nav--primary .md-nav__title[for="__drawer"] .kyvero-logo__mark {
    fill: var(--ink-900);
  }

  .md-nav--primary .md-nav__title[for="__drawer"] .kyvero-logo__word {
    fill: var(--paper);
  }
}

.md-nav__link {
  border-radius: var(--radius-sm);
  transition: color var(--duration-fast) var(--ease-standard);
}

/* The top level — Home, the shared pages, and one row per extension. Weight
   only: with a dozen collapsed sections it is the level that needs marking, and
   the row is a real link, so the colour it already has is the right one. The
   selector reaches the `div` wrapping a section's link and its toggle as well
   as a plain link, and the weight inherits from there. */
.md-nav--primary > .md-nav__list > .md-nav__item > .md-nav__link {
  font-weight: var(--weight-medium);
}

.md-nav__link--active,
.md-nav__link--active code {
  font-weight: var(--weight-semibold);
}

.md-sidebar__scrollwrap {
  scrollbar-color: var(--line-default) transparent;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Content
 * ────────────────────────────────────────────────────────────────────────── */

.md-typeset {
  line-height: var(--leading-loose);
}

.md-typeset :is(h1, h2, h3, h4, h5, h6) {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-heading);
  color: var(--text-primary);
}

/* Material's rem is 20px, so these are the display scale: 40 / 30 / 22 / 17. */
.md-typeset h1 {
  font-size: 2rem;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  margin-bottom: 1.2rem;
}

.md-typeset h2 {
  font-size: 1.5rem;
  line-height: var(--leading-snug);
  margin-top: 2rem;
}

.md-typeset h3 {
  font-size: 1.1rem;
  line-height: var(--leading-snug);
}

.md-typeset h4 {
  font-size: 0.85rem;
  margin-top: 1.2rem;
}

/* h5 and h6 stop being headings and become labels, as they do on the site. */
.md-typeset :is(h5, h6) {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Kyvero links are colour-only, which at this palette is a 2.7:1 difference
   from body text — under the 3:1 that colour-as-sole-cue needs. Prose links
   therefore carry a hairline underline; navigation and controls do not. */
.md-typeset a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--md-accent-fg-color--transparent);
  text-underline-offset: 0.15em;
  transition: color var(--duration-fast) var(--ease-standard),
    text-decoration-color var(--duration-fast) var(--ease-standard);
}

.md-typeset a:is(:hover, :focus) {
  color: var(--text-link-hover);
  text-decoration-color: currentcolor;
}

.md-typeset :is(a.headerlink, a.md-content__button, .md-button) {
  text-decoration: none;
}

.md-typeset hr {
  border-bottom-color: var(--line-subtle);
}

.md-typeset blockquote {
  border-left: 2px solid var(--line-default);
  color: var(--text-secondary);
}

.md-typeset ::selection {
  background-color: var(--surface-accent-soft);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Code
 * ────────────────────────────────────────────────────────────────────────── */

.md-typeset code {
  border: 1px solid var(--line-subtle);
  border-radius: var(--radius-sm);
}

.md-typeset pre > code {
  border-radius: var(--radius-md);
}

.md-typeset :is(h1, h2, h3, h4) code {
  font-size: 0.85em;
}

.md-clipboard {
  color: var(--text-faint);
}

.md-clipboard:is(:hover, :focus) {
  color: var(--md-accent-fg-color);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Tables
 *
 * The reference pages are mostly tables, so this is where the hairline rule
 * earns its keep: a boxed grid, no shadow, no zebra.
 * ────────────────────────────────────────────────────────────────────────── */

.md-typeset table:not([class]) {
  border: 1px solid var(--line-subtle);
  border-radius: var(--radius-md);
  box-shadow: none;
  font-size: var(--text-sm);
}

.md-typeset table:not([class]) th {
  background-color: var(--surface-sunk);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-normal);
  color: var(--text-primary);
}

.md-typeset table:not([class]) tr:hover {
  background-color: var(--md-accent-fg-color--transparent);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Admonitions
 *
 * Material's palette here is a set of hardcoded material-design hues that have
 * nothing to do with the brand. Each tone is remapped to the Kyvero semantic
 * colour: border, title tint, icon, and the focus ring on collapsible details.
 * ────────────────────────────────────────────────────────────────────────── */

.md-typeset :is(.admonition, details) {
  border-radius: var(--radius-md);
  border-width: 1px;
  border-left-width: 2px;
  box-shadow: none;
}

.md-typeset :is(.admonition-title, summary) {
  font-family: var(--font-mono);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.md-typeset :is(.admonition, details):is(.note, .info, .abstract, .example) {
  border-color: var(--accent-500);
}

.md-typeset :is(.note, .info, .abstract, .example) > :is(.admonition-title, summary) {
  background-color: var(--kyv-tint-accent);
}

.md-typeset :is(.note, .info, .abstract, .example) > :is(.admonition-title, summary)::before {
  background-color: var(--accent-500);
}

.md-typeset :is(.note, .info, .abstract, .example) > :is(.admonition-title, summary)::after {
  color: var(--accent-500);
}

.md-typeset :is(.admonition, details):is(.tip, .success, .question):focus-within,
.md-typeset :is(.admonition, details):is(.note, .info, .abstract, .example):focus-within {
  box-shadow: 0 0 0 3px var(--kyv-tint-accent);
}

.md-typeset :is(.admonition, details):is(.tip, .success, .question) {
  border-color: var(--success-500);
}

.md-typeset :is(.tip, .success, .question) > :is(.admonition-title, summary) {
  background-color: var(--kyv-tint-success);
}

.md-typeset :is(.tip, .success, .question) > :is(.admonition-title, summary)::before {
  background-color: var(--success-500);
}

.md-typeset :is(.tip, .success, .question) > :is(.admonition-title, summary)::after {
  color: var(--success-500);
}

.md-typeset :is(.admonition, details).warning {
  border-color: var(--warning-500);
}

.md-typeset .warning > :is(.admonition-title, summary) {
  background-color: var(--kyv-tint-warning);
}

.md-typeset .warning > :is(.admonition-title, summary)::before {
  background-color: var(--warning-500);
}

.md-typeset .warning > :is(.admonition-title, summary)::after {
  color: var(--warning-500);
}

.md-typeset :is(.admonition, details).warning:focus-within {
  box-shadow: 0 0 0 3px var(--kyv-tint-warning);
}

.md-typeset :is(.admonition, details):is(.danger, .failure, .bug) {
  border-color: var(--danger-500);
}

.md-typeset :is(.danger, .failure, .bug) > :is(.admonition-title, summary) {
  background-color: var(--kyv-tint-danger);
}

.md-typeset :is(.danger, .failure, .bug) > :is(.admonition-title, summary)::before {
  background-color: var(--danger-500);
}

.md-typeset :is(.danger, .failure, .bug) > :is(.admonition-title, summary)::after {
  color: var(--danger-500);
}

.md-typeset :is(.admonition, details):is(.danger, .failure, .bug):focus-within {
  box-shadow: 0 0 0 3px var(--kyv-tint-danger);
}

.md-typeset :is(.admonition, details).quote {
  border-color: var(--neutral-600);
}

.md-typeset .quote > :is(.admonition-title, summary) {
  background-color: var(--kyv-tint-neutral);
}

.md-typeset .quote > :is(.admonition-title, summary)::before {
  background-color: var(--neutral-600);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Buttons and footer
 * ────────────────────────────────────────────────────────────────────────── */

.md-typeset .md-button {
  border-radius: var(--radius-md);
  border-width: 1px;
  font-weight: var(--weight-medium);
  transition: var(--transition-control);
}

.md-typeset .md-button--primary {
  background-color: var(--control-primary-bg);
  border-color: var(--control-primary-bg);
  color: var(--control-primary-fg);
}

.md-typeset .md-button--primary:is(:hover, :focus) {
  background-color: var(--control-primary-bg-hover);
  border-color: var(--control-primary-bg-hover);
  color: var(--control-primary-fg);
}

.md-footer__title {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-heading);
}

.md-footer__direction {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  opacity: 1;
  color: var(--md-footer-fg-color--lighter);
}

.md-footer-meta {
  font-size: var(--text-xs);
  /* In dark mode the footer band and the page are both ink, six values apart.
     The hairline is what tells them apart; in light mode the edge is already
     obvious and the line simply reads as the top of the band. */
  border-top: 1px solid rgba(250, 249, 247, 0.10);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * Focus
 *
 * The brand's focus ring is a soft accent halo. Material's default outline is
 * left in place for anything not restated here.
 * ────────────────────────────────────────────────────────────────────────── */

.md-typeset a:focus-visible,
.md-nav__link:focus-visible,
.md-clipboard:focus-visible {
  outline: 2px solid var(--md-accent-fg-color);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
