/* =============================================================================
   guyhui-showcase — design tokens & components
   Source of truth: DESIGN.md (repository root). Keep the two in sync.

   Principles:
   - Self-hosted fonts only (no Google Fonts CDN — GDPR).
   - Neutral base = slate; a single custom indigo accent.
   - Green / red are RESERVED for pass/fail proof semantics — never decorative.
   - JetBrains Mono carries the textual proof artifacts: versions, JSON, tags.
     Verdict marks (✓ / ✗) are carried by colour, not by the display face — see
     the `.gh-pass` / `.gh-fail` rules below.
   ========================================================================== */

/* --- Self-hosted fonts (woff2, latin subset) ------------------------------ */

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-latin-600-normal.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-latin-700-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter-latin-600-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/inter-latin-700-normal.woff2") format("woff2");
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-latin-700-normal.woff2") format("woff2");
}

/* --- Font wiring ----------------------------------------------------------- */

:root {
  --md-text-font: "Inter";
  --md-code-font: "JetBrains Mono";

  /* Custom design tokens (site-local, not Material's) */
  --gh-font-display: "IBM Plex Sans", "Inter", system-ui, sans-serif;

  /* Slate scale */
  --gh-slate-50:  #f8fafc;
  --gh-slate-100: #f1f5f9;
  --gh-slate-200: #e2e8f0;
  --gh-slate-300: #cbd5e1;
  --gh-slate-400: #94a3b8;
  --gh-slate-500: #64748b;
  --gh-slate-600: #475569;
  --gh-slate-700: #334155;
  --gh-slate-800: #1e293b;
  --gh-slate-900: #0f172a;
  --gh-slate-950: #020617;

  /* Accent — single custom indigo */
  --gh-indigo:       #4f46e5;
  --gh-indigo-light: #6366f1;
  --gh-indigo-dark:  #4338ca;

  /* Proof semantics — RESERVED. Three verdicts, three colours: green = pass,
     red = fail, amber = returned-for-rework (a counter-review gate sent a
     deliverable back — neither a pass nor a hard failure). Never repurpose
     these hues for decoration.
     Light-scheme pass is green-700, not green-600: on the `.gh-proof` surface
     (--gh-slate-50) green-600 lands at 3.15:1, below the AA 4.5:1 text target.
     Returned amber mirrors that discipline: amber-700 = 4.8:1 on --gh-slate-50,
     amber-400 = 8.76:1 on --gh-slate-800 (dark). */
  --gh-pass: #15803d;
  --gh-fail: #dc2626;
  --gh-returned: #b45309;
  --gh-pass-light: #4ade80;
  --gh-fail-light: #f87171;
  --gh-returned-light: #fbbf24;
}

/* Headings use the display face; body stays on Inter. */
.md-typeset h1,
.md-typeset h2,
.md-typeset h3,
.md-typeset h4,
.md-header__title,
.md-nav__title {
  font-family: var(--gh-font-display);
  font-weight: 700;
  letter-spacing: -0.015em;
}

/* Mobile header title — swipe to reveal the full site name.
   "Guy HUI-BON-HOA — Agentic Stack" is wider than the narrow header (~221px at
   401px, less below), and shrinking the font enough to fit a 320px screen would make
   it illegible. Instead, let the title scroll horizontally on touch so the tail
   ("— Agentic Stack") is reachable by swipe at any width; the scrollbar is hidden. Applies
   only in the mobile header layout; where the title already fits, nothing scrolls. */
@media screen and (max-width: 76.1875em) {
  .md-header__title .md-ellipsis {
    overflow: auto hidden;
    text-overflow: clip;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .md-header__title .md-ellipsis::-webkit-scrollbar {
    display: none;
  }
}

/* Wide data tables (Proven runs, The ten workflows) — freeze the first column
   so the row anchor (WF-xxx / ID) stays visible while the rest of the row
   scrolls on narrow screens. In Material the table itself is the scroll
   container; the first cell is made sticky against it. Scoped to a wrapper so
   other tables are untouched, and to the mobile layout so the desktop
   appearance and row-hover are unchanged. The opaque background keeps scrolled
   cells from showing through; the hairline shadow marks the frozen edge. */
@media screen and (max-width: 76.1875em) {
  /* Material gives the <table> its own `overflow: auto`, which would capture the
     sticky context before the real scroller (.md-typeset__scrollwrap). Neutralise
     it inside the wrapper so the first cell sticks against the scrollwrap. */
  .gh-sticky-col table:not([class]) {
    overflow: visible;
  }
  .gh-sticky-col table:not([class]) th:first-child,
  .gh-sticky-col table:not([class]) td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background-color: var(--md-default-bg-color);
    box-shadow: 1px 0 0 var(--md-typeset-table-color);
  }
}

/* Under Projects, the standalone case study carries the same weight as the
   RAWLY entry above it, so the two projects read as siblings. Material only
   bolds real nav sections (.md-nav__item--section > .md-nav__link), and a
   single-page project has no children to make it one. */
.md-nav__link[href$="b2b_ecommerce_case_study/"] {
  font-weight: 700;
}

/* --- Colour scheme: light (default) --------------------------------------- */

[data-md-color-scheme="default"] {
  --md-primary-fg-color:        var(--gh-slate-900);
  --md-primary-fg-color--light: var(--gh-slate-700);
  --md-primary-fg-color--dark:  var(--gh-slate-950);
  --md-primary-bg-color:        #ffffff;
  --md-primary-bg-color--light: rgba(255, 255, 255, 0.7);

  --md-accent-fg-color:         var(--gh-indigo);
  --md-accent-fg-color--transparent: rgba(79, 70, 229, 0.1);

  --md-typeset-a-color:         var(--gh-indigo);

  --md-default-bg-color:        #ffffff;
  --md-default-fg-color:        var(--gh-slate-800);
  --md-default-fg-color--light: var(--gh-slate-600);
  --md-default-fg-color--lighter: var(--gh-slate-400);

  --md-code-bg-color:           var(--gh-slate-100);
  --md-code-fg-color:           var(--gh-slate-800);
}

/* --- Colour scheme: dark (slate) ------------------------------------------ */

[data-md-color-scheme="slate"] {
  --md-hue: 222;

  --md-primary-fg-color:        var(--gh-slate-950);
  --md-primary-fg-color--light: var(--gh-slate-800);
  --md-primary-fg-color--dark:  #000000;
  --md-primary-bg-color:        var(--gh-slate-100);

  --md-accent-fg-color:         var(--gh-indigo-light);

  --md-typeset-a-color:         #a5b4fc;

  --md-default-bg-color:        var(--gh-slate-900);
  --md-default-fg-color:        var(--gh-slate-200);
  --md-default-fg-color--light: var(--gh-slate-400);
  --md-default-fg-color--lighter: var(--gh-slate-500);

  --md-code-bg-color:           var(--gh-slate-800);
  --md-code-fg-color:           var(--gh-slate-200);
}

/* =============================================================================
   Hero
   ========================================================================== */

.gh-hero {
  padding: 0.5rem 0 0.25rem;
}

.gh-hero .md-typeset h1,
.md-typeset .gh-hero h1 {
  font-size: 2rem;
  line-height: 1.1;
  margin: 0 0 0.6rem;
  color: var(--md-default-fg-color);
}

.gh-hero p {
  font-size: 0.95rem;
  color: var(--md-default-fg-color--light);
  max-width: 42rem;
  margin: 0 0 1.4rem;
}

.gh-hero .md-button {
  margin: 0 0.5rem 0.5rem 0;
}

/* Dark mode: invert the primary button (light fill, dark text) so the CTA
   stays high-contrast — the header keeps its own dark --md-primary-fg-color. */
[data-md-color-scheme="slate"] .md-typeset .md-button--primary {
  background-color: var(--gh-slate-100);
  border-color: var(--gh-slate-100);
  color: var(--gh-slate-900);
}
[data-md-color-scheme="slate"] .md-typeset .md-button--primary:hover,
[data-md-color-scheme="slate"] .md-typeset .md-button--primary:focus {
  background-color: #ffffff;
  border-color: #ffffff;
  color: var(--gh-slate-950);
}

/* Secondary hero button (Try it → ) — a deliberate outlined companion to the
   filled primary, pinned identically in both themes and across resting / hover /
   focus states. Material's default .md-button renders differently per scheme
   (and picks up a filled look on :focus), which made the pair read inconsistently
   light vs dark; this fixes the pair to primary-filled + secondary-outlined.
   The film block's "Watch" button (.gh-film) takes the same outline: left to
   Material's default it renders near-black on the dark scheme. */
.gh-hero .md-button:not(.md-button--primary),
.gh-hero .md-button:not(.md-button--primary):focus,
.gh-film .md-button,
.gh-film .md-button:focus {
  background-color: transparent;
  border-color: var(--md-default-fg-color--lighter);
  color: var(--md-default-fg-color);
}
.gh-hero .md-button:not(.md-button--primary):hover,
.gh-film .md-button:hover {
  background-color: var(--md-accent-fg-color);
  border-color: var(--md-accent-fg-color);
  color: #ffffff;
}

/* Secondary action — quiet link, not a competing button. */
.gh-hero .gh-link {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.35rem 0;
  font-weight: 600;
  color: var(--md-default-fg-color--light);
}
.gh-hero .gh-link:hover {
  color: var(--md-accent-fg-color);
}

@media screen and (min-width: 45rem) {
  /* Align the hero title's cap-height with the side rails (Home nav + TOC):
     Material's residual content top spacing (.6rem padding + .4rem :before)
     lands the caps at ~1.25rem, level with the rail labels at ~1.35rem. */
  .gh-hero {
    padding: 0 0 0.25rem;
  }
  .gh-hero .md-typeset h1,
  .md-typeset .gh-hero h1 {
    font-size: 2.75rem;
  }
  .gh-hero p {
    font-size: 1.05rem;
  }
}

/* Film block under the Home hero (.gh-film): the WF-008 motion loop beside a
   short caption. The video is dark in both themes — its ground is exactly
   --gh-slate-900 — so it is framed as a screen rather than re-coloured: on the
   light scheme the dark card stands out on its own; on the dark scheme its
   ground equals the page, so a 1 px slate-700 ring draws the edge. The ring is
   a box-shadow, not a border, so it adds no layout width. The clip is portrait
   4:5: stacked and capped at 20rem on mobile so it never fills the screen,
   beside the caption from 45rem. Playback logic: javascripts/hero_video.js. */
.gh-film {
  display: grid;
  gap: 1rem;
  margin: 1.2rem 0 2rem;
}

.gh-film__media {
  position: relative;
  max-width: 20rem;
}

.gh-film video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 0.4rem;
  background-color: var(--gh-slate-900);
}

[data-md-color-scheme="slate"] .gh-film__media video,
[data-md-color-scheme="slate"] .gh-film__dialog video {
  box-shadow: 0 0 0 1px var(--gh-slate-700);
}

.md-typeset .gh-film__text p {
  margin: 0 0 1rem;
}

.gh-film__link {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.35rem 0;
  font-weight: 600;
}

/* Pause / Play — added by the script only when the loop actually plays. It sits
   on the video, so its colours are fixed for the dark ground in both themes. */
.gh-film__toggle {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--gh-slate-600);
  border-radius: 0.2rem;
  background-color: rgb(15 23 42 / 0.85);
  color: var(--gh-slate-100);
  font: inherit;
  font-size: 0.65rem;
  cursor: pointer;
}
.gh-film__toggle:hover,
.gh-film__toggle:focus-visible {
  border-color: var(--gh-slate-300);
  color: #ffffff;
}

/* Full version in a modal dialog. The width is bound by both the viewport
   width and 80 % of its height (× 2/3, the clip's aspect: the 4:5 scene plus
   a 270 px band below it for the captions), so the whole portrait frame and
   its controls fit on a phone and on a landscape screen. */
.gh-film__dialog {
  padding: 0;
  border: 0;
  background: transparent;
  max-width: none;
}
.gh-film__dialog::backdrop {
  background-color: rgb(2 6 23 / 0.85);
}
.gh-film__dialog video {
  width: min(92vw, 53vh);
}
.gh-film__dialog form {
  text-align: right;
  margin-bottom: 0.4rem;
}
.gh-film__close {
  padding: 0.2rem 0.7rem;
  border: 1px solid var(--gh-slate-400);
  border-radius: 0.2rem;
  background: transparent;
  color: var(--gh-slate-100);
  font: inherit;
  font-size: 0.7rem;
  cursor: pointer;
}
.gh-film__close:hover,
.gh-film__close:focus-visible {
  border-color: #ffffff;
  color: #ffffff;
}

@media screen and (min-width: 45rem) {
  .gh-film {
    grid-template-columns: 15rem 1fr;
    align-items: center;
    gap: 1.6rem;
  }
}

/* Page-title variant of the hero: a normal content-page H1 (as on The Stack /
   Method), not the large Home hero title — while keeping the hero layout (lead
   paragraph + action buttons). The compound selector outranks the base and the
   desktop hero-title rules, so the size holds at every width. Weight (300),
   letter-spacing and muted colour come from Material's default h1, matching the
   other pages exactly. */
.gh-hero.gh-hero--page .md-typeset h1,
.md-typeset .gh-hero.gh-hero--page h1 {
  font-size: 2em;
  line-height: 1.3;
  color: var(--md-default-fg-color--light);
}

/* ...and its lead paragraphs read as normal body copy (as on The Stack /
   Method), not the enlarged, muted, width-capped Home-hero lead. Size is
   inherited so it tracks Material's default body size at every breakpoint. */
.gh-hero.gh-hero--page p {
  font-size: inherit;
  color: var(--md-default-fg-color);
  max-width: none;
}

/* =============================================================================
   Profile hero — About (photo + identity)
   ========================================================================== */

.gh-profile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
  margin: 0.5rem 0 1.6rem;
}

.gh-profile__photo {
  width: 200px;
  height: auto;
  border-radius: 14px;
  background: #ffffff;
  border: 1px solid var(--md-default-fg-color--lightest);
}

.gh-profile__title {
  text-align: center;
}

.gh-profile__title > :first-child {
  margin: 0;
}

@media screen and (min-width: 45rem) {
  .gh-profile__photo {
    width: 250px;
  }
  .gh-profile__title > :first-child {
    font-size: 1.35rem;
    line-height: 1.35;
  }
}

/* =============================================================================
   Stat strip — four proof figures, in mono
   ========================================================================== */

.gh-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  margin: 0 0 2rem;
  padding: 1.25rem 0;
  border-top: 1px solid var(--md-default-fg-color--lighter);
  border-bottom: 1px solid var(--md-default-fg-color--lighter);
}

.gh-stat {
  text-align: center;
}

.gh-stat__num {
  display: block;
  font-family: var(--md-code-font), monospace;
  font-weight: 700;
  font-size: 1.9rem;
  line-height: 1;
  color: var(--gh-indigo);
}

[data-md-color-scheme="slate"] .gh-stat__num {
  color: var(--gh-indigo-light);
}

.gh-stat__label {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--md-default-fg-color--light);
}

@media screen and (min-width: 45rem) {
  .gh-stats {
    grid-template-columns: repeat(4, 1fr);
  }
  .gh-stat__num {
    font-size: 2.25rem;
  }
}

/* Three-stat variant: the labels are multi-word, so on phones the strip stacks
   to a single column (a three-column row would break words mid-token below
   ~400px). Three even columns return once there is room, at the shared breakpoint. */
.gh-stats--3 {
  grid-template-columns: 1fr;
}

@media screen and (min-width: 45rem) {
  .gh-stats--3 {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* =============================================================================
   Proof verdicts — reserved green / red
   ========================================================================== */

/* The verdict marks (U+2713 / U+2717) are absent from all three self-hosted
   latin subsets, JetBrains Mono included. The declared stack therefore resolves
   to the generic `monospace` family, which does carry them; the exact face is
   the platform's (Menlo on macOS). Colour, not typeface, is what encodes the
   verdict. Do not "fix" this by dropping the stack — that only moves the
   fallback to the body face and changes a rendering already validated. */
.gh-pass,
.gh-fail,
.gh-returned {
  font-family: var(--md-code-font), monospace;
  font-weight: 700;
}
.gh-pass { color: var(--gh-pass); }
.gh-fail { color: var(--gh-fail); }
.gh-returned { color: var(--gh-returned); }

/* Dark mode: lift the verdict colours to match the lightened indigo accent. */
[data-md-color-scheme="slate"] .gh-pass { color: var(--gh-pass-light); }
[data-md-color-scheme="slate"] .gh-fail { color: var(--gh-fail-light); }
[data-md-color-scheme="slate"] .gh-returned { color: var(--gh-returned-light); }

/* Proof card — neutral surface; green lives only on the ✓ verdicts. */
.gh-proof {
  margin: 1.5rem 0 2rem;
  padding: 1.25rem 1.4rem;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-radius: 0.5rem;
  background: var(--gh-slate-50);
}
[data-md-color-scheme="slate"] .gh-proof {
  background: var(--gh-slate-800);
}
.gh-proof > :first-child { margin-top: 0; }
.gh-proof > :last-child { margin-bottom: 0; }
.gh-proof .gh-proof__label {
  display: block;
  margin-bottom: 0.6rem;
  font-family: var(--md-code-font), monospace;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--md-default-fg-color--light);
}
.md-typeset .gh-proof ul {
  list-style: none;
  margin-left: 0;
}
.md-typeset .gh-proof ul li {
  margin-left: 0;
}

/* =============================================================================
   Call to action — the trial's lead-capture prompt (open, not a hard gate)
   ========================================================================== */

/* An accented panel, not a button row: it follows the fail-closed moment and
   turns "you just saw it refuse" into "let's talk". Left rule in indigo ties it
   to the accent; the surface reuses the neutral proof-card ground so the two
   read as one family down the page. */
.gh-cta {
  margin: 2rem 0;
  padding: 1.25rem 1.4rem;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-left: 3px solid var(--gh-indigo);
  border-radius: 0.5rem;
  background: var(--gh-slate-50);
}
[data-md-color-scheme="slate"] .gh-cta {
  background: var(--gh-slate-800);
  border-left-color: var(--gh-indigo-light);
}
.gh-cta > :first-child { margin-top: 0; }
.gh-cta > :last-child { margin-bottom: 0; }
.gh-cta .md-button {
  margin-top: 0.4rem;
}

/* =============================================================================
   Engagement flow — Prove → decide → Build (Work with Guy)
   ========================================================================== */

/* A vertical sequence: two phase panels with a decision gate between them. The
   panels reuse the neutral proof-card ground so the flow reads as one family
   down the page. Phase 2 is dashed and quiet on purpose — it is demand-pulled,
   not a committed next step. The verdict pills reuse the RESERVED pass/returned
   proof colours (a "ready" is a pass; a "not ready" is a returned-for-rework). */
.gh-flow {
  max-width: 42rem;
  margin: 1.5rem 0;
}

.gh-phase {
  padding: 1.1rem 1.3rem;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-radius: 0.5rem;
  background: var(--gh-slate-50);
}
[data-md-color-scheme="slate"] .gh-phase {
  background: var(--gh-slate-800);
}
.gh-phase--next {
  border-style: dashed;
  background: transparent;
}
[data-md-color-scheme="slate"] .gh-phase--next {
  background: transparent;
}
.md-typeset .gh-phase > :first-child { margin-top: 0; }
.md-typeset .gh-phase > :last-child { margin-bottom: 0; }

.gh-flow__arrow {
  margin: 0.4rem 0;
  text-align: center;
  font-family: var(--md-code-font), monospace;
  color: var(--md-default-fg-color--lighter);
}

.gh-decision {
  padding: 1rem 1.3rem;
  border: 1px dashed var(--md-default-fg-color--light);
  border-radius: 0.5rem;
}
.md-typeset .gh-decision > :first-child { margin-top: 0; }
.md-typeset .gh-decision > :last-child { margin-bottom: 0; }

.gh-verdict {
  display: inline-block;
  margin: 0.2rem 0.4rem 0.2rem 0;
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-radius: 2rem;
  font-family: var(--md-code-font), monospace;
  font-size: 0.8rem;
}

/* =============================================================================
   Table cells — keep code tokens whole (scoped, opt-in)
   ========================================================================== */

/* Opt-in only, via a `gh-nowrap-code` wrapper around a specific table. A token
   with no natural break opportunity (e.g. `validate:content`) otherwise wraps
   character by character on a narrow phone, cutting it mid-word
   (`validate:cont` / `ent`). Kept scoped on purpose: a blanket rule on every
   table forces whole tokens that already broke cleanly at their hyphens
   (`AGENT-...-ENGINEER`), which pushes wide tables into horizontal scroll on
   mobile. Apply this only where a token breaks mid-word AND fits whole. */
.gh-nowrap-code td code,
.gh-nowrap-code th code {
  white-space: nowrap;
}

/* Opt-in wrap for a paste-ready instruction block. A fenced `text` block does
   not wrap: long prose lines are clipped and scroll horizontally, so a reader
   cannot see the whole instruction without scrolling — the wrong behavior for
   the one thing on the page they are meant to read and copy. Scoped to a
   `gh-wrap-code` wrapper, it wraps the lines while preserving the leading
   indentation (pre-wrap), so the instruction reads whole; the copy button still
   yields the verbatim text. Long unbreakable tokens (a git URL) break rather
   than overflow. */
.gh-wrap-code pre > code {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* =============================================================================
   Mermaid — vertical stacking on very narrow viewports
   ========================================================================== */

/* Two diagram orientations: horizontal on wide screens, vertical (stacked,
   full-width boxes, readable text) on narrow ones. Mermaid renders to a fixed
   SVG and does not reflow, so we ship both and toggle by viewport. */
.gh-narrow-only {
  display: none;
}

/* Centre the rendered SVG in its container (both orientations). */
.mermaid {
  text-align: center;
}
.md-typeset .mermaid svg {
  display: block;
  margin-inline: auto;
}

@media screen and (max-width: 30rem) {
  .mermaid svg {
    max-width: 100%;
    height: auto;
  }
  .gh-wide-only {
    display: none;
  }
  .gh-narrow-only {
    display: block;
  }
}

/* ---------------------------------------------------------------------------
   Keyboard focus has to be visible where it lands.

   Below the drawer breakpoint the theme parks the primary navigation off-canvas
   (`left: -12.1rem`) and collapses nested navigations and the table of contents
   with `opacity: 0; transform: translateX(-100%)`. None of that removes their
   links from the focus order, and the labels that would reveal them
   (`label[for=__drawer]`, `label[for=__toc]`) carry no tabindex, so no keyboard
   can open them. Measured on production at 401 px, drawer closed: the first
   navigation link and the first table-of-contents link both report focusable,
   and none of the three labels does.

   Pulling those links out of the focus order would trade WCAG 2.4.7 (focus
   visible) for 2.1.1 (keyboard) -- the navigation would become unreachable
   rather than invisible. So the page reveals what the focus reaches, and the
   reveal undoes itself when focus leaves. The offsets are the theme's own, read
   from its compiled stylesheet; the `:checked` rules stay more specific, so
   nothing changes for a pointer user.
   --------------------------------------------------------------------------- */
@media screen and (max-width: 76.234375em) {
  .md-sidebar--primary:focus-within {
    box-shadow: var(--md-shadow-z3);
    transform: translateX(12.1rem);
  }
  .md-nav__toggle ~ .md-nav:focus-within {
    opacity: 1;
    transform: translateX(0);
  }
}

/* Same defect, second surface: below the search breakpoint the theme collapses
   the search panel to `height: 0; width: 0; opacity: 0` — which hides it without
   removing its input from the focus order. Measured on production at 401 px
   over two runs, with the panel's closed state read rather than assumed
   (0px by 0px, opacity 0): the input still takes focus while nothing is shown.
   The reveal the theme applies to `[data-md-toggle=search]:checked` is mirrored
   here on `:focus-within`, so the panel appears when focus reaches it. Note the
   breakpoint: the search collapses at 59.984375em, not at the drawer's
   76.234375em — its own stylesheet is where that number comes from. */
@media screen and (max-width: 59.984375em) {
  .md-search__inner:focus-within {
    height: 100%;
    opacity: 1;
    transform: translateX(0);
    width: 100%;
  }
  /* Revealing the panel alone would show the field over its own hidden results:
     the theme keys the form's open styling, the results and their scroll area on
     the same toggle. Those declarations are mirrored verbatim from its
     stylesheet rather than invented, so a keyboard user sees what a pointer user
     sees rather than typing into a box whose answers stay invisible. */
  .md-search__inner:focus-within .md-search__form {
    background-color: var(--md-default-bg-color);
    border-radius: 0.1rem 0.1rem 0 0;
    box-shadow: 0 0 0.6rem #00000012;
    color: var(--md-default-fg-color);
  }
  .md-search__inner:focus-within .md-search__output {
    box-shadow: var(--md-shadow-z3);
    opacity: 1;
  }
  .md-search__inner:focus-within .md-search__scrollwrap {
    max-height: 75vh;
  }
}

/* Header logo enlarged so the wordmark baked into the lockup stays legible.
   width/max-width are pinned so the size comes only from height × aspect ratio:
   Material's own `.md-logo img { max-width: 100%; object-fit: contain }` otherwise
   clamps the logo to the flex parent's width, which Firefox resolves smaller than
   Blink/WebKit — making the logo shrink in Firefox only. */
.md-header__button.md-logo img {
  height: 1.9rem;
  width: auto;
  max-width: none;
}
