@scope (grid-ui) {
  :where(:scope) {
    /* Explicit-then-ambient: `[gap="N"]` sets non-inheriting
       `--a-gap-self`; `[size]`/`:root` set inheriting `--a-gap` (base
       `--a-gap-md`). See styles/api/sizing.css + spec §5.2. */
    --grid-gap:        var(--a-gap-self, var(--a-gap));
    --grid-column-gap: var(--grid-gap);
    --grid-row-gap:    var(--grid-gap);
  }

  :scope {
    box-sizing: border-box;
    display: grid;
    /* Default: auto 1fr columns — as many equal columns as children */
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    column-gap: var(--grid-column-gap);
    row-gap: var(--grid-row-gap);
    /* Universal [padding] / [margin] opt-in — see tokens.css for scale. */
    padding: var(--a-padding, 0);
    margin: var(--a-margin, 0);
    /* Neutralize the legacy UA rule that maps the HTML `align=` attr to
       `text-align`. Our [align]/[justify] set grid cross/main-axis item
       alignment, NOT text alignment — without this, `align="center"` silently
       leaks `text-align:center` into every descendant (centered a hero
       headline/deck that should read left). Mirrors row.css / col.css. */
    text-align: inherit;
  }

  /* ── Item alignment ── [align] = block axis (align-items), [justify] =
     inline axis (justify-items). Parity with row-ui / col-ui. CSS-only. */
  :scope[align="start"]     { align-items: start; }
  :scope[align="center"]    { align-items: center; }
  :scope[align="end"]       { align-items: end; }
  :scope[align="stretch"]   { align-items: stretch; }

  :scope[justify="start"]   { justify-items: start; }
  :scope[justify="center"]  { justify-items: center; }
  :scope[justify="end"]     { justify-items: end; }
  :scope[justify="stretch"] { justify-items: stretch; }

  /* Explicit column count — switches to template mode */
  :scope[columns="1"] { grid-auto-flow: row; grid-template-columns: 1fr; grid-auto-columns: auto; }
  :scope[columns="2"] { grid-auto-flow: row; grid-template-columns: repeat(2, 1fr); grid-auto-columns: auto; }
  :scope[columns="3"] { grid-auto-flow: row; grid-template-columns: repeat(3, 1fr); grid-auto-columns: auto; }
  :scope[columns="4"] { grid-auto-flow: row; grid-template-columns: repeat(4, 1fr); grid-auto-columns: auto; }
  :scope[columns="5"] { grid-auto-flow: row; grid-template-columns: repeat(5, 1fr); grid-auto-columns: auto; }
  :scope[columns="6"] { grid-auto-flow: row; grid-template-columns: repeat(6, 1fr); grid-auto-columns: auto; }

  /* Responsive presets — the minmax() floor reads [min-column-width] via
     --grid-min-col (set inline by grid.class.js), defaulting to 12rem.
     MUST also flip to grid-auto-flow:row + grid-auto-columns:auto (like the
     numeric rules) — the base :scope default is grid-auto-flow:column +
     grid-auto-columns:1fr, which makes items flow into IMPLICIT 1fr columns
     instead of wrapping into the auto-fit row tracks (the cause of the
     "240px 77px 77px" sliver cram). */
  :scope[columns="auto-fill"] {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(auto-fill, minmax(var(--grid-min-col, 12rem), 1fr));
  }
  :scope[columns="auto-fit"] {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(auto-fit, minmax(var(--grid-min-col, 12rem), 1fr));
  }

  /* Column span — children can span multiple columns */
  & > [span="2"] { grid-column: span 2; }
  & > [span="3"] { grid-column: span 3; }
  & > [span="4"] { grid-column: span 4; }
  & > [span="5"] { grid-column: span 5; }
  & > [span="6"] { grid-column: span 6; }
  & > [span="full"] { grid-column: 1 / -1; }
}
