/* filepath: /Users/andy/Devel/mkdocs_webpage/overrides/stylesheets/extra.css */
@font-face {
  font-family: "JetBrainsMono Nerd Font";
  src: "https://github.com/ryanoasis/nerd-fonts/releases/download/v2.1.0/JetBrainsMono.zip";
}

[data-md-color-scheme="default"] {
  --md-hue: 210;
  --md-primary-fg-color: #3b332c;
  --md-default-bg-color: #eee3c7;
  /* --md-accent-fg-color: #FF0000; */
}

[data-md-color-scheme="slate"] {
  --md-hue: 210;
  --md-primary-fg-color: #231e1a;
  --md-default-bg-color: #002b36;
  /* --md-accent-fg-color: #FF0000; */
}

/* Slate theme */
[data-md-color-scheme="slate"] .md-tabs {
  background-color: #231e1a;
}

/* Slate theme active nav link */
[data-md-color-scheme="slate"] .md-nav__item .md-nav__link--active {
  color: #b519af;
}

[data-md-color-scheme="slate"] .md-header {
  background-color: #231e1a;

}
/* Light theme active nav link */
[data-md-color-scheme="default"] .md-nav__item .md-nav__link--active {
  color: #c462c1;
}

:root > * {
  --md-code-font: "JetBrainsMono Nerd Font";
  --md-code-hl-variable-color: #c88174;
}

.md-typeset table:not([class]) th:not([align]) {
  text-align: left;
}
.md-typeset table:not([class]) th {
  min-width: 10rem;
  padding: 1.2rem 1.6rem;
  background-color: rgba(0, 0, 0, 1);
  color: #fff;
  vertical-align: top;
}

.md-typeset a {
  color: var(--md-accent-fg-color);
}
article a:hover {
  text-decoration: underline;
}

/* Logo image sizing */
.md-header-nav__button.md-logo {
  margin: 0;
  padding: 0;
}
.md-header-nav__button.md-logo img,
.md-nav__button img {
  height: 50px;
  width: 50px;
}

/* Widen content area for tables/code blocks */
.md-grid {
  max-width: 90rem;
}

/* Smaller font for admonitions and details */
.md-typeset .admonition,
.md-typeset details {
  font-size: 0.7rem;
}

/* Custom button style */
.md-button {
  font-family: "JetBrainsMono Nerd Font", sans-serif;
  padding: 0.8em 1.2em;
  border: 2px solid var(--md-default-bg-color);
  border-radius: 4px;
  cursor: pointer;
  display: inline-block;
  position: relative;
  overflow: hidden;
  background-color: var(--md-default-bg-color);
  color: var(--md-text-color-on-background);
  transition: background 0.3s ease;
}



/* Code block "copy to clipboard" button styles */
.md-clipboard {
  /* Position is handled by default theme (top-right of code block) */
  padding: 0.4rem;
  border: 2px solid var(--md-default-bg-color);
  border-radius: 4px;
  background-color: var(--md-default-bg-color);
  color: var(--md-text-color-on-background);
  cursor: pointer;
  transition: background 0.3s ease, color 0.3s ease;
}
.md-clipboard:hover {
  color: var(--md-accent-fg-color);
  background: linear-gradient(var(--button-gradient-start), var(--button-gradient-end));
}

/* ================================================
 *  CRT typewriter animation for H1 / H2 headers
 * ================================================ */

/* Bold blinking underscore cursor.
 * The animation is shared by every cursor on the page and starts at the same
 * time (DOMContentLoaded), so all cursors blink in unison.
 */
.crt-cursor {
  display: inline-block;
  margin-left: 0.05em;
  font-weight: 700;
  animation: crt-blink 950ms steps(2, start) infinite;
  transition: opacity 1.5s ease;
}

.crt-cursor.crt-fade {
  animation: none;
  opacity: 0;
}

@keyframes crt-blink {
  0%, 49% {
    opacity: 1;
  }
  50%, 100% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .crt-cursor {
    display: none;
    animation: none;
  }
}

/* ================================================
 *  CRT static noise overlay for the site top bar
 * ================================================
 *
 * A <canvas class="crt-noise"> is injected as the first child of each noise
 * host -- currently `.md-header` and `.md-tabs` -- by
 * `javascripts/header-crt-noise.js`. Both canvases share one rAF loop and one
 * noise buffer, so the grain reads as one continuous CRT plane across the
 * header and the navigation tabs strip. These rules:
 *   - establish each host as a positioning context for its canvas,
 *   - lift each host's interactive content above the canvas,
 *   - expose tunable knobs as CSS custom properties so the look can be tweaked
 *     per color scheme (and live in DevTools).
 *
 * Tunable variables (defaults below; override per scheme as needed):
 *   --crt-noise-opacity      Overall visibility of the grain.
 *                            Per-scheme defaults: default=0.122, slate=0.2684.
 *                            Recommended range: 0.05 .. 0.35.
 *   --crt-noise-blend-mode   How the grain composites onto the host bg.
 *                            Try `overlay`, `soft-light`, `screen`, `multiply`.
 *   --crt-noise-z-index      Stacking position of the canvas inside the host.
 *                            Keep < 1 so .md-header__inner / .md-tabs__list
 *                            (which use z-index: 1) stay above the noise.
 *   --crt-noise-fps          Repaint rate of the grain, in frames per second.
 *                            Read once at script init. Recommended: 12 .. 60.
 *                            12  -> very low CPU, 24 -> soft CRT (default),
 *                            60  -> sharper TV-static, higher CPU.
 *   --crt-noise-blur         Blur applied when upscaling the noise buffer.
 *                            Read once at script init. Recommended: 0.5 .. 2.5px.
 *                            Lower -> sharper grain, higher -> softer plasma.
 *   --crt-noise-fade-duration
 *                            Total length of the one-shot intro animation
 *                            on page load. The grain rises from 0 to its
 *                            peak (--crt-noise-opacity) at the midpoint and
 *                            falls back to 0 along a Gaussian bell curve.
 *                            Consumed by the `crt-noise-bell` @keyframes
 *                            animation on `.crt-noise`; header-crt-noise.js
 *                            tears each canvas down on `animationend`.
 *                            Recommended: 4000ms .. 12000ms.
 *   --crt-noise-fade-easing  Easing curve applied between the keyframe
 *                            stops of `crt-noise-bell`. Keep `linear`
 *                            (default) to preserve the shape of the bell;
 *                            non-linear easings warp every segment and
 *                            break the symmetry.
 *
 * Runtime-set by header-crt-noise.js (do not author):
 *   --crt-noise-reserve-left, --crt-noise-reserve-right
 *      Inline on the .crt-noise canvas; feed its clip-path so the search
 *      widget, search toggle, etc. stay free of grain.
 */
:root {
  --crt-noise-opacity: 0.15;
  --crt-noise-blend-mode: overlay;
  --crt-noise-z-index: 0;
  --crt-noise-fps: 24;
  --crt-noise-blur: 1.2px;
  --crt-noise-fade-duration: 11000ms;
  --crt-noise-fade-easing: linear;
}

/* Per-scheme intensity. Light theme needs less to avoid muddying the cream
 * background; the dark theme can carry more grain without losing legibility. */
[data-md-color-scheme="default"] {
  --crt-noise-opacity: 0.122;
}

[data-md-color-scheme="slate"] {
  --crt-noise-opacity: 0.2684;
}

/* Make each noise host a positioning context for its canvas. We deliberately
 * do NOT set `overflow: hidden` here because the search results dropdown
 * (`.md-search__output`) is positioned absolutely below the header and must
 * remain visible. The canvas itself is sized to its host via `inset: 0`,
 * so it cannot visually overflow on its own. */
.md-header,
.md-tabs {
  position: relative;
}

/* Keep each host's interactive content above the noise layer. */
.md-header__inner,
.md-tabs__list {
  position: relative;
  z-index: 1;
}

.crt-noise {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: var(--crt-noise-z-index);
  mix-blend-mode: var(--crt-noise-blend-mode);
  /* One-shot intro bell: opacity rises from 0 to --crt-noise-opacity at the
   * midpoint and falls back to 0, along a Gaussian curve sampled in the
   * @keyframes rule below. `both` keeps the 0% stop applied before the
   * animation starts (no t=0 flash) and the 100% stop applied after it
   * ends, until header-crt-noise.js removes the canvas on `animationend`. */
  animation: crt-noise-bell var(--crt-noise-fade-duration) var(--crt-noise-fade-easing) both;
  /* Carve out a reserved band on the right so the search button, the search
   * input/dialog, and the dropdown results panel are not grainy. The reserve
   * width is measured at runtime by header-crt-noise.js and applied as an
   * inline style on this element; the variables here are safe fallbacks. */
  clip-path: inset(
    0
    var(--crt-noise-reserve-right, 0px)
    0
    var(--crt-noise-reserve-left, 0px)
  );
}

/* Gaussian bell sampled at 11 stops (sigma = 0.18, mu = 0.5, normalised so
 * the endpoints sit at exactly 0 and the peak at exactly 1). Each stop
 * scales `--crt-noise-opacity` so per-scheme intensity overrides still
 * drive the peak height. With `animation-timing-function: linear`
 * (the recommended `--crt-noise-fade-easing` default) the segments
 * between stops are straight lines, which approximate the smooth bell
 * closely without warping it. */
@keyframes crt-noise-bell {
  0%   { opacity: 0; }
  10%  { opacity: calc(var(--crt-noise-opacity) * 0.064); }
  20%  { opacity: calc(var(--crt-noise-opacity) * 0.233); }
  30%  { opacity: calc(var(--crt-noise-opacity) * 0.530); }
  40%  { opacity: calc(var(--crt-noise-opacity) * 0.854); }
  50%  { opacity: var(--crt-noise-opacity); }
  60%  { opacity: calc(var(--crt-noise-opacity) * 0.854); }
  70%  { opacity: calc(var(--crt-noise-opacity) * 0.530); }
  80%  { opacity: calc(var(--crt-noise-opacity) * 0.233); }
  90%  { opacity: calc(var(--crt-noise-opacity) * 0.064); }
  100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .crt-noise {
    display: none;
  }
}
