/* Landing-page polish. Colors use Material theme variables so both palettes work. */

/* ============================================================================
   Self-hosted typefaces — the "GitHub-native" pairing.

   Material's built-in Google Fonts loader is disabled (theme.font: false in
   mkdocs.yml), so these @font-face rules plus the --md-text-font/--md-code-font
   mapping below replace it with zero third-party requests. woff2 files live in
   assets/fonts/ (SIL OFL 1.1, latin subset). Roles:
     - Monaspace Neon  — display: landing hero + each page's h1
     - IBM Plex Sans   — body, UI, and headings h2–h6
     - Monaspace Argon — code blocks and inline code
   See docs/development/website.md § Fonts.
   ========================================================================== */

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: optional;
  src: url("../assets/fonts/IBMPlexSans-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: italic;
  font-weight: 400;
  font-display: optional;
  src: url("../assets/fonts/IBMPlexSans-Italic.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: optional;
  src: url("../assets/fonts/IBMPlexSans-SemiBold.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 700;
  font-display: optional;
  src: url("../assets/fonts/IBMPlexSans-Bold.woff2") format("woff2");
}
@font-face {
  font-family: "Monaspace Neon";
  font-style: normal;
  font-weight: 500;
  font-display: optional;
  src: url("../assets/fonts/MonaspaceNeon-Medium.woff2") format("woff2");
}
@font-face {
  font-family: "Monaspace Neon";
  font-style: normal;
  font-weight: 700;
  font-display: optional;
  src: url("../assets/fonts/MonaspaceNeon-Bold.woff2") format("woff2");
}
@font-face {
  font-family: "Monaspace Argon";
  font-style: normal;
  font-weight: 400;
  /* Code is below the fold and not preloaded; keep swap so it always ends up in
     real Monaspace Argon (mono→mono, so the swap barely shifts layout) rather
     than being dropped to the system monospace on a slow first load. */
  font-display: swap;
  src: url("../assets/fonts/MonaspaceArgon-Regular.woff2") format("woff2");
}

:root {
  /* Material composes these into --md-text-font-family / --md-code-font-family,
     appending its own system fallback stack — so a face that fails to load
     degrades to the OS UI/mono font, never to Times. */
  --md-text-font: "IBM Plex Sans";
  --md-code-font: "Monaspace Argon";
}

/* Display face: Monaspace Neon carries the top of the hierarchy — the landing
   hero headline and each page's h1 title. h2–h6 stay in IBM Plex Sans so long
   reference pages don't turn into walls of monospace. */
.md-typeset h1,
.gag-hero h1 {
  font-family: "Monaspace Neon";
  font-weight: 500;
  letter-spacing: -0.02em;
}

:root {
  --gag-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --gag-elev-1: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
  --gag-elev-2: 0 8px 20px rgba(0, 0, 0, 0.12);
  --gag-accent-soft: color-mix(in srgb, var(--md-accent-fg-color) 9%, transparent);
  --gag-accent-line: color-mix(in srgb, var(--md-accent-fg-color) 35%, transparent);
}

/* Brand palette: Kubernetes blue -> teal, matching the logomark + social card.
   Set under the scheme selectors so these win over Material's named accent. */
body[data-md-color-scheme="default"] {
  --md-accent-fg-color: #326ce5;
  --md-accent-fg-color--transparent: rgba(50, 108, 229, 0.1);
  --md-typeset-a-color: #2456c9; /* darker blue for link-text contrast on white */

  /* Semantic red/green used across the why-gag page (problem chips, table
     verdicts, proof rows, stat numbers). "ink" = text/icon colour; "fill" =
     solid background carrying white text. Tuned per palette so they stay
     legible and harmonised — change them here, everywhere follows. */
  --gag-win-ink: #0f8a5f;
  --gag-win-fill: #0f8a5f;
  --gag-bad-ink: #c23a22;
  --gag-bad-fill: #c23a22;

  /* Secondary prose and accent-coloured labels. Same ink/fill split as above:
     these are text colours, and the Material tokens they replace are tuned for
     the light palette only. See website.md § Interface rules the custom layer
     must satisfy for the per-palette APCA readings. */
  --gag-muted: #6e6e6e;
  --gag-accent-ink: #2456c9;
}

body[data-md-color-scheme="slate"] {
  --md-accent-fg-color: #5b8def;
  --md-accent-fg-color--transparent: rgba(91, 141, 239, 0.1);
  --md-typeset-a-color: #6fa0f5;
  --gag-elev-1: 0 1px 3px rgba(0, 0, 0, 0.4);
  --gag-elev-2: 0 10px 24px rgba(0, 0, 0, 0.5);

  /* Lighter inks for legible text/icons on the dark surface. Fills stay deep
     enough to carry white text (the proof-row pills, problem-card chips). */
  --gag-win-ink: #50c878;
  --gag-win-fill: #0f8a5f;
  --gag-bad-ink: #f4744f;
  --gag-bad-fill: #e5533c;

  /* Both are capped by slate's own body text, which sits at Lc 66.9: muted
     prose that out-contrasts body copy inverts the hierarchy. Hence Lc 55.6 and
     61.5 rather than the 75 an unconstrained reading of the rule would ask for.
     Raising the ceiling means raising Material's palette, which is Q734. */
  --gag-muted: hsl(225deg 15% 70%);
  --gag-accent-ink: hsl(220deg 82% 78%);
}

/* Header: Material gives the site title a 1rem left margin, which leaves a big
   gap after the logomark. Tighten it so the wordmark sits beside the mark, with
   the logo's own padding giving roughly equal space on each side. */
[dir="ltr"] .md-header__title {
  margin-left: 0.2rem;
}

/* Hamburger drawer header: centre the logomark across the top and enlarge it a
   touch; let the header grow and add top room so the bigger mark clears the
   site title beneath it (Material left-aligns it at a fixed 5.6rem height). */
.md-nav--primary .md-nav__title {
  height: auto;
  padding-top: 4rem;
  text-align: center;
}

.md-nav--primary .md-nav__title .md-logo img {
  height: 3rem;
  margin-inline: auto;
}

.gag-hero {
  position: relative;
  isolation: isolate;
  text-align: left;
  max-width: 44rem;
  margin: 0 auto;
  padding: 1.25rem 0 1.75rem;
}

/* Subtle dot-grid behind the hero, faded out toward the edges. */
.gag-hero::before {
  content: "";
  position: absolute;
  inset: -1.5rem -2rem 0;
  z-index: -1;
  background-image: radial-gradient(var(--md-default-fg-color--lightest) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(ellipse 70% 70% at 50% 28%, #000, transparent 75%);
  mask-image: radial-gradient(ellipse 70% 70% at 50% 28%, #000, transparent 75%);
  opacity: 0.6;
}

/* Drop the horizontal bleed once the hero nearly fills the viewport. Above the
   large breakpoint the hero is inset far enough that 2rem is absorbed (880px
   hero inside a 1,408px column at 1440px); below it the hero keeps only a 16px
   margin, so the same bleed put 24px of horizontal scroll on the page. */
@media screen and (max-width: 76.25em) {
  .gag-hero::before {
    inset: -1.5rem 0 0;
  }
}

/* Illuminated-initial logomark: the faceted ring sits like a manuscript drop
   cap at the start of the hero, with the eyebrow, headline, and description
   flowing around and beneath it. flow-root contains the float so the call-to-
   action buttons clear it and start on their own line below. */
.gag-hero__intro {
  display: flow-root;
}

/* Logomark + headline as a lockup, the logo vertically centred against the
   title so it never leaves a gap; the description and call-to-action sit below.
   Markdown wraps the <img> in a <p>, so collapse that wrapper to make the image
   itself the flex item. */
.gag-hero__intro {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-bottom: 1.2rem;
}

.gag-hero__intro > p:has(.gag-hero__logo) {
  display: contents;
}

.gag-hero__logo {
  flex-shrink: 0;
  width: clamp(92px, 11vw, 132px);
  height: auto;
  filter: drop-shadow(0 6px 16px color-mix(in srgb, var(--md-accent-fg-color) 30%, transparent));
}

.gag-hero__headline > :first-child {
  margin-top: 0;
}

.gag-hero__headline > :last-child {
  margin-bottom: 0;
}

/* Narrow screens: stack the lockup with the logo centred above the title. The
   breakpoint is set by the headline, not the logo — side by side, the logomark
   and its gap take ~162px out of the headline column, and below 56rem that
   leaves less than the longest unbreakable phrase needs. Stacking hands the
   headline the full hero width instead of splitting the phrase. */
@media screen and (max-width: 56rem) {
  .gag-hero__intro {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 1rem;
  }
}

/* Install snippet: shrink to the width of its longest line and centre it, so
   the block doesn't stretch full width with dead space to the right of the
   short helm flags. max-width (not width) keeps it a full-width block when the
   viewport is narrower than the content, so the code scrolls instead of being
   clipped. */
.gag-install {
  max-width: fit-content;
  margin-inline: auto;
}

/* Section intro (heading + lede): both landing sections share the hero's width
   and are centred as a block, with the text left-aligned inside — so the hero,
   "What GAG gives you", and "How it fits together" all line up consistently.
   Caps to the viewport (and wraps) on narrow screens. */
.gag-section-intro {
  max-width: 44rem;
  margin-inline: auto;
}

/* Caption beneath the architecture flow: centred under the centred diagram. */
.gag-flow__caption {
  max-width: 40rem;
  margin-inline: auto;
  text-align: center;
}

.gag-eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gag-accent-ink);
  margin: 0 0 0.75rem;
}

.gag-hero h1 {
  /* Upper bound is set by the headline column, not by taste: at 44rem minus the
     logomark and its gap the column is 35.9rem, and the longest unbreakable
     phrase is 26 characters of Monaspace Neon (15.86em all told), so anything
     much above 2.2rem forces "Self-hosted GitHub Actions" to overrun. 2.2rem
     leaves ~20px spare at the tightest width (1200px, where the logomark hits
     its 132px cap); every fallback mono face is narrower than Neon, so a failed
     webfont load only ever gains slack. */
  font-size: clamp(1.9rem, 1.25rem + 2.4vw, 2.2rem);
  line-height: 1.12;
  letter-spacing: -0.01em;
  margin: 0 0 0.7rem;
  /* Pretty (not balance): the headline wraps around the floated logomark, so
     keep the lines flush-left rather than centre-balanced. */
  text-wrap: pretty;
}

/* Headline phrases that read as one unit ("Self-hosted GitHub Actions", "zero
   idle compute") and shouldn't be split by a line break — the headline reads as
   two phrases at a glance instead of three ragged lines. Paired with the h1
   font-size cap above, which is what keeps the longest phrase inside the
   headline column. Released below 44rem, where even the full stacked width is
   narrower than the phrase at the minimum type size; phones wrap inside the
   phrase rather than pushing the page sideways. Distinct from the .gag-nowrap
   table-chip utility below, which never releases. */
.gag-hero__phrase {
  white-space: nowrap;
}

@media screen and (max-width: 44rem) {
  .gag-hero__phrase {
    white-space: normal;
  }
}

/* The hero title is the page banner, not a deep-link target — drop its ¶ permalink. */
.gag-hero .headerlink {
  display: none;
}

/* The three load-bearing promises, read as one wide line rather than a
   sentence. Each claim is its own span separated by real whitespace, so a
   screen reader gets three phrases; the dots are generated content and stay
   out of the accessibility tree entirely. */
.gag-hero .gag-claims {
  font-size: clamp(1.05rem, 0.85rem + 0.8vw, 1.22rem);
  font-weight: 700;
  line-height: 1.45;
  color: var(--md-default-fg-color);
  margin: 0 0 0.85rem;
  text-align: center;
}


/* Each claim is an inline-block so a wrap falls *between* phrases; a phrase
   breaks internally only when no line is wide enough to hold it, which is the
   graceful case on a phone rather than the common one. */
.gag-hero .gag-claims span {
  display: inline-block;
}

.gag-hero .gag-claims span + span::before {
  content: "·";
  color: var(--gag-accent-ink);
  font-weight: 400;
  /* Oversized against the claim text so the dot reads as a divider rather than
     punctuation. `em` here resolves against the claim's own clamped size, so it
     scales with the row; line-height 0 keeps the taller glyph from growing the
     line box. */
  font-size: 1.8em;
  line-height: 0;
  vertical-align: -0.08em;
  /* Owned by the claim that follows it, so a wrap never strands the dot at the
     end of a line. Padding is in the dot's own em, hence the smaller numbers. */
  padding: 0 0.28em 0 0.08em;
}

.gag-hero .gag-tagline {
  font-size: clamp(1rem, 0.95rem + 0.4vw, 1.15rem);
  color: var(--gag-muted);
  margin: 0 0 1.5rem;
  text-wrap: pretty;
}

/* Center the call-to-action row even though the hero text is left-aligned. */
.gag-hero p:has(.md-button) {
  text-align: center;
}

.gag-hero .md-button {
  margin: 0.5rem 0.3rem 0;
  border-radius: 0.45rem;
  transition: transform 0.2s var(--gag-ease), box-shadow 0.2s var(--gag-ease),
    background-color 0.2s var(--gag-ease), color 0.2s var(--gag-ease);
}

.gag-hero .md-button:hover {
  transform: translateY(-2px);
  box-shadow: var(--gag-elev-2);
}

.gag-hero .md-button--primary {
  box-shadow: var(--gag-elev-1);
}

.gag-reassure {
  font-size: 0.82rem;
  color: var(--gag-muted);
  max-width: 48rem;
  margin: 1.1rem 0 0;
  text-wrap: pretty;
}

.gag-reassure .twemoji {
  color: var(--gag-accent-ink);
}

/* Benefit cards: 3 across (two balanced rows of three), degrading when narrow. */
.gag-pillars .grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media screen and (max-width: 56rem) {
  .gag-pillars .grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media screen and (max-width: 42rem) {
  .gag-pillars .grid {
    grid-template-columns: 1fr;
  }
}

/* "Who GAG is for" honesty band — the disqualifier, set apart from the three
   persona cards rather than carried as a fourth peer. Flatter than a card (no
   shadow, no hover lift) with an accent rule, so the "not for everyone" scope
   note reads as confident honesty — a trust signal — and closes the section. */
.gag-fit-note {
  /* Block, not flex. This is a paragraph with a leading icon, and a flex
     container promotes every inline child (`strong`, `a`) to its own flex item
     that will not wrap. Measured 2026-08-07 at 375px: the flex version pushed
     the layout viewport to 485px and rendered "Not your setup?" as a 52px
     column three lines tall. Block keeps the icon inline and the prose prose. */
  display: block;
  margin: 1.1rem 0 0;
  padding: 0.8rem 1rem;
  border: 1px solid var(--md-default-fg-color--lightest);
  border-left: 3px solid var(--md-accent-fg-color);
  border-radius: 0.6rem;
  background: color-mix(
    in srgb,
    var(--md-accent-fg-color) 5%,
    var(--md-default-bg-color)
  );
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--gag-muted);
  text-wrap: pretty;
}

.gag-fit-note strong {
  color: var(--md-default-fg-color);
}

.gag-fit-note .twemoji {
  color: var(--gag-accent-ink);
  margin-right: 0.4rem;
  vertical-align: -0.16em;
}

/* Tighten the routing list: it is three scan lines, not body copy, so it gets
   less leading than the surrounding prose and no extra block margins. */
.gag-fit-note > :first-child {
  margin-top: 0;
}

.gag-fit-note > :last-child {
  margin-bottom: 0;
}

.gag-fit-note ul {
  margin: 0.5rem 0;
}

.gag-fit-note li {
  margin-bottom: 0.15rem;
}

.gag-fit-note .twemoji svg {
  width: 1.05rem;
  height: 1.05rem;
}

/* Marketing pages (landing + Why-GAG): give the content more side breathing
   room on wide screens. Scoped via :has() to the pages carrying the heroes, so
   the nav-inset docs pages are untouched (no JS needed). */
@media screen and (min-width: 72rem) {
  .md-content__inner:has(.gag-hero),
  .md-content__inner:has(.gag-vs-hero) {
    padding-left: 3.5rem;
    padding-right: 3.5rem;
  }
}

/* Why-GAG split hero: left-aligned argument + a right-hand ARC-vs-GAG proof
   card, so the comparison starts in the first screenful (distinct from the
   centered landing hero). Stacks to one column on narrow screens. */
.gag-vs-hero {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 2.5rem;
  align-items: center;
  padding: 2.5rem 0 2rem;
}

@media screen and (max-width: 55rem) {
  .gag-vs-hero {
    grid-template-columns: 1fr;
    gap: 1.5rem;
    padding: 1.5rem 0;
  }
}

.gag-vs-hero h1 {
  font-size: clamp(1.9rem, 1.4rem + 2.4vw, 2.8rem);
  line-height: 1.12;
  letter-spacing: -0.01em;
  margin: 0 0 0.8rem;
  text-wrap: balance;
}

/* Hero headline is the page banner, not a deep-link target — drop its ¶ permalink. */
.gag-vs-hero h1 .headerlink {
  display: none;
}

.gag-vs-hero__lede {
  font-size: clamp(1rem, 0.95rem + 0.35vw, 1.12rem);
  color: var(--gag-muted);
  max-width: 34rem;
  margin: 0 0 1.5rem;
  text-wrap: pretty;
}

.gag-vs-hero .md-button {
  margin: 0.25rem 0.5rem 0.25rem 0;
  border-radius: 0.45rem;
  transition: transform 0.2s var(--gag-ease), box-shadow 0.2s var(--gag-ease),
    background-color 0.2s var(--gag-ease), color 0.2s var(--gag-ease);
}

.gag-vs-hero .md-button:hover {
  transform: translateY(-2px);
  box-shadow: var(--gag-elev-2);
}

.gag-vs-hero .md-button--primary {
  box-shadow: var(--gag-elev-1);
}

/* The proof card: ARC's failure mode stacked above GAG's, on the same scenario. */
.gag-vs-hero__proof {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  border: 1px solid var(--md-default-fg-color--lightest);
  border-radius: 0.7rem;
  padding: 1rem;
  background: var(--md-default-bg-color);
  box-shadow: var(--gag-elev-1);
}

.gag-vs-hero__proof-cap {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--gag-muted);
  margin: 0 0 0.1rem;
}

.gag-vs-hero__proof-cap code {
  text-transform: none;
}

.gag-vs-row {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  padding: 0.7rem 0.8rem;
  border-radius: 0.5rem;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--md-default-fg-color);
}

/* Warm tint for the ARC pain, cool/green for the GAG outcome — the row colour
   carries the contrast (matching the warm problem-card chips elsewhere). */
.gag-vs-row--arc {
  background: color-mix(in srgb, var(--gag-bad-fill) 10%, transparent);
}

.gag-vs-row--gag {
  background: color-mix(in srgb, var(--gag-win-fill) 12%, transparent);
}

.gag-vs-row__tag {
  flex: none;
  align-self: center;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 0.2rem 0.45rem;
  border-radius: 0.3rem;
  color: #fff;
}

.gag-vs-row--arc .gag-vs-row__tag {
  background: var(--gag-bad-fill);
}

.gag-vs-row--gag .gag-vs-row__tag {
  background: var(--gag-win-fill);
}

/* Why-GAG problem cards: 2 across (the four problems pair up), reusing the
   benefit-card visuals below. Collapses to one column on narrow screens. */
.gag-pillars.gag-cols-2 .grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media screen and (max-width: 45rem) {
  .gag-pillars.gag-cols-2 .grid {
    grid-template-columns: 1fr;
  }
}

/* Problem cards read as "the pain", so fill their icon chip red (vs the accent
   blue used for GAG's benefits) — the eye separates problem from solution. */
.gag-pillars.gag-pillars--problem .grid.cards .twemoji.lg {
  background: var(--gag-bad-fill);
  color: #fff;
}

/* Stat band: a row of headline numbers — the scannable "spice" for skimmers,
   each tied to a claim spelled out in the table and appendices below. */
.gag-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.75rem;
  margin: 1.5rem 0 1.75rem;
}

.gag-stat {
  border: 1px solid var(--md-default-fg-color--lightest);
  border-radius: 0.6rem;
  padding: 1.1rem 1rem;
  text-align: center;
  background: var(--md-default-bg-color);
  box-shadow: var(--gag-elev-1);
  transition: transform 0.2s var(--gag-ease), box-shadow 0.2s var(--gag-ease),
    border-color 0.2s var(--gag-ease);
}

.gag-stat:hover {
  transform: translateY(-3px);
  box-shadow: var(--gag-elev-2);
  border-color: var(--gag-accent-line);
}

.gag-stat__num {
  display: block;
  font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.2rem);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  /* Green = "GAG win" (same language as the table ✓ and hero GAG pill), so the
     stat band reads as the red problem cards above it, now fixed. */
  color: var(--gag-win-ink);
}

.gag-stat__label {
  display: block;
  margin-top: 0.45rem;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--gag-muted);
  text-wrap: pretty;
}

/* Bold lead phrase (before the em-dash) at full text strength, so it reads as a
   mini-heading above the muted supporting detail. */
.gag-stat__lead {
  font-weight: 700;
  color: var(--md-default-fg-color);
}

@media screen and (max-width: 50rem) {
  .gag-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media screen and (max-width: 30rem) {
  .gag-stats {
    grid-template-columns: 1fr;
  }
}

/* Savings calculator (Appendix F § F.5). The `.gag-calc` mount is empty in the
   markdown (so GitHub / no-JS shows the worked example below it); JS fills it. */
.gag-calc {
  border: 1px solid var(--md-default-fg-color--lightest);
  border-radius: 0.7rem;
  padding: 1.25rem;
  margin: 1.5rem 0;
  background: var(--md-default-bg-color);
  box-shadow: var(--gag-elev-1);
}

.gag-calc__form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.9rem;
}

.gag-calc__field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.gag-calc__field-label {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--gag-muted);
}

.gag-calc__field input {
  font-size: 0.95rem;
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-radius: 0.4rem;
  background: var(--md-default-bg-color);
  color: var(--md-default-fg-color);
}

.gag-calc__field input:focus-visible {
  outline: 2px solid var(--md-accent-fg-color);
  outline-offset: 1px;
}

.gag-calc__presets {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.9rem;
}

.gag-calc__preset {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  text-align: left;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--md-default-fg-color--lighter);
  border-radius: 0.45rem;
  background: var(--md-default-bg-color);
  color: var(--md-default-fg-color);
  cursor: pointer;
  transition: border-color 0.15s var(--gag-ease), transform 0.15s var(--gag-ease);
}

.gag-calc__preset:hover {
  border-color: var(--gag-accent-line);
  transform: translateY(-1px);
}

.gag-calc__preset strong {
  font-size: 0.82rem;
}

.gag-calc__preset small {
  font-size: 0.7rem;
  color: var(--gag-muted);
}

.gag-calc__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.6rem;
  margin-top: 1.1rem;
}

.gag-calc__cell {
  border: 1px solid var(--md-default-fg-color--lightest);
  border-radius: 0.55rem;
  padding: 0.8rem 0.7rem;
  text-align: center;
  background: var(--md-default-bg-color);
}

.gag-calc__cell--win {
  border-color: color-mix(in srgb, var(--gag-win-fill) 45%, transparent);
  background: color-mix(in srgb, var(--gag-win-fill) 9%, transparent);
}

.gag-calc__cell-num {
  display: block;
  font-size: clamp(1.2rem, 0.95rem + 1vw, 1.6rem);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  /* These four re-render on every keystroke, so proportional figures make the
     digits shuffle width as the reader types. Tabular pins them. */
  font-variant-numeric: tabular-nums;
}

.gag-calc__cell--win .gag-calc__cell-num {
  color: var(--gag-win-ink);
}

.gag-calc__cell-label {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--md-default-fg-color);
}

.gag-calc__cell-sub {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.68rem;
  color: var(--gag-muted);
}

.gag-calc__note {
  margin: 0.9rem 0 0;
  font-size: 0.76rem;
  line-height: 1.5;
  color: var(--gag-muted);
  text-wrap: pretty;
}

@media screen and (max-width: 50rem) {
  .gag-calc__form {
    grid-template-columns: 1fr;
  }
  .gag-calc__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media screen and (max-width: 30rem) {
  .gag-calc__grid {
    grid-template-columns: 1fr;
  }
}

/* Four-tier flow: real DOM boxes so text stays legible and the layout reflows
   (branching row on wide screens, stacked on narrow) instead of scaling an SVG. */
.gag-flow {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  margin: 1.5rem auto;
  /* Bound the diagram so the two-up Tier 2/3 row doesn't stretch to fill a wide
     column — keeps the boxes a consistent size and the whole flow centered. */
  max-width: 38rem;
}

.gag-flow__node {
  border: 1px solid var(--md-default-fg-color--lightest);
  border-radius: 0.4rem;
  padding: 0.6rem 1rem;
  text-align: center;
  background: var(--md-default-bg-color);
  min-width: 12rem;
}

.gag-flow__node--lead {
  border-color: var(--md-accent-fg-color);
}

.gag-flow__node--input {
  border-style: dashed;
}

.gag-flow__tier {
  display: block;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gag-accent-ink);
  margin-bottom: 0.15rem;
}

.gag-flow__tier--input {
  color: var(--gag-muted);
}

.gag-flow__title {
  display: block;
  font-weight: 700;
}

.gag-flow__sub {
  display: block;
  font-size: 0.78rem;
  color: var(--gag-muted);
}

.gag-flow__arrow {
  color: var(--gag-muted);
  font-size: 0.8rem;
}

.gag-flow__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
}

/* Roll-up variant (why-gag "What changes with GAG"). Two differences from the
   four-tier diagram: it may use the full content column, and its nodes carry a
   sentence rather than a label, so they must share the row evenly instead of
   sizing to their text. `flex: 1 1 0` splits each row N ways whatever N is,
   while the inherited 12rem floor decides when to wrap: the four-outcome row is
   4-across at full width and 2x2 in a narrow column. */
.gag-flow--wide {
  max-width: 52rem;
}

.gag-flow--wide .gag-flow__row {
  align-self: stretch;
}

.gag-flow--wide .gag-flow__row .gag-flow__node {
  flex: 1 1 0;
}

/* A capability that is only partly delivered. Dashed rather than solid so the
   diagram cannot claim more than has shipped; the node still reads as an input
   because the delivered half genuinely feeds the outcome. */
.gag-flow__node--wip {
  border-style: dashed;
}

/* Wider content column (less side gutter) so wide tables have room to breathe. */
.md-grid {
  max-width: 72rem;
}

/* Benefit cards: depth + hover lift, with the icon in an accent chip. */
.gag-pillars .grid.cards > ul > li {
  border: 1px solid var(--md-default-fg-color--lightest);
  border-radius: 0.6rem;
  box-shadow: var(--gag-elev-1);
  transition: transform 0.2s var(--gag-ease), box-shadow 0.2s var(--gag-ease),
    border-color 0.2s var(--gag-ease);
  padding: 0.6rem 0.75rem;
}

.gag-pillars .grid.cards > ul > li:hover {
  transform: translateY(-3px);
  box-shadow: var(--gag-elev-2);
  border-color: var(--gag-accent-line);
}

/* Card header: icon chip sits inline-left of the title, vertically centred —
   not floating as a separate block above it. */
.gag-pillars .grid.cards > ul > li > p:first-child {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.3rem;
}

/* Divider between header and body. */
.gag-pillars .grid.cards > ul > li > hr {
  margin: 0.3rem 0;
}

/* Lead text and bullet list. */
.gag-pillars .grid.cards > ul > li > p:not(:first-child) {
  font-size: 0.75rem;
  margin-bottom: 0.25rem;
}

.gag-pillars .grid.cards > ul > li ul {
  margin: 0;
  padding-left: 1rem;
}

.gag-pillars .grid.cards > ul > li ul > li {
  font-size: 0.75rem;
  line-height: 1.35;
  margin-bottom: 0.15rem;
}

/* Bold, solid icon chip with a white glyph so the card headers pop. */
.gag-pillars .grid.cards .twemoji.lg {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 0.5rem;
  background: var(--md-accent-fg-color);
  color: #fff;
}

.gag-pillars .grid.cards .twemoji.lg svg {
  width: 1rem;
  height: 1rem;
}

/* Continuation line in a table cell — indents to align under the first line's
   text, past the leading icon. */
.gag-cont {
  display: inline-block;
  padding-left: 1.5em;
}

/* Keep a short code chip on one line inside a narrow table column (Material
   default word-breaks code in table cells). Applied per-span via raw HTML
   (<code class="gag-nowrap">) — attr_list does not attach to inline code —
   and never table-wide: long code in other columns still needs to wrap. */
.md-typeset .gag-nowrap {
  white-space: nowrap;
  word-break: normal;
}

/* Marketing badges — one pill, four independent axes. Each answers a different
   question about a capability: which API surface it needs, how stable its shape
   is, which release it belongs to, and which acquisition tier it reaches. Hue
   is the only thing that varies; the geometry lives here once so a fifth axis
   cannot drift a pixel away from the other four. Contrast for every pair is
   measured in docs/development/website.md, "Interface rules". */
.gag-v2-badge,
.gag-maturity-badge,
.gag-release-chip,
.gag-new-badge,
.gag-tier-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem 0.4rem;
  border-radius: 0.75rem;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  vertical-align: middle;
  margin-left: 0.15rem;
  white-space: nowrap;
}

/* v2 API badge — the capability requires the v2beta1 API. */
.gag-v2-badge {
  background: rgba(103, 80, 164, 0.12);
  color: #6750a4;
}

[data-md-color-scheme="slate"] .gag-v2-badge {
  background: rgba(208, 188, 255, 0.15);
  color: #d0bcff;
}

/* Maturity badge — the API shape is still under its first stability contract.
   Amber warns "not yet GA". */
.gag-maturity-badge {
  background: rgba(179, 118, 0, 0.14);
  color: #8a5a00;
}

[data-md-color-scheme="slate"] .gag-maturity-badge {
  background: rgba(255, 202, 128, 0.16);
  color: #ffca80;
}

/* Release chip — the release a roadmap item blocks. Injected by
   hooks/release_gates.py from the backlog's `X.Y-gate` labels, never typed into
   the page (Q770), so a stale one is unreachable rather than unlikely. */
.gag-release-chip {
  background: rgba(0, 105, 110, 0.12);
  color: #00696e;
}

[data-md-color-scheme="slate"] .gag-release-chip {
  background: rgba(93, 216, 224, 0.16);
  color: #5dd8e0;
}

/* New-in-release badge — the release a shipped capability arrived in, declared
   by the pull request that ships it. Green reads as an addition; the gate in
   devtools/docs/roadmapcheck expires it as releases pass (Q768). */
.gag-new-badge {
  background: rgba(30, 106, 58, 0.12);
  color: #1e6a3a;
}

[data-md-color-scheme="slate"] .gag-new-badge {
  background: rgba(126, 217, 156, 0.16);
  color: #7ed99c;
}

/* Tier badge — the capability reaches only one acquisition tier. A caveat on a
   shipped capability rather than a property of it, so it takes the rose the
   other three leave free, and the gate removes it on parity (Q767). */
.gag-tier-badge {
  background: rgba(158, 44, 78, 0.12);
  color: #9e2c4e;
}

[data-md-color-scheme="slate"] .gag-tier-badge {
  background: rgba(255, 177, 198, 0.16);
  color: #ffb1c6;
}

/* Every table: bigger text, rounded frame, emphasized header. NB: do not re-add
   a :not([class]) guard here — the scroll-reveal JS stamps .gag-reveal onto
   every plain table in .md-content, which a :not([class]) selector would then
   exclude, dropping all this styling (that was the why-gag bug). That same reach
   is why the GAG-column accent lives with the comparison table below and not
   here: "last column" means GAG on exactly one of the site's ~660 tables. */
.md-typeset table {
  font-size: 0.8rem;
  border: 1px solid var(--md-default-fg-color--lightest);
  border-radius: 0.5rem;
  overflow: hidden;
}

.md-typeset table th {
  font-weight: 700;
  background: var(--md-default-fg-color--lightest);
}

.md-typeset table td:first-child {
  font-weight: 500;
}

.md-typeset table tbody tr:hover td {
  background: color-mix(in srgb, var(--md-accent-fg-color) 4%, transparent);
}

/* Plain (non-marketing) tables: Material defaults these to 0.64rem (12.8px),
   which reads too small against 16px body copy — more so since IBM Plex Sans has
   a smaller x-height than Roboto. The rule above only wins for classed tables
   (the reveal JS stamps a class on marketing tables); Material's own
   :not([class]) selector out-specifies it for plain docs tables, so bump those
   explicitly to 0.75rem (15px). */
.md-typeset table:not([class]) {
  font-size: 0.75rem;
}

/* Admonitions / collapsible details (e.g. the "New tenants: onboard on v2" tip):
   Material defaults their content to 0.64rem (12.8px), same too-small problem as
   plain tables. Bump the block so the title and body both read at 0.75rem (15px);
   nested children inherit. */
.md-typeset .admonition,
.md-typeset details {
  font-size: 0.75rem;
}

/* The why-gag comparison table: fill the column (so it isn't left-aligned with a
   right-hand gap) and restore roomy cell padding. Material's default cell padding
   is :not([class])-guarded, so the reveal JS that classes this table drops it —
   hence re-stating it here. Scoped to this page so other tables are untouched.
   table-layout: fixed pins the column widths below: under auto layout the browser
   splits width by each column's max-content demand, and the GAG column's
   continuation sentences dwarf the other two — it took 58% while the capability
   label, the anchor of every row, was starved to 19% (narrower than ARC's 23%)
   and wrapped labels that would otherwise fit on one line. */
.md-content__inner:has(.gag-vs-hero) table {
  width: 100%;
  table-layout: fixed;
}

/* Label column gets room for a one-line capability name; the two compared columns
   stay close enough to read side-by-side, GAG widest as it carries ~2x the text. */
.md-content__inner:has(.gag-vs-hero) table th:nth-child(1) {
  width: 26%;
}

.md-content__inner:has(.gag-vs-hero) table th:nth-child(2) {
  width: 32%;
}

.md-content__inner:has(.gag-vs-hero) table th:nth-child(3) {
  width: 42%;
}

.md-content__inner:has(.gag-vs-hero) table th,
.md-content__inner:has(.gag-vs-hero) table td {
  padding: 0.7rem 1.05rem;
  vertical-align: top;
}

/* Last column = GitHub Actions Gateway: tint it so the eye lands on "us". This
   is the whole reason the accent is page-scoped — on every other table the last
   column is whatever the author put rightmost, and the tint reads as an emphasis
   the page never meant. */
.md-content__inner:has(.gag-vs-hero) table th:last-child {
  color: var(--gag-accent-ink);
}

.md-content__inner:has(.gag-vs-hero) table th:last-child,
.md-content__inner:has(.gag-vs-hero) table td:last-child {
  background: var(--gag-accent-soft);
}

.md-content__inner:has(.gag-vs-hero) table tbody tr:hover td:last-child {
  background: var(--gag-accent-soft);
}

/* On phones the 3-column table is unreadable (cells wrap to many lines, code
   tokens break mid-word), so stack each row: the capability becomes a heading
   with the ARC and GAG outcomes labelled and full-width beneath it. */
@media screen and (max-width: 38rem) {
  .md-content__inner:has(.gag-vs-hero) table,
  .md-content__inner:has(.gag-vs-hero) table tbody,
  .md-content__inner:has(.gag-vs-hero) table tr,
  .md-content__inner:has(.gag-vs-hero) table td {
    display: block;
    width: auto;
  }

  .md-content__inner:has(.gag-vs-hero) table thead {
    display: none;
  }

  .md-content__inner:has(.gag-vs-hero) table tr {
    padding: 0.6rem 0.4rem;
    border-bottom: 1px solid var(--md-default-fg-color--lightest);
  }

  .md-content__inner:has(.gag-vs-hero) table tr:last-child {
    border-bottom: 0;
  }

  .md-content__inner:has(.gag-vs-hero) table td {
    padding: 0.15rem 0.8rem;
  }

  .md-content__inner:has(.gag-vs-hero) table td:first-child {
    font-weight: 700;
    font-size: 0.92rem;
    padding-bottom: 0.4rem;
  }

  /* Drop the per-cell GAG tint when stacked, and label the two outcome lines. */
  .md-content__inner:has(.gag-vs-hero) table td:last-child {
    background: transparent;
  }

  .md-content__inner:has(.gag-vs-hero) table td:nth-child(2)::before,
  .md-content__inner:has(.gag-vs-hero) table td:last-child::before {
    font-weight: 700;
    margin-right: 0.15rem;
  }

  .md-content__inner:has(.gag-vs-hero) table td:nth-child(2)::before {
    content: "ARC";
    color: var(--gag-bad-ink);
  }

  .md-content__inner:has(.gag-vs-hero) table td:last-child::before {
    content: "GAG";
    color: var(--gag-win-ink);
  }
}

/* The generated API reference (docs/reference/api.md): every type renders as the
   same Field / Description / Default / Validation table, so the columns are
   pinned rather than left to auto layout. Auto layout splits width by each
   column's max-content demand, which the descriptions dominate and which shifts
   with the container: measured at a 748px content column, Description held 38%
   while Default held 13% for values never longer than "kubernetes"; widen the
   container and the split inverts, starving Field until `githubCABundleRef` and
   its type link break mid-word. Scoped by the page's own h1, the same :has()
   page-scoping the comparison table above uses. */
.md-typeset:has(> h1#api-reference) table {
  width: 100%;
  table-layout: fixed;
}

.md-typeset:has(> h1#api-reference) table th:nth-child(1) {
  width: 24%;
}

.md-typeset:has(> h1#api-reference) table th:nth-child(2) {
  width: 50%;
}

/* Every default in the generated page is a short scalar (longest: "kubernetes"),
   so this column only needs room for its own header. */
.md-typeset:has(> h1#api-reference) table th:nth-child(3) {
  width: 10%;
}

/* Enum tables are Field / Description only; the widths above would leave the
   description at half the row with nothing beside it. */
.md-typeset:has(> h1#api-reference) table th:nth-child(2):last-child {
  width: 76%;
}

/* Rows are tall and uneven (a one-line default beside a five-line description),
   so cell text starts at the top rather than floating in the middle. */
.md-typeset:has(> h1#api-reference) table th,
.md-typeset:has(> h1#api-reference) table td {
  vertical-align: top;
}

/* Verdict icons in the comparison table: green for a GAG win, warm red for an
   ARC shortfall (matching the proof-card and problem-card colour language). */
.md-typeset .gag-yes,
.md-typeset .gag-no {
  margin-right: 0.15rem;
  vertical-align: text-bottom;
}

.md-typeset .gag-yes {
  color: var(--gag-win-ink);
}

.md-typeset .gag-no {
  color: var(--gag-bad-ink);
}

/* Scroll reveals — only when JS adds .gag-reveal-ready. No-JS and reduced-motion
   users never get the hidden initial state, so they see everything immediately. */
html.gag-reveal-ready .gag-reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.5s var(--gag-ease), transform 0.5s var(--gag-ease);
}

html.gag-reveal-ready .gag-reveal.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html.gag-reveal-ready .gag-reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none;
  }
}

/* Clear keyboard focus ring. */
.md-typeset a:focus-visible,
.md-button:focus-visible,
.persona-chip:focus-visible {
  outline: 2px solid var(--md-accent-fg-color);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Persona filter on the operations index (progressively enhanced from a table). */
.persona-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0 0 1rem;
}

.persona-chip {
  font-size: 0.78rem;
  line-height: 1;
  padding: 0.42rem 0.85rem;
  border-radius: 1rem;
  border: 1px solid var(--md-default-fg-color--lightest);
  background: transparent;
  color: var(--gag-muted);
  cursor: pointer;
  transition: background-color 0.15s var(--gag-ease), color 0.15s var(--gag-ease),
    border-color 0.15s var(--gag-ease);
}

.persona-chip:hover {
  border-color: var(--gag-accent-line);
}

.persona-chip[aria-pressed="true"] {
  background: var(--md-accent-fg-color);
  border-color: var(--md-accent-fg-color);
  color: #fff;
}

.persona-pill {
  display: inline-block;
  font-size: 0.7rem;
  line-height: 1.5;
  /* 0.1rem, not 0.05rem: the row pills are buttons, and 14px of text at 1.5
     leaves a 23px control at the smaller value — a pixel under the 24px hit
     target floor. See website.md § Interface rules the custom layer must satisfy. */
  padding: 0.1rem 0.5rem;
  border-radius: 0.8rem;
  background: var(--gag-accent-soft);
  color: var(--gag-accent-ink);
  white-space: nowrap;
}

/* Row pills are progressively enhanced into buttons that select the chip. */
button.persona-pill {
  border: none;
  font-family: inherit;
  cursor: pointer;
  transition: background-color 0.15s var(--gag-ease);
}

button.persona-pill:hover {
  background: color-mix(in srgb, var(--md-accent-fg-color) 20%, transparent);
}

button.persona-pill:focus-visible {
  outline: 2px solid var(--md-accent-fg-color);
  outline-offset: 1px;
}

/* Per-doc audience pills, just under the page title. */
.persona-pills-top {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: -0.2rem 0 1.2rem;
}

/* Audience pills are links to the filtered ops index — keep the pill look. */
.md-typeset a.persona-pill {
  text-decoration: none;
  color: var(--gag-accent-ink);
  transition: background-color 0.15s var(--gag-ease);
}

.md-typeset a.persona-pill:hover {
  background: color-mix(in srgb, var(--md-accent-fg-color) 20%, transparent);
}

/* Backlog filters on the dev-only STATUS page — one labelled chip bar per
   dimension, reusing the persona chip look. */
.backlog-filters {
  margin: 0 0 1rem;
}

.backlog-filter {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.35rem;
}

.backlog-filter__legend {
  flex: 0 0 3.4rem;
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gag-muted);
}

/* The bars sit inside a labelled row, so drop the standalone bottom margin. */
.backlog-filter .persona-bar {
  margin: 0;
}

.md-typeset .backlog-count {
  margin: 0.2rem 0 0;
  font-size: 0.7rem;
  color: var(--gag-muted);
}

/* Row labels select their chip, like the persona pills. */
.md-typeset code.backlog-label {
  cursor: pointer;
}

@media screen and (max-width: 44.9375em) {
  .backlog-filter__legend {
    flex-basis: 100%;
  }
}
