@layer components {
  /* ——— The feed's day ———
     A heading and whatever is under it: sentences in Timeline, bands of things
     in Wrap-up. The group exists so that hiding rows can hide what was heading
     them — the text filter takes rows down one by one, and a date or a band
     label left standing over nothing reads as a bug, the same complaint the
     gap row answers from the other side.

     Keyed on the filter's own target rather than on a list of row classes:
     "the thing the filter hides" is exactly what the rule means, and the two
     readings of this feed draw different rows. :has() rather than a count kept
     in JavaScript, because the filter already says what it hid and the
     headings only have to notice.

     The feed's type size is set here, once, for the same reason the group
     exists: it is a fact about the day and not about how you are reading it.
     It used to sit on `.trail`, which is the Timeline's rail — so Wrap-up,
     which hangs off no rail, fell through to body size and the same feed read
     at two sizes (user, 2026-08-14). Also what makes `lh` below resolve in the
     row's own type rather than the page's: the rail's arithmetic is all in
     line heights, and it should follow the scale if the scale is retuned. */
  .day {
    font-size: var(--text-small);
  }

  .day:not(:has([data-filter-target="item"]:not([hidden]))),
  .day section:not(:has([data-filter-target="item"]:not([hidden]))) {
    display: none;
  }

  /* ——— The trail ———
     A day's lines hanging off one rail, Basecamp's shape (user, 2026-08-13):
     a line down the start edge with a glyph per row saying what kind of thing
     was touched.

     It REPLACES the hairline between rows rather than joining it — a rule
     under every event and a rail beside them are two grammars doing one job,
     and together they read as a table. `--event-rule` is the property
     events.css leaves for exactly this, so nothing is restated here.

     Ours is ink on paper: BC gives each tool a colour, we give the whole rail
     one weight and let the shapes do the telling. */
  .trail {
    --trail-gutter: 1.75rem;
    --event-rule: none;

    position: relative;
    padding-inline-start: var(--trail-gutter);
  }

  /* Begins at the centre of the FIRST glyph — half a line below the row's own
     top padding — and runs to the foot of the day. Started edge to edge it
     reads as a border on the day rather than as a thread through it; ended at
     the last glyph it would cut the rolled-up subjects loose from the line
     that names them. Basecamp's rail does the same on both counts. */
  .trail::before {
    content: "";
    position: absolute;
    inset-block-start: calc(var(--block-space-half) + 0.5lh);
    inset-block-end: 0;
    inset-inline-start: calc(var(--trail-gutter) / 2);
    inline-size: var(--border-size);
    background-color: var(--color-line);
  }

  .trail .event {
    position: relative;
  }

  /* ——— The clock column ———
     Basecamp puts the time beside the glyph rather than at the end of the
     sentence (user, 2026-08-13), and the row is better for it twice over: the
     sentence now ends on what it is about, and a column of times is scannable
     where a column of trailing stamps was ragged.

     Absolutely positioned like the glyph, for the same reason — the sentence
     is a run of inline nodes, so a grid would make a cell of every fragment of
     it. The gutter grows by exactly the column, which keeps the rail and the
     glyph where they were: both are measured from `.trail`'s edge, and the
     event's own offsets are negative multiples of the same two values. */
  .trail--timed {
    --trail-clock: 3rem;

    padding-inline-start: calc(var(--trail-gutter) + var(--trail-clock));

    .event__time {
      position: absolute;
      inset-block-start: var(--block-space-half);
      inset-inline-start: calc(var(--trail-clock) * -1);
      inline-size: var(--trail-clock);
      font-variant-numeric: tabular-nums;
      color: var(--color-ink-faint);
    }

    .trail__glyph {
      inset-inline-start: calc((var(--trail-gutter) / 2 + var(--trail-clock)) * -1);
    }
  }

  /* Centred on the rail, and exactly one line tall so it masks the rail across
     the line it belongs to — which is what lets the rail be continuous and the
     glyphs sit *on* it rather than beside it. `1lh` resolves against the row's
     own type, so the mark tracks the text if the scale is ever retuned. */
  .trail__glyph {
    position: absolute;
    inset-block-start: var(--block-space-half);
    inset-inline-start: calc(var(--trail-gutter) / -2);
    translate: -50% 0;
    display: grid;
    place-items: center;
    inline-size: 1lh;
    block-size: 1lh;
    color: var(--color-ink-subtle);
    background-color: var(--color-canvas);
  }
}
