@layer components {
  /* The task timeline

     D-14: what was said and what happened are one stream, not two tabs. Only
     comments are on it in 1.0; events join them in M5, which is why the spacing
     belongs to the stream rather than to the comment.

     Deliberately not cards. A card per comment turns a conversation into a stack
     of receipts, and this page already has one raised surface in the notes
     editor. Separation here is space, and a rule only between one person's turn
     and the next — the last resort, per the tokens file. */

  .timeline {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--line);
  }

  .timeline__list { display: flex; flex-direction: column; }

  .timeline__list:has(*) + .timeline__empty { display: none; }

  .timeline__empty {
    color: var(--ink-faint);
    font-size: var(--text-sm);
    max-width: var(--measure);
  }

  .comment {
    display: flex;
    flex-direction: column;
    gap: var(--space);
    padding: var(--space-3) 0;
    border-top: 1px solid var(--line);
  }

  .timeline__list > :first-child .comment,
  .timeline__list > .event:first-child { border-top: 0; padding-top: var(--space); }

  .comment__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    flex-wrap: wrap;
  }

  .comment__author { font-weight: var(--weight-medium); }

  /* Who and when: the name is a person, the timestamp is data, so it is set in
     the mono face like every other thing the system assigned. */
  .comment__meta {
    display: flex;
    align-items: baseline;
    gap: var(--space);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--ink-faint);
    white-space: nowrap;
  }

  .comment__edited { font-style: italic; }

  .comment__body {
    font-size: var(--text-base);
    line-height: var(--leading-body);
    max-width: var(--measure);
    /* A pasted reference or a long URL must not push the page sideways. */
    overflow-wrap: anywhere;
  }

  .comment__body p { margin: 0 0 var(--space); }
  .comment__body p:last-child { margin-bottom: 0; }

  /* Present but recessive, and never a row of buttons: deleting what a
     colleague said should take a deliberate reach, not a stray click on the way
     past. They come forward when the comment is hovered or anything inside it
     has focus, so the keyboard route is never the hidden one. */
  .comment__actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    opacity: 0;
    /* In from the edge they are ranged against, like the pull on a task row —
       the same reveal, so the two read as the same kind of thing being offered
       rather than two components each fading in their own way. */
    translate: var(--space) 0;
    transition: opacity var(--transition), translate var(--transition-enter);
  }

  .comment:hover .comment__actions,
  .comment:focus-within .comment__actions { opacity: 1; translate: none; }

  @media (hover: none) {
    .comment__actions { opacity: 1; translate: none; }
  }

  /* The quiet text button: a label and nothing else. The shortcuts sheet's Close
     is the same treatment, and it used to reach for the comment class to get it —
     which left the comment component owning the look of a button in a dialog it
     knows nothing about. Two names, one rule, neither depending on the other. */
  .comment__action,
  .shortcuts__close {
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--ink-faint);
    background: none;
    border: 0;
    padding: 0;
    min-height: auto;
    cursor: pointer;
    text-decoration: none;
  }

  .comment__action,
  .shortcuts__close { transition: color var(--transition), var(--responds); }

  .comment__action:hover,
  .shortcuts__close:hover { color: var(--ink); text-decoration: underline; }
  .comment__action--danger:hover { color: var(--danger); }

  /* button_to wraps its button in a form, which would otherwise break the row. */
  .comment__actions form { display: contents; }

  /* An event is the record moving rather than somebody talking, so it is set at
     the weight of a caption: one line, the actor's face to hold the column that
     the comments above and below it share, and no rule of its own unless it
     follows a comment. A run of them reads as a margin note down the side of the
     conversation, which is what it is. */
  .event {
    display: grid;
    grid-template-columns: 2.25rem minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space) 0;
    font-size: var(--text-sm);
    color: var(--ink-muted);
  }

  /* Only where the two kinds meet, and never between two events. */
  .comment + .event, .event + .comment, turbo-frame + .event { border-top: 1px solid var(--line); }
  .timeline__list > .event { border-top: 1px solid var(--line); }
  .timeline__list > .event + .event { border-top: 0; }

  .event__line { margin: 0; }
  .event__actor { color: var(--ink); font-weight: var(--weight-medium); }

  /* Something joining the conversation (arrivals_controller)

     A conversation grows downward, so an entry rises into place rather than
     dropping in — the opposite of a task row, and the difference is the point:
     one is a list you are scanning, the other is a thread you are reading, and
     they should not arrive the same way.

     The rule above it fades in with it. Without that the border lands first
     and there is a line across the page for a fifth of a second before there
     is anything under it to separate. */
  @media (prefers-reduced-motion: no-preference) {
    .comment.arriving,
    .event.arriving { animation: timeline-in var(--transition-enter); }
  }

  @media (prefers-reduced-motion: reduce) {
    .comment.arriving,
    .event.arriving { animation: fade-in var(--transition-enter); }
  }

  @keyframes timeline-in {
    from {
      opacity: 0;
      translate: 0 var(--space);
      border-top-color: transparent;
    }
  }

  .event__when {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--ink-faint);
    white-space: nowrap;
  }
}
