@scope (heatmap-ui) {
  :where(:scope) {
    /* ── Layout ── */
    --heatmap-gap:              var(--a-space-1);
    --heatmap-cell-radius:      var(--a-radius-xs);
    --heatmap-inset:            var(--a-inset);
    --heatmap-aspect:           auto;
    --heatmap-cell-min-size:    0.75rem;

    /* ── Colors ── */
    --heatmap-empty-bg:         var(--a-bg-muted);
    --heatmap-border:           1px solid var(--a-border-subtle);
    --heatmap-text:             var(--a-fg);
    --heatmap-label:            var(--a-fg-subtle);

    /* ── Data ramp (5 buckets) ──
       Sequential tint scale, sourced from the L2 `--a-{family}-bucket-N`
       semantic aliases (see styles/colors/semantics.css §BUCKETS). The
       L2 layer handles light-dark() polarity so step 0 reads as
       low-intensity in either scheme without per-component math. */
    --heatmap-bucket-0:         var(--a-accent-bucket-0);
    --heatmap-bucket-1:         var(--a-accent-bucket-1);
    --heatmap-bucket-2:         var(--a-accent-bucket-2);
    --heatmap-bucket-3:         var(--a-accent-bucket-3);
    --heatmap-bucket-4:         var(--a-accent-bucket-4);

    /* ── Legend ── */
    --heatmap-legend-size:      var(--a-caption-size);
    --heatmap-legend-gap:       var(--a-space-1);
  }

  :scope {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: var(--heatmap-gap);
    color: var(--heatmap-text);
    font-size: var(--a-body-size);
    /* A wide day-grid (52+ week columns) keeps a FIXED cell size and scrolls
       horizontally (the GitHub-contributions model) rather than crushing
       fixed-size cells into overlap. matrix/density fit-and-shrink instead. */
    overflow-x: auto;
    scrollbar-width: thin;
  }

  /* day-grid: fixed-size cell tracks + intrinsic width so the host scrolls
     instead of squishing. (class.js writes the fixed gridTemplateColumns
     inline for day-grid; matrix/density keep minmax(0,1fr) to fit.) */
  :scope[type="day-grid"] > [data-grid],
  :scope[type="day-grid"] > [data-months] {
    width: max-content;
  }

  /* Title slot */
  :scope [slot="title"] {
    font-weight: 600;
    margin: 0;
  }

  /* Month labels row (day-grid mode) */
  :scope > [data-months] {
    display: grid;
    gap: var(--heatmap-gap);
    font-size: var(--heatmap-legend-size);
    color: var(--heatmap-label);
  }

  :scope [data-month-label] {
    line-height: 1;
  }

  /* Grid of cells */
  :scope > [data-grid] {
    display: grid;
    gap: var(--heatmap-gap);
  }

  :scope[aspect="square"] > [data-grid] {
    aspect-ratio: 1 / 1;
  }

  :scope[aspect="wide"] > [data-grid] {
    aspect-ratio: auto;
  }

  :scope [data-cell] {
    border-radius: var(--heatmap-cell-radius);
    background: var(--heatmap-empty-bg);
    /* No hard min on the cell box — it conflicted with matrix/density's
       minmax(0,1fr) tracks (the floor refused to shrink, so cells overlapped
       into a smear). day-grid keeps fixed size via its fixed tracks; the
       fit-to-container modes shrink with the track. */
    min-width: 0;
    min-height: 0;
    aspect-ratio: 1 / 1;
    cursor: default;
    transition: transform var(--a-duration-fast) var(--a-easing-out);
  }

  :scope [data-cell][data-v] {
    cursor: pointer;
  }

  :scope [data-cell][data-v]:hover {
    transform: scale(1.15);
    outline: var(--heatmap-border);
  }

  :scope [data-cell][data-bucket="0"] { background: var(--heatmap-bucket-0); }
  :scope [data-cell][data-bucket="1"] { background: var(--heatmap-bucket-1); }
  :scope [data-cell][data-bucket="2"] { background: var(--heatmap-bucket-2); }
  :scope [data-cell][data-bucket="3"] { background: var(--heatmap-bucket-3); }
  :scope [data-cell][data-bucket="4"] { background: var(--heatmap-bucket-4); }

  /* Legend strip */
  :scope > [data-legend] {
    display: flex;
    align-items: center;
    gap: var(--heatmap-legend-gap);
    font-size: var(--heatmap-legend-size);
    color: var(--heatmap-label);
    margin-top: var(--heatmap-gap);
  }

  :scope [data-legend-swatch] {
    width: 0.875rem;
    height: 0.875rem;
    border-radius: var(--heatmap-cell-radius);
    background: var(--heatmap-empty-bg);
    display: inline-block;
  }

  :scope [data-legend-swatch][data-bucket="0"] { background: var(--heatmap-bucket-0); }
  :scope [data-legend-swatch][data-bucket="1"] { background: var(--heatmap-bucket-1); }
  :scope [data-legend-swatch][data-bucket="2"] { background: var(--heatmap-bucket-2); }
  :scope [data-legend-swatch][data-bucket="3"] { background: var(--heatmap-bucket-3); }
  :scope [data-legend-swatch][data-bucket="4"] { background: var(--heatmap-bucket-4); }

  /* ── Color-scheme variants (token overrides only) ── */

  :scope[color-scheme="success"] {
    --heatmap-bucket-0: var(--a-success-bucket-0);
    --heatmap-bucket-1: var(--a-success-bucket-1);
    --heatmap-bucket-2: var(--a-success-bucket-2);
    --heatmap-bucket-3: var(--a-success-bucket-3);
    --heatmap-bucket-4: var(--a-success-bucket-4);
  }

  :scope[color-scheme="warning"] {
    --heatmap-bucket-0: var(--a-warning-bucket-0);
    --heatmap-bucket-1: var(--a-warning-bucket-1);
    --heatmap-bucket-2: var(--a-warning-bucket-2);
    --heatmap-bucket-3: var(--a-warning-bucket-3);
    --heatmap-bucket-4: var(--a-warning-bucket-4);
  }

  :scope[color-scheme="danger"] {
    --heatmap-bucket-0: var(--a-danger-bucket-0);
    --heatmap-bucket-1: var(--a-danger-bucket-1);
    --heatmap-bucket-2: var(--a-danger-bucket-2);
    --heatmap-bucket-3: var(--a-danger-bucket-3);
    --heatmap-bucket-4: var(--a-danger-bucket-4);
  }

  :scope[color-scheme="info"] {
    --heatmap-bucket-0: var(--a-info-bucket-0);
    --heatmap-bucket-1: var(--a-info-bucket-1);
    --heatmap-bucket-2: var(--a-info-bucket-2);
    --heatmap-bucket-3: var(--a-info-bucket-3);
    --heatmap-bucket-4: var(--a-info-bucket-4);
  }
}
