/* Playbakk themes (ADDENDUM §1, §4): background motif, message style, corners, density and type, keyed on the
   html attributes web/theme.ts sets — data-theme, data-scheme, data-bg, data-msg, data-radius, data-density — and
   on the conversation DOM contract (ADDENDUM §4). Colours come only from tokens.css. No gradients, no shadows,
   nothing here animates. One curvature (Qlaas language): the corner dial varies around it and is never sharp.
   Owns the look of: .thread (motif + scroller), .thread-col, .msg, .msg-author, .bubble, .msg-time, .day-sep,
   .new-anchor, .marker, .sys-line, .thread-start, the .intent-card chassis. Screen CSS (app.css) builds layout
   around these and must not restyle them; pad .thread-col, never .thread (the motif is sticky to .thread). */

/* Axis values are custom properties, re-based on every themed element (html, previews, theme tiles), so a nested
   preview never inherits the app's overrides. Then the axes, then the per-theme type (later = wins). */
:root, [data-theme] {
  --r-bub: 22px; --r-card: 28px; --r-join: 8px; --r-row: 20px; --r-in: 16px;
  --row-h: 72px; --av-row: 48px; --k-gap: 16px;
  --bub-py: 8px; --bub-px: 16px; --gap-group: 2px; --gap-between: 12px;
  --msg-fs: var(--fs-body); --msg-lh: var(--lh-body);
}
@media (min-width: 760px) { :root, [data-theme] { --r-card: 32px; } }
/* ---- corners ---------------------------------------------------------------------------------------------- */
/* standard is the house curvature (bubble 22 / card 28 → 32); soft is rounder; tight is still soft-cornered */
[data-radius="soft"] { --r-bub: 26px; --r-card: 32px; --r-row: 24px; }
@media (min-width: 760px) { [data-radius="soft"] { --r-card: 36px; } }
[data-radius="tight"] { --r-bub: 16px; --r-card: 20px; --r-join: 6px; --r-row: 16px; --r-in: 12px; }

/* ---- density (SPEC §3.7) ----------------------------------------------------------------------------------- */
[data-density="compact"] {
  --row-h: 56px; --av-row: 32px; --card-pad: 16px; --k-gap: 12px;
  --bub-py: 4px; --bub-px: 12px; --gap-between: 8px;
  --msg-fs: .875rem; --msg-lh: 1.25rem;
}
@media (min-width: 760px) { [data-density="compact"] { --card-pad: 24px; } }

/* ---- type per theme and message style (after density: these win) ----------------------------------------- */
[data-msg="letter"] { --msg-fs: 1.0625rem; --msg-lh: 1.625rem; }
[data-theme="studio"] { --msg-fs: 1.0625rem; --msg-lh: 1.5rem; }
[data-theme="studio"][data-density="compact"] { --msg-fs: 1rem; --msg-lh: 1.375rem; }
[data-theme="editorial"] { --msg-fs: 1.0625rem; --msg-lh: 1.625rem; }
[data-theme="editorial"][data-msg="letter"] { --msg-fs: 1.125rem; --msg-lh: 1.75rem; }
[data-theme="stone"] { --msg-lh: 1.5rem; }                                   /* line-height + 2px */
[data-theme="stone"][data-density="compact"] { --msg-lh: 1.375rem; }
[data-theme="ledger"] .msg-time { font-family: var(--mono); letter-spacing: 0; }   /* the paper trail */
[data-theme="slate"] .receipt { font-family: var(--mono); font-size: var(--fs-mono); line-height: var(--lh-mono); letter-spacing: 0; }
[data-theme="stone"] .crow .av { display: none; }                          /* quiet lists: no avatars */

/* ---- the conversation scroller and its fixed motif ---------------------------------------------------------- */
/* :root-qualified so screen CSS loaded later can't turn the scroller into a padded flex box (the motif needs it plain) */
:root .thread { position: relative; display: block; padding: 0; gap: 0; overflow-y: auto; overscroll-behavior: contain; container: thread / inline-size; }
/* The motif is fixed to the thread viewport (sticky in a viewport-tall grid row the column overlaps): it never scrolls or
   parallaxes, sits behind the column, never in lists or sheets, and is never mirrored in RTL (ticks move to the
   inline-start edge, the brand mark does not flip). Ink: t1 at 3.5 % / mark 3 % (dark), 6 % / 5 % (light); ≤ 4 % dark, ≤ 6 % light by
   contract (amended 6 Oct 2026). */
.thread::before {
  content: none; display: block; position: sticky; inset-block-start: 0; z-index: 0;
  float: inline-start; inline-size: 100%; block-size: 100%; margin-inline-end: -100%; pointer-events: none;
  background-color: var(--pattern);
}
[data-bg="chevron"] .thread::before { content: ""; -webkit-mask: url(brand/chevron-tile.svg) 0 0 / 56px 56px repeat; mask: url(brand/chevron-tile.svg) 0 0 / 56px 56px repeat; }
[data-bg="ruled"] .thread::before { content: ""; -webkit-mask: url(brand/ruled-tile.svg) 0 0 / 8px 28px repeat; mask: url(brand/ruled-tile.svg) 0 0 / 8px 28px repeat; }
[data-bg="dots"] .thread::before { content: ""; -webkit-mask: url(brand/dots-tile.svg) 0 0 / 20px 20px repeat; mask: url(brand/dots-tile.svg) 0 0 / 20px 20px repeat; }
[data-bg="ticks"] .thread::before { content: ""; -webkit-mask: url(brand/ticks-tile.svg) left 0 top 12px / 10px 40px repeat-y; mask: url(brand/ticks-tile.svg) left 0 top 12px / 10px 40px repeat-y; }
[data-bg="ticks"][dir="rtl"] .thread::before { -webkit-mask-position: right 0 top 12px; mask-position: right 0 top 12px; }
[data-bg="ticks"] .thread-col { padding-inline-start: max(var(--col-pad), 24px); }
[data-bg="mark"] .thread::before { content: ""; background-color: var(--pattern-mark); -webkit-mask: url(brand/symbol.svg) center / 40vmin auto no-repeat; mask: url(brand/symbol.svg) center / 40vmin auto no-repeat; }
/* forced flat (theme.ts also resolves bg to plain for these) */
:is([data-theme="night"], [data-theme="contrast"]) .thread::before { content: none; }

/* ---- the reading column ------------------------------------------------------------------------------------- */
.thread-col {
  --col-pad: 16px; --bub-max: min(88%, 560px); --time-w: 2.75rem;
  position: relative; z-index: 1; display: flex; flex-direction: column; inline-size: 100%;
  max-inline-size: var(--col-max, 760px); margin-inline: auto; padding: 12px var(--col-pad) 24px;
}
@container thread (min-width: 600px) { .thread-col { --col-pad: 24px; --bub-max: min(72%, 560px); } }
/* twelve-hour locales write a day-period after the time ("03:48 م", "03:48 pm"): the spacer under it grows with it */
:root:is(:lang(ar), :lang(hi)) .thread-col { --time-w: 3.75rem; }
[data-msg="letter"] .thread-col { --col-max: 620px; }

/* ---- a message row: author line, bubble, time --------------------------------------------------------------- */
.msg {
  display: grid; grid-template-columns: fit-content(var(--bub-max)) auto; grid-template-areas: "a a" "b t";
  justify-content: start; align-items: end; column-gap: 8px; margin-block-start: var(--gap-between);
}
.msg:is([data-pos="mid"], [data-pos="last"]) { margin-block-start: var(--gap-group); }
.msg[data-me="1"] { grid-template-columns: auto fit-content(var(--bub-max)); grid-template-areas: "a a" "t b"; justify-content: end; }
.msg-author { grid-area: a; font-size: var(--fs-body-s); line-height: var(--lh-body-s); font-weight: var(--w-heading); color: var(--t1); }
.msg[data-me="1"] .msg-author { text-align: end; }
/* visually hidden except in transcript, letter (first of a group) and groups (.thread[data-group]) */
.msg-author, .msg:is([data-pos="mid"], [data-pos="last"]) .msg-author {
  position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.thread[data-group] .msg[data-me="0"]:is([data-pos="first"], [data-pos="single"]) .msg-author { position: static; inline-size: auto; block-size: auto; clip-path: none; color: var(--t2); margin: 0 var(--bub-px) 2px; }

.bubble {
  grid-area: b; min-inline-size: 0; max-inline-size: 64ch; padding: var(--bub-py) var(--bub-px);
  border-radius: var(--r-bub); background: var(--bub-them); color: var(--t1);
  font-size: var(--msg-fs); line-height: var(--msg-lh); font-weight: var(--w-body); letter-spacing: var(--tr-body);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.msg[data-me="1"] .bubble { background: var(--bub-me); color: var(--bub-me-t); }
/* grouping: the joined corners on the author's side tighten (logical, so RTL follows) */
.msg[data-me="0"][data-pos="first"] .bubble { border-end-start-radius: var(--r-join); }
.msg[data-me="0"][data-pos="mid"] .bubble { border-start-start-radius: var(--r-join); border-end-start-radius: var(--r-join); }
.msg[data-me="0"][data-pos="last"] .bubble { border-start-start-radius: var(--r-join); }
.msg[data-me="1"][data-pos="first"] .bubble { border-end-end-radius: var(--r-join); }
.msg[data-me="1"][data-pos="mid"] .bubble { border-start-end-radius: var(--r-join); border-end-end-radius: var(--r-join); }
.msg[data-me="1"][data-pos="last"] .bubble { border-start-end-radius: var(--r-join); }

/* time: micro tnum. On the last bubble of a group it sits inside the bubble at the inline-end of the last line
   (an inline spacer reserves its room, so it never covers text); elsewhere it waits beside the bubble and shows on
   hover/focus (opacity only: it keeps its room, nothing reflows, screen readers always read it). */
.msg-time {
  grid-area: t; align-self: end; padding-block-end: 2px; opacity: 0; white-space: nowrap;
  font-size: var(--fs-micro); line-height: var(--lh-micro); font-weight: var(--w-body); font-variant-numeric: tabular-nums; color: var(--t3);
}
.msg:hover .msg-time, .msg:focus-within .msg-time { opacity: 1; }
.msg:is([data-pos="last"], [data-pos="single"]) .msg-time { grid-area: b; justify-self: end; opacity: 1; padding: 0; margin: 0 var(--bub-px) calc(var(--bub-py) + 1px); pointer-events: none; position: relative; }
.msg:is([data-pos="last"], [data-pos="single"]) .bubble::after { content: ""; display: inline-block; inline-size: var(--time-w); block-size: 1px; }
.msg[data-me="1"]:is([data-pos="last"], [data-pos="single"]) .msg-time { color: var(--inv-t2); }

/* tonal: both tonal, mine one step further from the ground; my time is t2 (never opacity) */
[data-msg="tonal"] .msg[data-me="1"] .bubble { background: var(--bub-tonal); color: var(--t1); }
[data-msg="tonal"] .msg[data-me="1"]:is([data-pos="last"], [data-pos="single"]) .msg-time { color: var(--t2); }

/* outline: theirs is a 1 px control line on the ground, mine filled */
[data-msg="outline"] .thread-col { --gap-group: 4px; }
[data-msg="outline"] .msg[data-me="0"] .bubble { background: transparent; border: 1px solid var(--ctl); padding: calc(var(--bub-py) - 1px) calc(var(--bub-px) - 1px); }

/* transcript: no bubbles. Author + time line, then the text, full width; mine carry a 2 px t1 rail at
   inline-start. The rail is continuous through a group (padding, not margin, between grouped rows). */
[data-msg="transcript"] .thread-col { --gap-between: 16px; }
[data-msg="transcript"][data-density="compact"] .thread-col { --gap-between: 12px; }
[data-msg="transcript"] .msg { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "a t" "b b"; justify-content: stretch; align-items: baseline; padding-inline-start: 12px; }
[data-msg="transcript"] .msg:is([data-pos="mid"], [data-pos="last"]) { grid-template-areas: "b t"; margin-block-start: 0; padding-block-start: var(--gap-group); }
[data-msg="transcript"] .msg[data-me="1"] { padding-inline-start: calc(12px - 2px); border-inline-start: 2px solid var(--t1); }
/* an intent card in a transcript spans the column; its author line keeps the text indent */
[data-msg="transcript"] .thread-col > .msg[data-kind="intent"] { padding-inline-start: 0; }
[data-msg="transcript"] .thread-col > .msg[data-kind="intent"] .msg-author { margin-inline-start: 12px; }
[data-msg="transcript"] .msg:is([data-pos="first"], [data-pos="single"]) .msg-author { position: static; inline-size: auto; block-size: auto; clip-path: none; text-align: start; margin-block-end: 2px; }
[data-msg="transcript"] .msg[data-me] .bubble { background: none; color: var(--t1); padding: 0; border-radius: 0; max-inline-size: 72ch; }
[data-msg="transcript"] .msg .bubble::after { content: none; }
[data-msg="transcript"] .msg[data-me] .msg-time { grid-area: t; opacity: 1; margin: 0; padding: 0; justify-self: end; color: var(--t3); }
[data-msg="transcript"] .msg[data-me]:is([data-pos="mid"], [data-pos="last"]) .msg-time { opacity: 0; }
[data-msg="transcript"] .msg[data-me]:is([data-pos="mid"], [data-pos="last"]):is(:hover, :focus-within) .msg-time { opacity: 1; }

/* letter: a centred 620 px reading column, larger type; theirs is plain text under the author line, mine filled */
[data-msg="letter"] .thread-col { --gap-between: 24px; }
[data-msg="letter"] .msg[data-me="0"] { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "a t" "b b"; justify-content: stretch; align-items: baseline; }
[data-msg="letter"] .msg[data-me="0"]:is([data-pos="mid"], [data-pos="last"]) { grid-template-areas: "b t"; margin-block-start: 8px; }
[data-msg="letter"] .msg[data-me="0"]:is([data-pos="first"], [data-pos="single"]) .msg-author { position: static; inline-size: auto; block-size: auto; clip-path: none; margin-block-end: 4px; }
[data-msg="letter"] .msg[data-me="0"] .bubble { background: none; padding: 0; border-radius: 0; max-inline-size: 64ch; }
[data-msg="letter"] .msg[data-me="0"] .bubble::after { content: none; }
[data-msg="letter"] .msg[data-me="0"] .msg-time { grid-area: t; justify-self: end; opacity: 1; margin: 0; padding: 0; }
[data-msg="letter"] .msg[data-me="0"]:is([data-pos="mid"], [data-pos="last"]) .msg-time { opacity: 0; }
[data-msg="letter"] .msg[data-me="0"]:is([data-pos="mid"], [data-pos="last"]):is(:hover, :focus-within) .msg-time { opacity: 1; }
[data-msg="letter"] .msg[data-me="1"] { --bub-max: 85%; }

/* Contrast: filled, with visible boundaries on every container */
[data-theme="contrast"] .bubble { border: 1px solid var(--line); padding: calc(var(--bub-py) - 1px) calc(var(--bub-px) - 1px); }
[data-theme="contrast"][data-msg="transcript"] .bubble, [data-theme="contrast"][data-msg="letter"] .msg[data-me="0"] .bubble { border: 0; padding: 0; }
[data-theme="contrast"] :is(.intent-card, .kcard) { border: 1px solid var(--line); }

/* ---- non-text rows: intent cards and system lines are never restyled by the message style ------------------- */
.thread-col > .msg:is([data-kind="intent"], [data-kind="system"]) .bubble { background: none; border: 0; padding: 0; border-radius: 0; max-inline-size: none; color: var(--t1); white-space: normal; }
.thread-col > .msg:is([data-kind="intent"], [data-kind="system"]) .bubble::after { content: none; }
.thread-col > .msg[data-me]:is([data-kind="intent"], [data-kind="system"]) .msg-time { grid-area: t; opacity: 0; margin: 0; padding: 0; }
.thread-col > .msg[data-me]:is([data-kind="intent"], [data-kind="system"]):is(:hover, :focus-within) .msg-time { opacity: 1; }
.thread-col > .msg[data-kind="intent"] { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "a t" "b b"; justify-content: stretch; inline-size: 100%; max-inline-size: 640px; border: 0; }
.thread-col > .msg[data-kind="intent"][data-me="1"] { margin-inline-start: auto; }
.thread-col > .msg[data-me][data-kind="intent"] .msg-time { opacity: 1; justify-self: end; margin-block-end: 4px; }
.thread-col > .msg[data-kind="system"] { grid-template-columns: minmax(0, 1fr); grid-template-areas: "b"; justify-content: center; padding-inline-start: 0; border: 0; }
.thread-col > .msg[data-kind="system"] .msg-time { display: none; }
.intent-card { display: grid; gap: 16px; padding: var(--card-pad); border-radius: var(--r-card); background: var(--card); color: var(--t1); font-size: var(--fs-body); line-height: var(--lh-body); text-align: start; }
.sys-line {
  margin: 8px auto; max-inline-size: 48ch; text-align: center; color: var(--t3);
  font-size: var(--fs-body-s); line-height: var(--lh-body-s); letter-spacing: var(--tr-body-s);
}

/* ---- markers in time ---------------------------------------------------------------------------------------- */
.day-sep, .new-anchor {
  display: flex; align-items: center; justify-content: center; gap: 8px; margin: 24px 0 12px;
  font-size: var(--fs-label); line-height: var(--lh-label); font-weight: var(--w-label); letter-spacing: var(--tr-label); text-transform: uppercase;
  font-variant-numeric: tabular-nums; color: var(--t2);
}
.new-anchor { color: var(--t1); }
/* scrolled to (the unread anchor, a day): leave the header's shadow of room above it */
.day-sep, .new-anchor { scroll-margin-block-start: 16px; }
/* brass = "you are here in time"; one per screen, never the only cue (the label says "New") */
.marker { flex: none; inline-size: 6px; block-size: 6px; border-radius: 50%; background: var(--marker); }

.thread-start { display: grid; justify-items: center; gap: 4px; max-inline-size: 400px; margin: 0 auto 16px; padding-block-start: 48px; text-align: center; }
.thread-start .ts-name { font-size: var(--fs-title); line-height: var(--lh-title); font-weight: var(--w-title); letter-spacing: var(--tr-title); }
.thread-start .ts-meta { font-size: var(--fs-body-s); line-height: var(--lh-body-s); color: var(--t2); }
.thread-start .ts-proof { font-size: var(--fs-micro); line-height: var(--lh-micro); color: var(--t3); }
