Chat Transcript
The small parts every transcript repeats: the day a run of messages belongs to, the clock beside a turn, a human's message with its links made clickable, pictures that open in the lightbox, files that can only be named, and a turn that never reached the server. Assemble them inside message-scroller, message and bubble.
Day divider and timestamp
`startsNewDay(previous, current)` says when to draw the divider, `dayLabelOf` says what it reads: Today, Yesterday, or the date. `ChatTimestamp` is the clock beside a turn, and it never fades: an action you go looking for can hide until hover, context you read cannot.
Text with links
A human's message is text, not markdown. `ChatText` splits it into segments and builds an element for each URL, so whatever someone typed stays text and nothing they wrote is parsed as markup. Trailing punctuation stays with the sentence.
Pictures and file chips
Pictures are shown, not named: `ChatPictures` opens each one in the lightbox. Anything that cannot be drawn - a document, or an image whose bytes are gone - goes through `ChatFileChips`.
Failed turn
A turn that never reached the server keeps the reader's own words where they wrote them, says what went wrong, and offers Retry and Discard. The host owns the message and decides what retrying means.
Unread dot
For a launcher whose panel is shut while something arrived. A dot rather than a count: on a small round button a number needs a size the style guide does not allow for a value, and the next action is the same either way.