/* =====================================
   Waveshift Documentation - Clean CSS
   Pure MkDocs Material customisation
   ===================================== */

/* Microgramma D Extended is the Waveshift wordmark typeface. We
   load the regular weight (TTF) and the bold (OTF) and apply them
   to headings only — body copy stays in Roboto for readability.
   The display font is what makes the docs feel "Waveshift" rather
   than "Material with red accents". */
@font-face {
  font-family: "Microgramma";
  src: url("fonts/Microgramma-Regular.ttf") format("truetype");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Microgramma";
  src: url("fonts/Microgramma-Bold.otf") format("opentype");
  font-weight: 700 900;
  font-style: normal;
  font-display: swap;
}

/* Apply the display font to H1 — H3 only. H4 — H6 stay in Roboto
   so deep nesting reads cleanly without screaming. Letter-spacing
   tightens slightly on display headings since Microgramma extends
   wider than Roboto at the same size. */
.md-typeset h1,
.md-typeset h2,
.md-typeset h3 {
  font-family: "Microgramma", "Roboto", -apple-system, BlinkMacSystemFont, sans-serif;
  letter-spacing: -0.005em;
}

/* Waveshift brand palette — kept available as utility tokens for explicit
   use in admonitions, charts, and highlights. The Material primary/accent
   variables below mirror the new web app: charcoal chrome with red as
   the brand accent. */
:root {
  --waveshift-red: #CC1A36;
  --waveshift-charcoal: #171717;
  --waveshift-charcoal-light: #262626;
  --waveshift-charcoal-dark: #0a0a0a;
  --waveshift-yellow: #FFD23F;
  --waveshift-green: #06FFA5;
  --waveshift-blue: #0080FF;
  --waveshift-purple: #8000FF;
}

/* Shared chrome colours — same in both themes so the docs read as one
   piece with the web app: dark header, brand-red accents on links and
   highlights. */
:root,
[data-md-color-scheme="slate"],
[data-md-color-scheme="default"] {
  --md-primary-fg-color: var(--waveshift-charcoal);
  --md-primary-fg-color--light: var(--waveshift-charcoal-light);
  --md-primary-fg-color--dark: var(--waveshift-charcoal-dark);
  --md-accent-fg-color: var(--waveshift-red);
  --md-accent-fg-color--transparent: rgba(204, 26, 54, 0.1);

  /* Code highlighting — the brand red appears for keywords/operators,
     leaving function/variable names readable against either theme. */
  --md-code-hl-color: rgba(204, 26, 54, 0.15);
  --md-code-hl-number-color: var(--waveshift-yellow);
  --md-code-hl-special-color: var(--waveshift-green);
  --md-code-hl-function-color: var(--waveshift-blue);
  --md-code-hl-constant-color: var(--waveshift-purple);
  --md-code-hl-keyword-color: var(--waveshift-red);
  --md-code-hl-string-color: var(--waveshift-yellow);
  --md-code-hl-name-color: var(--waveshift-blue);
  --md-code-hl-operator-color: var(--waveshift-red);
  --md-code-hl-punctuation-color: rgba(120, 120, 120, 0.9);
  --md-code-hl-comment-color: rgba(120, 120, 120, 0.65);
  --md-code-hl-generic-color: rgba(120, 120, 120, 0.7);
  --md-code-hl-variable-color: var(--waveshift-blue);
}

/* Dark Theme (Slate) - Background and Text Colors Only */
[data-md-color-scheme="slate"] {
  /* True black background */
  --md-default-bg-color: #000000;
  --md-default-fg-color: #ffffff;
  --md-default-fg-color--light: rgba(255, 255, 255, 0.7);
  --md-default-fg-color--lighter: rgba(255, 255, 255, 0.4);
  --md-default-fg-color--lightest: rgba(255, 255, 255, 0.2);

  /* Code blocks - Dark background */
  --md-code-bg-color: #1a1a1a;

  /* Header text on primary chrome. Note: in mkdocs-material,
     `--md-primary-bg-color` is the *foreground* colour for text/icons
     painted on top of the primary header — the naming is misleading.
     The header is charcoal in both schemes, so this stays white in
     slate too (otherwise it'd be black-on-charcoal and unreadable). */
  --md-primary-bg-color: #ffffff;
  --md-primary-bg-color--light: rgba(255, 255, 255, 0.7);

  /* Cards and surfaces */
  --md-default-bg-color--light: #0d1117;
  --md-default-bg-color--lighter: #161b22;
  --md-default-bg-color--lightest: #21262d;
}

/* Light Theme (Default) - Background and Text Colors Only */
[data-md-color-scheme="default"] {
  /* Light backgrounds */
  --md-default-bg-color: #ffffff;
  --md-default-fg-color: #000000;
  --md-default-fg-color--light: rgba(0, 0, 0, 0.7);
  --md-default-fg-color--lighter: rgba(0, 0, 0, 0.4);
  --md-default-fg-color--lightest: rgba(0, 0, 0, 0.2);

  /* Code blocks - Light background */
  --md-code-bg-color: #f5f5f5;

  /* Header text on primary chrome — see slate block above for why
     this is the foreground colour despite the variable name. */
  --md-primary-bg-color: #ffffff;
  --md-primary-bg-color--light: rgba(255, 255, 255, 0.7);

  /* Cards and surfaces */
  --md-default-bg-color--light: #f5f5f5;
  --md-default-bg-color--lighter: #eeeeee;
  --md-default-bg-color--lightest: #e0e0e0;
}

/* Admonition styling — semantic colours for each kind. Brand red stays
   reserved for danger so it keeps its impact when it shows up. */
.md-typeset .admonition.note {
  border-color: var(--waveshift-blue);
}

.md-typeset .admonition.warning {
  border-color: var(--waveshift-yellow);
}

.md-typeset .admonition.danger {
  border-color: var(--waveshift-red);
}

.md-typeset .admonition.success {
  border-color: var(--waveshift-green);
}

.md-typeset .admonition.info {
  border-color: var(--waveshift-blue);
}

/* Code blocks - Force dark appearance in both themes */
.md-typeset code,
.md-typeset pre {
  background-color: var(--md-code-bg-color);
  color: var(--md-code-fg-color);
}

.md-typeset pre > code {
  background-color: transparent;
}

/* Inline code styling */
.md-typeset :not(pre) > code {
  background-color: var(--md-code-bg-color);
  color: var(--md-code-fg-color);
  padding: 0.1em 0.4em;
  border-radius: 0.2em;
  font-size: 0.85em;
}

/* Ensure code block container is dark */
.md-typeset .highlight {
  background-color: var(--md-code-bg-color);
}

/* Tables in light mode - maintain good contrast */
[data-md-color-scheme="default"] .md-typeset table:not([class]) {
  border: 1px solid rgba(0, 0, 0, 0.12);
}

[data-md-color-scheme="default"] .md-typeset table:not([class]) th {
  background-color: rgba(0, 0, 0, 0.05);
  color: rgba(0, 0, 0, 0.87);
}

/* Print styles */
@media print {
  .md-header,
  .md-tabs,
  .md-sidebar,
  .md-footer,
  button {
    display: none !important;
  }

  .md-main__inner {
    margin: 0;
  }

  .md-content {
    max-width: 100%;
  }

  h2 {
    page-break-after: avoid;
  }

  .admonition {
    page-break-inside: avoid;
  }

  .md-typeset code,
  .md-typeset pre {
    background-color: #f5f5f5 !important;
    color: #000000 !important;
    border: 1px solid #ddd;
  }

  a[href]:after {
    content: none;
  }
}

/* Responsive adjustments */
@media (max-width: 768px) {
  .md-typeset h1 {
    font-size: 2rem;
  }
}

/* The header is charcoal in both schemes (mirrors the web app), so the
   white logo always reads correctly. No scheme-driven swapping. */
.md-header__button.md-logo img {
  content: url('../images/branding/Logo/SVG - for web/Waveshift Logo Inline - White.svg');
}

/* Wave-glyph section divider — the Waveshift logomark in red
   over a faded gradient line. Applied two ways:

   1. To explicit `<hr>` elements written as `---` in markdown.
   2. Auto-injected as a `::before` pseudo-element on every
      top-level `<h2>` except the first on the page, so every
      page gets a brand mark between major sections without
      authors having to write `---` everywhere.

   Scoped to direct children of the article body, so dividers
   inside grid-cards, FAQ collapsibles, and admonitions fall back
   to the plain default. */
.md-content__inner.md-typeset > hr,
.md-content__inner.md-typeset > h2:not(:first-of-type)::before {
  content: "";
  display: block;
  border: none;
  height: 28px;
  margin: 2.75rem 0 1.5rem;
  background-image:
    url("../images/branding/Logo/SVG - for web/Waveshift logomark - Red.svg"),
    linear-gradient(to right, transparent, var(--md-default-fg-color--lightest) 12%, var(--md-default-fg-color--lightest) 88%, transparent);
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
  background-size: 28px 28px, 100% 1px;
  opacity: 0.7;
}
.md-content__inner.md-typeset > hr {
  margin: 2.5rem 0;
}
[data-md-color-scheme="slate"] .md-content__inner.md-typeset > hr,
[data-md-color-scheme="slate"] .md-content__inner.md-typeset > h2:not(:first-of-type)::before {
  opacity: 0.55;
}
/* If an explicit `---` divider already sits immediately before
   an h2, suppress the auto-injected one so we don't double up.
   The `:not(:first-of-type)` is included to match the inject
   rule's specificity (otherwise the inject rule wins the
   cascade). */
.md-content__inner.md-typeset > hr + h2:not(:first-of-type)::before {
  display: none;
}

/* Home-page hero banner — full-width charcoal-to-red gradient
   with the Waveshift roundel and Microgramma title. Replaces the
   default H1 + tagline pair so the page opens with a brand
   moment instead of a docs-template heading. */
.hero-banner {
  background:
    radial-gradient(circle at 85% 20%, rgba(204, 26, 54, 0.55) 0%, transparent 55%),
    linear-gradient(135deg, var(--waveshift-charcoal-dark) 0%, var(--waveshift-charcoal) 50%, var(--waveshift-charcoal-light) 100%);
  border-radius: 0.6rem;
  padding: 3rem 2rem 3.25rem;
  margin: 0.25rem 0 1.75rem;
  text-align: center;
  color: rgba(255, 255, 255, 0.95);
  position: relative;
  overflow: hidden;
  border: 1px solid var(--waveshift-charcoal-light);
}
.hero-banner__logo {
  display: block;
  margin: 0 auto 1.25rem;
  height: 56px;
  width: auto;
  max-width: 90%;
}
.hero-banner__tagline {
  font-size: 0.85rem;
  line-height: 1.55;
  max-width: 36rem;
  margin: 0 auto;
  color: rgba(255, 255, 255, 0.78);
}
@media (max-width: 50em) {
  .hero-banner {
    padding: 2.25rem 1.25rem 2.5rem;
  }
  .hero-banner__logo {
    height: 40px;
  }
  .hero-banner__tagline {
    font-size: 0.8rem;
  }
}

/* Splash hero — first viewport shows only the logo + 4
   thumbnail tiles, centred. Header + tabs fade in as the user
   scrolls past. The hero itself fades out at the same time so
   the transition feels like a curtain lift, not a sudden cut.
   --hero-progress is set 0..1 by docs/javascripts/hero-splash.js. */
.hero-splash {
  /* Take the visible first viewport (minus the chrome the
     transparent header still reserves above it) so the logo +
     thumbnails sit vertically centred on load. The bottom
     margin gives a scroll-room beat for the cross-fade before
     the next section arrives. */
  min-height: calc(100vh - 7.2rem);
  min-height: calc(100dvh - 7.2rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  margin-bottom: 30vh;
  opacity: calc(1 - var(--hero-progress, 0));
  transition: opacity 0.05s linear;
}
.hero-splash > .hero-banner,
.hero-splash > .hero-row {
  width: 100%;
  max-width: 76rem;
}
.hero-splash__hint {
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.5);
  margin: 0.75rem 0 0;
  animation: hero-hint-bob 2.6s ease-in-out infinite;
}
@keyframes hero-hint-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(4px); }
}

/* Register --hero-progress as a real <number> so it can be used
   inside calc() in colour expressions below. Without the
   @property registration, the variable is treated as an opaque
   string and the calc falls back to invalid — which reverts the
   `background-color` rule to the cascade's previous value
   (Material's solid `var(--md-primary-fg-color)`), and the
   tabs end up looking solid charcoal instead of translucent. */
@property --hero-progress {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

/* Header + tabs stay visible from page-load, but with a
   translucent / blurred background so the hero content reads
   through them as the user scrolls. As scroll progresses, the
   alpha ticks up via --hero-progress so they end up looking
   close to the rest of the docs once the splash is gone. */
body:has(.hero-splash) .md-header {
  background-color: rgba(15, 15, 18, calc(0.35 + 0.55 * var(--hero-progress)));
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
body:has(.hero-splash) .md-tabs {
  /* Match the header's alpha curve exactly so the two bands
     read as one continuous translucent strip. */
  background-color: rgba(15, 15, 18, calc(0.35 + 0.55 * var(--hero-progress))) !important;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.06);
}

/* Home-page-only chrome: force dark mode regardless of the user's
   chosen scheme (the dark hero + light card backgrounds clash if
   the rest of the page renders in light mode), and hide the
   colour-mode toggle since flipping it does nothing useful here.
   Scoped to `body:has(.hero-banner)` so the rest of the docs
   keep their normal scheme. */
body:has(.hero-banner) {
  /* Mirror the slate-scheme defaults from this file so colours,
     code blocks, surfaces all render dark on the home page. */
  --md-default-bg-color: #000000;
  --md-default-fg-color: #ffffff;
  --md-default-fg-color--light: rgba(255, 255, 255, 0.7);
  --md-default-fg-color--lighter: rgba(255, 255, 255, 0.4);
  --md-default-fg-color--lightest: rgba(255, 255, 255, 0.2);
  --md-code-bg-color: #1a1a1a;
  --md-default-bg-color--light: #0d1117;
  --md-default-bg-color--lighter: #161b22;
  --md-default-bg-color--lightest: #21262d;

  background-color: var(--md-default-bg-color);
  color: var(--md-default-fg-color);
}
body:has(.hero-banner) .md-header__option[data-md-component="palette"] {
  display: none;
}
/* With the left sidebar hidden the article column is much wider
   than usual; constrain the home-page card grid so it sits
   centred and the four cards don't get stretched edge-to-edge. */
body:has(.hero-banner) .md-typeset .grid.cards {
  max-width: 64rem;
  margin-left: auto;
  margin-right: auto;
}

/* Screen-reader only / visually-hidden — the home page uses this
   on its `# Waveshift` H1 so Material doesn't fall back to
   rendering the nav label "Home" as the page heading. */
.visually-hidden,
.md-typeset h1.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

/* Home-page hero strip — four linked thumbnails of the most
   distinctive Web UI pages. Each card is aspect-ratio-cropped via
   object-fit so a tall full-page screenshot still reads as a
   preview without distorting. Light/dark image swap relies on
   Material's `#only-light` / `#only-dark` URL-fragment hiding. */
.hero-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.6rem;
  margin: 1.25rem 0 1.5rem;
}
.hero-row a {
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: 0.4rem;
  border: 1px solid var(--md-default-fg-color--lightest);
  background: var(--md-default-bg-color);
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
  text-decoration: none;
}
.hero-row a:hover,
.hero-row a:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
  border-color: var(--md-accent-fg-color);
}
.hero-row img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  display: block;
}
.hero-row span {
  position: absolute;
  inset: auto 0 0 0;
  padding: 0.4rem 0.6rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: #fff;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
  letter-spacing: 0.02em;
}
@media (max-width: 50em) {
  .hero-row {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* Apply the same lift / shadow / accent-border hover used on the
   home-page hero strip to Material's grid-cards blocks (used in
   the home page "Where to start" section). */
.md-typeset .grid.cards > ol > li,
.md-typeset .grid.cards > ul > li {
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.md-typeset .grid.cards > ol > li:hover,
.md-typeset .grid.cards > ul > li:hover,
.md-typeset .grid.cards > ol > li:focus-within,
.md-typeset .grid.cards > ul > li:focus-within {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
  border-color: var(--md-accent-fg-color);
}

/* Brand & press page — visual previews of each logo variant.
   .brand-grid lays the figures out in a responsive flex wrap;
   .brand-preview is a neutral panel; .brand-preview--dark inverts to
   a charcoal background so white/two-colour-on-dark variants are
   readable without switching the page theme. */
.brand-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin: 1rem 0 1.25rem;
}
.brand-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--md-default-fg-color--lightest);
  border-radius: 0.4rem;
  background: var(--md-default-bg-color);
  margin: 0;
  min-width: 12rem;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.brand-preview:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
  border-color: var(--md-accent-fg-color);
}
.brand-preview--dark {
  background: var(--waveshift-charcoal);
  border-color: var(--waveshift-charcoal-light);
}
.brand-preview img {
  display: block;
  max-width: 100%;
  height: auto;
}
.brand-preview figcaption {
  margin-top: 0.75rem;
  font-size: 0.78rem;
  color: var(--md-default-fg-color--light);
}
.brand-preview--dark figcaption {
  color: rgba(255, 255, 255, 0.78);
}

/* Footer "Made by Blackfire" link. Material's footer is dark in both
   schemes, so the white-text + orange-mark variant of the logo works
   everywhere without scheme switching. */
.footer-blackfire-logo {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  margin: 0 0.25em;
}
.footer-blackfire-logo img {
  height: 1.1rem;
  width: auto;
  display: block;
}

/* `<abbr>` tooltips for jargon terms (Egress Server, WireGuard,
   etc.) are defined globally via pymdownx.snippets, so every
   occurrence on every page becomes an `<abbr>`. Material's default
   styling is a dotted underline on every match, which reads as
   visual noise once a term appears 20 times on a page.
   Hide the underline by default; the `cursor: help` and the
   tooltip still fire on hover, so discovery works without the
   page looking flagged. */
.md-typeset abbr {
  text-decoration: none;
  border-bottom: none;
}
.md-typeset abbr:hover {
  text-decoration: underline dotted;
  text-decoration-color: var(--md-default-fg-color--lighter);
  text-underline-offset: 0.2em;
}

/* The custom 404 page (docs/404.md) gets its own hero: oversized
   "404" in brand red + a friendly tagline. Pure CSS so we don't
   pollute the markdown with HTML. */
body[data-md-color-scheme] [data-md-component="content"] .md-content__inner > h1:first-of-type:has(+ p) {
  /* fallback styling — overridden by the `.error-hero` class */
}
.error-hero {
  text-align: center;
  padding: 1.5rem 0 2rem;
  border-bottom: 1px solid var(--md-default-fg-color--lightest);
  margin-bottom: 1.75rem;
}
.error-hero__code {
  font-size: 8rem;
  font-weight: 800;
  line-height: 1;
  color: var(--md-accent-fg-color);
  letter-spacing: -0.04em;
  margin: 0;
}
.error-hero__tagline {
  font-size: 1.1rem;
  color: var(--md-default-fg-color--light);
  margin: 0.5rem 0 0;
}
@media (max-width: 50em) {
  .error-hero__code {
    font-size: 5rem;
  }
}

/* Pygments aggressively colours tokens that don't carry useful
   information in shell snippets — IP digits, operators, built-in
   commands. The result is that `mkdir foo && cd foo` renders with
   half its tokens in different colours, which reads as noise. We
   inherit the default text colour for:
   - numbers (.m and friends) — kills the "8.8.8.8 has one yellow
     digit then a plain dot" effect on IPs / CIDRs / ports
   - operators (.o) — `&&`, `||`, `|`, `>`, `<`, `;`
   - built-in commands (.nb) — `cd`, `ls`, `mkdir`, `cp`, etc.
   Comments, strings, variables, and keywords keep their colour. */
.md-typeset .highlight .m,
.md-typeset .highlight .mb,
.md-typeset .highlight .mf,
.md-typeset .highlight .mh,
.md-typeset .highlight .mi,
.md-typeset .highlight .mo,
.md-typeset .highlight .il,
.md-typeset .highlight .o,
.md-typeset .highlight .nb {
  color: inherit;
}

/* Material's scrollspy that highlights the active heading in the
   integrated TOC only fires when a heading scrolls past a threshold
   near the top of the viewport. Headings at the very bottom of a
   page can never reach that threshold because there's no content
   below them to push the page further. Adding padding to the
   article bottom gives those last sections somewhere to scroll
   *to*, so the highlight tracks them correctly. */
.md-content__inner {
  padding-bottom: 60vh;
}
/* The home page has no integrated TOC, so the 60vh trailing
   padding above just adds an empty stretch beneath the last
   section. Drop it back to normal there. */
body:has(.hero-splash) .md-content__inner {
  padding-bottom: 2rem;
}
