/**
 * FILE: style.css
 * USAGE: Classless stylesheet for the rule-mcp documentation site
 * SCOPE: every emitted page (header, nav, main, footer, preference menu)
 *
 * Layer order: reset, tokens, base, layout, dropdown, home.
 *
 * Typography uses a deliberate local-first stack: no webfont is downloaded, so
 * the serif display face degrades to the platform serif and the interface face
 * to the platform sans. Spacing is a single 0.25rem-based scale.
 */

@layer reset, tokens, base, layout, dropdown, home;

/* Tokens */

@layer tokens {
  :root {
    color-scheme: light dark;
    --font-sans: "Source Serif 4", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
    --font-mono: "IBM Plex Mono", "SF Mono", ui-monospace, monospace;
    --font-ui: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
    --content-width: 112ch;
    --gutter: clamp(1rem, 3vw, 2rem);
    /* Inset shared by header, subnav and footer: it reproduces exactly where
       `main` starts, so every band begins on the same x at every width. */
    --inset: max(var(--gutter), calc((100% - var(--content-width)) / 2));
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-7: 3rem;
    --radius: 0.35rem;
    --bg: light-dark(#f7f4ef, #111724);
    --fg: light-dark(#1a1c1f, #e0f8ff);
    --muted: light-dark(#5c635c, #a9b8ce);
    --border: light-dark(#c9c2b6, #2a3350);
    --accent: light-dark(#1e2363, #63ddff);
    --accent-fg: light-dark(#e0f8ff, #08101c);
    --code-bg: light-dark(#ece7de, #1a2033);
    --focus: light-dark(#1e2363, #8cecff);
    --header-bg: light-dark(#efeae2, #15182a);
    --table-stripe: light-dark(#f0ebe3, #161d2e);
    /* Brand kit palette. The dark theme is the navy field the guidelines
       describe; the light theme keeps its paper field and takes the brand blue
       as its accent, which is the documented light adaptation. */
    --brand-navy: #111724;
    --brand-indigo: #2c2557;
    --brand-cyan: #63ddff;
    --brand-violet: #8f7cff;
    --brand-lilac: #c6bbff;
    --brand-ink: #08101c;
    --brand-glow: color-mix(in srgb, var(--brand-cyan) 22%, transparent);
  }

  html[data-theme="light"] {
    color-scheme: light;
    --bg: #f7f4ef;
    --fg: #1a1c1f;
    --muted: #5c635c;
    --border: #c9c2b6;
    --accent: #1e2363;
    --accent-fg: #e0f8ff;
    --code-bg: #ece7de;
    --focus: #1e2363;
    --header-bg: #efeae2;
    --table-stripe: #f0ebe3;
  }

  html[data-theme="dark"] {
    color-scheme: dark;
    --bg: #111724;
    --fg: #e0f8ff;
    --muted: #a9b8ce;
    --border: #2a3350;
    --accent: #63ddff;
    --accent-fg: #08101c;
    --code-bg: #1a2033;
    --focus: #8cecff;
    --header-bg: #15182a;
    --table-stripe: #161d2e;
  }

  html[data-contrast="more"] {
    --fg: light-dark(#000000, #ffffff);
    --bg: light-dark(#ffffff, #000000);
    --border: light-dark(#000000, #ffffff);
    --muted: light-dark(#222222, #dddddd);
  }

  html[data-theme="light"][data-contrast="more"] {
    --fg: #000000;
    --bg: #ffffff;
    --border: #000000;
    --muted: #222222;
  }

  html[data-theme="dark"][data-contrast="more"] {
    --fg: #ffffff;
    --bg: #000000;
    --border: #ffffff;
    --muted: #dddddd;
  }
}

/* Reset */

@layer reset {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

  html {
    -webkit-text-size-adjust: 100%;
  }

  body {
    margin: 0;
  }

  img,
  svg {
    max-width: 100%;
    height: auto;
  }
}

/* Base elements */

@layer base {
  body {
    font-family: var(--font-ui);
    font-size: 1.26rem;
    line-height: 1.65;
    background: var(--bg);
    color: var(--fg);
    min-height: 100vh;
  }

  h1,
  h2,
  h3,
  h4 {
    /* The brand asks for a neutral modern sans and keeps typography secondary
       to the mark, so the display serif left the headings. */
    font-family: var(--font-ui);
    line-height: 1.15;
    font-weight: 650;
    letter-spacing: -0.015em;
    text-wrap: balance;
    /* A long identifier or a wide font has no break opportunity in a heading,
       and an unbreakable word pushes the whole document sideways at 320px. */
    overflow-wrap: break-word;
  }

  h1 {
    font-size: clamp(2.16rem, 3vw, 2.88rem);
  }

  a {
    color: var(--accent);
  }

  a:focus-visible,
  summary:focus-visible,
  input:focus-visible,
  button:focus-visible {
    outline: 3px solid var(--focus);
    outline-offset: 2px;
  }

  code,
  kbd,
  samp {
    font-family: var(--font-mono);
    font-size: 0.92em;
  }

  pre {
    font-family: var(--font-mono);
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-4);
    overflow-x: auto;
  }

  code:not(pre code) {
    background: var(--code-bg);
    padding: 0.1em var(--space-1);
    border-radius: var(--space-1);
    overflow-wrap: anywhere;
  }

  /* A cell whose only element is a code span holds a bare identifier: a command,
     a tool, a skill, a prompt, a variable. Splitting one across two lines makes
     it unreadable and unsearchable, so it never wraps. A prose cell that merely
     mentions a name inline keeps wrapping, which is why this selects the only
     child rather than every code element. */
  td > code:only-child {
    white-space: nowrap;
  }

  table {
    width: 100%;
    border-collapse: collapse;
    font-size: 1.14rem;
  }

  th,
  td {
    border: 1px solid var(--border);
    padding: var(--space-1) var(--space-3);
    text-align: left;
    vertical-align: top;
  }

  th {
    background: var(--header-bg);
  }

  tbody tr:nth-child(even) {
    background: var(--table-stripe);
  }

  [data-part="table-scroll"] {
    max-width: 100%;
    margin-block: var(--space-4);
    overflow-x: auto;
  }

  hr {
    border: 0;
    border-top: 1px solid var(--border);
  }

  blockquote {
    margin-inline: 0;
    padding-inline: var(--space-4);
    border-inline-start: 3px solid var(--accent);
    color: var(--muted);
  }

  /* A long path or identifier in prose has no space to wrap at, so the line
     stays wider than the viewport and the page scrolls sideways at 320px
     (WCAG 2.2 SC 1.4.10). Break the word only when it cannot fit. */
  p,
  li,
  dd,
  dt {
    overflow-wrap: break-word;
  }
}

/* Layout */

@layer layout {
  body > a[href="#main"] {
    position: absolute;
    left: -999px;
    top: 0;
    background: var(--accent);
    color: var(--accent-fg);
    padding: var(--space-2) var(--space-4);
    z-index: 10;
  }

  body > a[href="#main"]:focus {
    left: var(--space-4);
    top: var(--space-4);
  }

  /* Mobile first. Two rows on a phone: the brand with the preference trigger,
     then the destinations. From 56rem the three share one row. */
  body > header {
    position: sticky;
    top: 0;
    z-index: 5;
    display: grid;
    /* One column by default: at 200% text size a phone has no room for the
       brand and the trigger side by side, and the breakpoint is in rem so it
       follows the text, not the screen. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "brand"
      "nav"
      "prefs";
    align-items: center;
    gap: var(--space-1) var(--space-4);
    padding: var(--space-2) var(--inset);
    background: var(--header-bg);
    border-bottom: 1px solid var(--border);
  }

  /* The brand is one of the menu items, not a masthead above them: same face,
     same weight, same height, so the row reads on one line. */
  body > header > p {
    grid-area: brand;
    margin: 0;
    font-family: var(--font-ui);
    font-size: 1.14rem;
    font-weight: 650;
    letter-spacing: -0.01em;
    min-height: 2.75rem;
    display: flex;
    align-items: center;
  }

  body > header > p a {
    display: inline-flex;
    align-items: center;
    /* Clear space around a standalone mark: at least 15% of the core height.
       The mark is 30px, so the gap carries more than the minimum. */
    gap: var(--space-2);
    min-height: 2.75rem;
    color: var(--fg);
    text-decoration: none;
    letter-spacing: -0.01em;
  }

  body > header > p a:hover {
    color: var(--accent);
  }

  /* The monochrome mark, recolored with the brand gradient: the guidelines
     allow recoloring it and reserve it for small sizes, where the full color
     mark turns into a dark smudge. */
  body > header > p [data-part="brand-mark"] {
    display: block;
    width: 34px;
    height: 34px;
    flex: none;
    background: linear-gradient(135deg, var(--brand-cyan), var(--brand-violet));
    mask: url("assets/monochrome-mark.png") center / 132% no-repeat;
    -webkit-mask: url("assets/monochrome-mark.png") center / 132% no-repeat;
  }

  body > header nav {
    grid-area: nav;
    min-width: 0;
  }

  body > header nav ul,
  body > nav[aria-label="Reference"] ul {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-2);
    list-style: none;
    margin: 0;
    padding: 0;
  }

  body > header nav a,
  body > nav[aria-label="Reference"] a {
    display: inline-flex;
    align-items: center;
    padding-inline: var(--space-3);
    border-radius: var(--radius);
    text-decoration: none;
  }

  /* A finger needs a target it can hit: 44px below the wide breakpoint. */
  body > header nav a {
    min-height: 2.75rem;
    font-weight: 600;
  }

  body > header nav a:hover,
  body > nav[aria-label="Reference"] a:hover {
    background: color-mix(in srgb, var(--accent) 18%, transparent);
  }

  body > header nav a[aria-current="page"],
  body > nav[aria-label="Reference"] a[aria-current="page"] {
    background: var(--accent);
    color: var(--accent-fg);
  }

  body > nav[aria-label="Reference"] {
    padding: var(--space-2) var(--inset);
    border-bottom: 1px solid var(--border);
    background: color-mix(in srgb, var(--header-bg) 70%, var(--bg));
  }

  body > nav[aria-label="Reference"] ul {
    /* Each item carries its own inline padding, so a gap between them would
       double the space and pull the submenu off the header's rhythm. */
    gap: 0;
    font-size: 1.14rem;
  }

  main {
    /* No inline padding: the gutter lives in the width, so the content box and
       the header/subnav/footer content band are the same box. */
    max-width: min(var(--content-width), calc(100% - 2 * var(--gutter)));
    margin-inline: auto;
    padding-block: var(--space-5) var(--space-7);
  }

  footer {
    max-width: min(var(--content-width), calc(100% - 2 * var(--gutter)));
    margin-inline: auto;
    padding-block: var(--space-4) var(--space-6);
    border-top: 1px solid var(--border);
    color: var(--muted);
  }

  footer > p {
    font-size: 1.08rem;
  }

  /* The copyright closes the page: a step down from the build line above it. */
  footer > p[data-part="copyright"] {
    margin-block: 0;
    font-size: 0.98rem;
  }

  /* The request path: a vertical flow graph, one block per step, joined by a
     chevron. Plain markup, so it renders without JavaScript. */
  [data-part="architecture-diagram"] {
    display: flex;
    flex-direction: column;
    margin-block: var(--space-5);
    padding: 0;
    list-style: none;
    counter-reset: step;
  }

  [data-part="architecture-diagram"] > li[data-part="step"] {
    counter-increment: step;
    position: relative;
    margin-block-end: var(--space-5);
    padding: var(--space-4) var(--space-4) var(--space-4) var(--space-7);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--code-bg);
  }

  [data-part="architecture-diagram"] > li[data-part="step"]:last-child {
    margin-block-end: 0;
  }

  [data-part="architecture-diagram"] > li[data-part="step"]::before {
    content: counter(step);
    position: absolute;
    left: var(--space-2);
    top: var(--space-3);
    width: var(--space-5);
    height: var(--space-5);
    border-radius: 50%;
    background: var(--accent);
    color: var(--accent-fg);
    font-size: 1.02rem;
    font-weight: 700;
    /* The body line box is taller than the circle, so a centered line box put
       the digit off-centre. One line, one em, then the em box is the digit. */
    line-height: 1;
    font-variant-numeric: tabular-nums;
    display: grid;
    place-items: center;
    /* A digit's ink sits right of its advance centre and above the em centre,
       so the centred box leaves the numeral visibly off the circle's centre.
       Both nudges are in em: they hold when the badge size changes. */
    text-indent: -0.05em;
    padding-block-start: 0.06em;
  }

  [data-part="architecture-diagram"] > li[data-part="step"]:not(:last-child)::after {
    content: "";
    position: absolute;
    top: calc(100% + var(--space-2));
    left: 50%;
    width: 0.7rem;
    height: 0.7rem;
    border-inline-end: 2px solid var(--accent);
    border-block-end: 2px solid var(--accent);
    rotate: 45deg;
    translate: -50% 0;
  }

  [data-part="architecture-diagram"] > li[data-part="step"] h3 {
    margin-block: 0 var(--space-1);
    font-size: 1.38rem;
  }

  [data-part="architecture-diagram"] > li[data-part="step"] p {
    margin-block: 0;
  }
}

/* Preference dropdown */

@layer dropdown {
  body > header details[data-part="prefs"] {
    grid-area: prefs;
    position: relative;
    font-size: 1.02rem;
    font-family: var(--font-ui);
  }

  /* The trigger speaks the nav's language: the same pill, the same hover wash,
     and the same accent fill as the current page once it is open. */
  body > header details[data-part="prefs"] summary {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 2.75rem;
    padding: var(--space-1) var(--space-4);
    border: 1px solid var(--border);
    border-radius: 999px;
    background: color-mix(in srgb, var(--bg) 70%, transparent);
    color: var(--fg);
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    list-style: none;
    /* The label wraps rather than pushing the header wider than the screen:
       at 200% text size "Preferences" alone is wider than a phone. */
    text-align: start;
    max-width: 100%;
  }

  body > header details[data-part="prefs"] summary::-webkit-details-marker {
    display: none;
  }

  body > header details[data-part="prefs"] summary::after {
    display: inline-block;
    width: 0.55rem;
    height: 0.55rem;
    border-inline-end: 2px solid currentColor;
    border-block-end: 2px solid currentColor;
    rotate: 45deg;
    translate: 0 -0.15rem;
    content: "";
  }

  body > header details[data-part="prefs"] summary:hover {
    border-color: var(--accent);
    color: var(--accent);
  }

  body > header details[data-part="prefs"][open] summary {
    border-color: var(--accent);
    background: var(--accent);
    color: var(--accent-fg);
  }

  body > header details[data-part="prefs"][open] summary::after {
    rotate: -135deg;
    translate: 0 0.1rem;
  }

  /* The outside-click catcher: an invisible layer under the panel. */
  body > header details[data-part="prefs"][open] summary::before {
    display: block;
    z-index: 1;
    position: fixed;
    inset: 0;
    background: none;
    content: "";
    cursor: default;
  }

  /* Closed, the panel leaves the flow entirely. Opacity alone kept an
     invisible box over the nav and the content, which ate clicks and read as
     overlapping text. No transition is allowed on this site, so `display` is
     the honest switch. */
  body > header details[data-part="prefs"] summary + menu {
    display: none;
    z-index: 99;
    position: absolute;
    right: 0;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 16rem;
    margin: var(--space-2) 0 0;
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-radius: calc(var(--radius) * 2.5);
    background: var(--bg);
    color: var(--fg);
    box-shadow: 0 0.9rem 1.6rem color-mix(in srgb, #000 24%, transparent);
    list-style: none;
    opacity: 0;
    transform: scaleY(0.96);
    transform-origin: top right;
  }

  body > header details[data-part="prefs"][open] summary + menu {
    display: flex;
    transform: scaleY(1);
    opacity: 1;
  }

  body > header details[data-part="prefs"] summary + menu > li {
    list-style: none;
  }

  body > header details[data-part="prefs"] fieldset {
    margin: 0;
    padding: var(--space-2) var(--space-2) var(--space-1);
    border: 1px solid color-mix(in srgb, var(--border) 65%, transparent);
    border-radius: var(--radius);
  }

  body > header details[data-part="prefs"] legend {
    padding: 0 var(--space-1);
    font-size: 0.86rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
  }

  /* One row per answer: the whole row is the target, and the native control
     takes the brand color instead of a second set of hand-drawn glyphs. */
  body > header details[data-part="prefs"] label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 2rem;
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius);
    cursor: pointer;
  }

  body > header details[data-part="prefs"] label:hover {
    background: color-mix(in srgb, var(--accent) 14%, transparent);
  }

  body > header details[data-part="prefs"] input {
    flex: none;
    width: 1.05rem;
    height: 1.05rem;
    margin: 0;
    accent-color: var(--accent);
  }

  /* Narrow screens have no room for a panel beside the header, so the panel
     takes the full width and pushes the page down instead of covering its
     title. An overlay that hides the heading reads as a broken page. */
  @media (min-width: 24rem) {
    body > header {
      grid-template-columns: minmax(0, 1fr) auto;
      grid-template-areas:
        "brand prefs"
        "nav nav";
    }
  }

  /* A 320px phone fits both destinations on one line at this size, and two
     stacked rows of menu is a header taller than the content it introduces. */
  @media (max-width: 23.999rem) {
    body > header nav {
      font-size: 1.06rem;
    }

    body > header nav a {
      padding-inline: var(--space-2);
    }
  }

  /* Below the wide breakpoint the panel takes the full width and pushes the
     page down instead of covering its title. */
  @media (max-width: 55.999rem) {
    body > header details[data-part="prefs"] summary {
      width: 100%;
      justify-content: space-between;
    }

    body > header details[data-part="prefs"][open] summary + menu {
      position: static;
      width: 100%;
      min-width: 0;
      margin-block-start: var(--space-2);
      transform: none;
    }
  }

  /* One row from 56rem: brand, destinations, preferences. */
  @media (min-width: 56rem) {
    body > header {
      grid-template-columns: auto 1fr auto;
      grid-template-areas: "brand nav prefs";
      gap: var(--space-2) var(--space-5);
      padding-block: var(--space-3);
    }

    body > header > p,
    body > header > p a {
      min-height: 2.5rem;
    }

    body > header nav a {
      min-height: 2.25rem;
    }

    body > header details[data-part="prefs"] summary {
      min-height: 2.5rem;
    }
  }
}

/* Home page */

@layer home {
  /* The home page is two columns: the hero owns the left half, the flow and the
     cards stack on the right. Named areas are the documented reason to reach
     for grid over flex here (rule-styleguide-css: css-flex-first). */
  body[data-page="home"] main {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "head head"
      "hero flow"
      "hero cards"
      "closing closing";
    align-content: start;
    column-gap: var(--space-6);
    row-gap: var(--space-5);
  }

  body[data-page="home"] main > h1 {
    grid-area: head;
    font-size: clamp(2.88rem, 5vw, 4.32rem);
    margin-block-end: 0;
  }

  body[data-page="home"] section[data-part="closing"] {
    grid-area: closing;
  }

  body[data-page="home"] section[data-part="closing"] > p:last-child {
    margin-block-end: 0;
  }

  body[data-page="home"] section[data-part="hero"] {
    grid-area: hero;
    /* Stretches to match the taller flow/cards column instead of hugging the
       top, so the card's border and background do not leave dead space below
       it (docs/reviews/ui.md: home-grid-hero-deadspace). */
    align-self: start;
    padding: var(--space-6) clamp(1.25rem, 3vw, 2.5rem);
    border: 1px solid var(--border);
    border-radius: calc(var(--radius) * 2);
    background: radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--brand-violet) 20%, transparent), transparent 60%), var(--header-bg);
  }

  /* The primary icon in its rounded-square plate, as the brand kit describes:
     a deep navy field, large corners, one inner border and restrained glow. */
  [data-part="brand-plate"] {
    display: block;
    max-width: 100%;
    margin-block-end: var(--space-5);
    filter: drop-shadow(0 0 1.75rem var(--brand-glow));
  }

  [data-part="brand-plate"] img {
    display: block;
    width: 8rem;
    max-width: 100%;
    height: auto;
    aspect-ratio: 1;
    border: 1px solid color-mix(in srgb, var(--brand-lilac) 28%, transparent);
    border-radius: 1.6rem;
  }

  body[data-page="home"] section[data-part="hero"] > p[data-part="lead"] {
    font-size: 1.56rem;
    text-wrap: balance;
  }

  /* The build line: what this site documents, and where the source is. */
  body[data-page="home"] [data-part="meta"] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-4);
    margin-block: var(--space-3) var(--space-4);
    font-size: 1.02rem;
    color: var(--muted);
  }

  body[data-page="home"] [data-part="meta"] [data-part="version"] {
    padding: 0.05rem var(--space-2);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 0.92rem;
  }

  body[data-page="home"] [data-part="meta"] a[data-part="repo"] {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 2rem;
    color: var(--accent);
    font-weight: 600;
    text-decoration: none;
  }

  body[data-page="home"] [data-part="meta"] a[data-part="repo"]:hover {
    text-decoration: underline;
  }

  body[data-page="home"] [data-part="meta"] svg {
    width: 1.1em;
    height: 1.1em;
  }

  body[data-page="home"] section[data-part="flow"] {
    grid-area: flow;
  }

  body[data-page="home"] section[data-part="flow"] > h2,
  body[data-page="home"] section[data-part="cards"] > h2 {
    margin-block-start: 0;
  }

  body[data-page="home"] section[data-part="cards"] {
    grid-area: cards;
  }

  /* Below the two-column width the same blocks stack in reading order. */
  @media (max-width: 56rem) {
    body[data-page="home"] main {
      grid-template-columns: minmax(0, 1fr);
      grid-template-areas:
        "head"
        "hero"
        "flow"
        "cards"
        "foot";
    }
  }

  body[data-page="home"] ul[data-part="stats"] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    list-style: none;
    margin: var(--space-5) 0;
    padding: 0;
  }

  body[data-page="home"] ul[data-part="stats"] li {
    max-width: 100%;
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--bg);
    font-size: 1.14rem;
    /* A pill that cannot wrap pushes the document past the viewport at 320px
       (WCAG 2.2 SC 1.4.10), so the label wraps instead. */
    overflow-wrap: anywhere;
  }

  body[data-page="home"] ul[data-part="stats"] strong {
    color: var(--accent);
  }

  body[data-page="home"] p[data-part="cta"] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-block-end: 0;
  }

  body[data-page="home"] p[data-part="cta"] a {
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    text-decoration: none;
    font-weight: 600;
  }

  body[data-page="home"] p[data-part="cta"] a:first-child {
    background: var(--accent);
    color: var(--accent-fg);
  }

  body[data-page="home"] p[data-part="cta"] a:hover {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  body[data-page="home"] section[data-part="flow"] ol {
    display: grid;
    /* `min()` keeps the track from forcing a column wider than the card:
       at 200% text size 14rem is wider than a phone. */
    grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
    gap: var(--space-3);
    list-style: none;
    margin: 0;
    padding: 0;
    counter-reset: flow;
  }

  body[data-page="home"] section[data-part="flow"] ol li {
    counter-increment: flow;
    padding: var(--space-4) var(--space-4) var(--space-4) var(--space-7);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--code-bg);
    position: relative;
    font-size: 1.14rem;
  }

  body[data-page="home"] section[data-part="flow"] ol li::before {
    content: counter(flow);
    position: absolute;
    left: var(--space-3);
    top: var(--space-3);
    width: var(--space-5);
    height: var(--space-5);
    border-radius: 50%;
    background: var(--accent);
    color: var(--accent-fg);
    font-size: 1.02rem;
    font-weight: 700;
    /* The body line box is taller than the circle, so a centered line box put
       the digit off-centre. One line, one em, then the em box is the digit. */
    line-height: 1;
    font-variant-numeric: tabular-nums;
    display: grid;
    place-items: center;
    /* A digit's ink sits right of its advance centre and above the em centre,
       so the centred box leaves the numeral visibly off the circle's centre.
       Both nudges are in em: they hold when the badge size changes. */
    text-indent: -0.05em;
    padding-block-start: 0.06em;
  }

  body[data-page="home"] section[data-part="cards"] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
    gap: var(--space-4);
  }

  body[data-page="home"] section[data-part="cards"] > h2 {
    grid-column: 1 / -1;
  }

  body[data-page="home"] section[data-part="cards"] article {
    padding: var(--space-4) var(--space-5);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--header-bg);
  }

  body[data-page="home"] section[data-part="cards"] article h3 {
    margin-block: 0 var(--space-2);
    font-size: 1.38rem;
  }

  body[data-page="home"] section[data-part="cards"] article p {
    margin-block: 0;
    font-size: 1.14rem;
    color: var(--muted);
  }

  body[data-page="home"] section[data-part="cards"] article a {
    text-decoration: none;
  }

  body[data-page="home"] section[data-part="cards"] article a:hover {
    text-decoration: underline;
  }
}
